미래의 마우스 포인터 트레일을 표시하십시오!


24

d3js 를 사용 하는 이 예제 에서 영감을 얻어 마우스 포인터 트레일 이 표시 되는 캔버스 (또는 선택한 언어와 동일)를 다음과 같이 변형하여 작성해야합니다.

트위스트

당신은 마우스 포인터 곳의 산책로 표시되지해야 했다 , 그러나이 곳의 "산책로" 것입니다 미래에 일 (수를).

다음 중 하나를 사용하여 수행 할 수 있습니다.

  1. 타임머신

  2. 이전 마우스 움직임을 기반으로 한 확률 적 추정

가정

타임머신 구현을 선택하지 않은 경우 마우스가 임계 값 밀리 초 이상 움직이지 않으면 트레일을 표시 할 수 없습니다. ( 임계 값을 선택할 수 있습니다.)

커서 이미지는 사용자에게 달려 있으며 OS 커서와 같을 필요는 없습니다 (일반적인 작은 원이나 점을 그릴 수도 있음).

악의 입력이 테스트되지 않습니다. 움직임이 원활하다고 가정 할 수 있습니다. 이 경우의 '부드러운'정의는 마우스 움직임이 캔버스의 x 및 y 축에 대한 함수 인 경우 연속적인 함수입니다.

승리

코드에서 문자가 가장 적은 유효한 답이 이길 것입니다. 동점 인 경우-처음 게시 된 동점이 이길 것입니다.

편집 : 가장 많은 투표 를 가진 유효한 답변 이 이길 것입니다. 동점 인 경우-처음 게시 된 동점이 이길 것입니다. 구현에서 생성하거나 예측을 통해 정확할 수 있습니다. 나는 더 이상 판사가 아니야, 우리 모두는 :)

  • 유효한 답변에는 온라인 도구 또는 무료로 다운로드 할 수있는 컴파일러 / 인터프리터 / 런타임 등에서 플레이 할 수있는 방법이 포함되어야합니다.

2
나는이 질문이 코드 골프보다 인기 경연 대회에 더 적합 할 것이라고 생각한다. 왜냐하면 그것은 충분히 좋은 예측으로서의 자격에 대해 상당히 주관적이기 때문이다. 태그를 명확히하거나 태그를 변경하는 것이 좋습니다. 그럼에도 불구하고 재미있어 보인다.
— isaacg

2
네가 옳아. 질문을 편집하고 태그를 변경했습니다.
— Jacob

누군가가 기계 학습 알고리즘을 구현할 시간입니다!
— Ingo Bürk

6
테스트를 위해 어떤 타임머신 모델에 액세스 할 수 있습니까? 표준 라이브러리를 사용하여 인터페이스 할 수 있습니까?
— 피터 테일러

1
여기에서 징징 거리는 수학자 : smooth! = 연속. 실제로 거친 스파이크 움직임은 계속 지속될 것입니다.
— CompuChip

답변:


33

자바 스크립트

내 프로그램은 마지막 20 개의 마우스 이동 방향의 각도 변화의 평균을 사용하여 포인터의 방향을 예측합니다. 또한 각도 변화의 분산을 사용하여 포인터의 가능한 위치와 방향의 "구름"을 만듭니다. "구름"에있는 각 포인터의 색상은 마우스 포인터의 새로운 위치 일 가능성을 나타내며, 어두운 색상은 더 큰 가능성을 나타냅니다. 마우스 앞의 포인터 구름 거리는 마우스 이동 속도를 사용하여 계산됩니다. 최상의 예측은 아니지만 깔끔하게 보입니다.

바이올린이 있습니다 : http://jsfiddle.net/5hs64t7w/4/

포인터 구름의 크기를 늘리는 것은 흥미로운 일입니다. cloudSize프로그램의 첫 번째 줄 에서 변수를 변경하여 설정할 수 있습니다 . 다음은 구름 크기가 10 인 바이올린입니다. http://jsfiddle.net/5hs64t7w/5/

이 소스를 사용하여 원형 평균 및 분산에 대한 공식을 얻었습니다.
원형 평균 : http://en.wikipedia.org/wiki/Circular_mean
원형 분산 : http://www.ebi.ac.uk/thornton-srv/software/ PROCHECK / nmr_manual / man_cv.html

관심이 있다면 다음 코드를 작성하십시오.

    var cloudSize = 3;

    var canvas = document.getElementById('canvas_element');
    var c = canvas.getContext('2d');
    var prevX = -1;
    var prevY = -1;
    var curX = -1;
    var curY = -1;
    var distance = 0;
    var direction = 0;

    function drawMouse(x, y, angle, gray){
        var grayVal = Math.round(gray*255);
        var grayString = "rgb(" + grayVal + "," + grayVal +"," + grayVal + ")";
        c.fillStyle = grayString;
        c.strokeStyle = grayString;
        c.lineWidth = 1;
        c.beginPath();
        c.moveTo(x, y);
        c.lineTo(x + 16*Math.cos(angle + Math.PI/2.0 + Math.PI/8.0), y + 16*Math.sin(angle + Math.PI/2.0 + Math.PI/8.0));
        c.moveTo(x, y);
        c.lineTo(x + 16*Math.cos(angle + Math.PI/2.0 - Math.PI/8.0), y + 16*Math.sin(angle + Math.PI/2.0 - Math.PI/8.0));
        c.lineTo(x + 16*Math.cos(angle + Math.PI/2.0 + Math.PI/8.0), y + 16*Math.sin(angle + Math.PI/2.0 + Math.PI/8.0));
        c.stroke();
        c.fill();
        c.beginPath();
        c.moveTo(x, y);
        c.lineTo(x + 24*Math.cos(angle + Math.PI/2), y + 24*Math.sin(angle + Math.PI/2));
        c.stroke();
    }

    function sum(array){
        var s = 0.0;
        for(var i=0; i<array.length; i++){
            s += array[i];
        }
        return s;
    }

    var sins = [];
    var coss = [];
    var lengths = [];
    var times = [];
    var index = 0;
    var limit = 20;
    var variance = 0;
    var prevTime = new Date().getTime();
    function updateDistanceAndDirection(x, y){
        var angle = Math.atan2(prevY - curY, prevX - curX);
        sins[index] = Math.sin(angle);
        coss[index] = Math.cos(angle);
        lengths[index] = Math.sqrt((curX-prevX)*(curX-prevX) + (curY-prevY)*(curY-prevY));
        var time = new Date().getTime();
        times[index] = time - prevTime;

        variance = 1.0 - Math.sqrt(sum(coss)*sum(coss)+sum(sins)*sum(sins))/sins.length;

        direction = Math.atan2(1/sins.length*sum(sins),1/coss.length*sum(coss));
        var speed = sum(lengths)/(sum(times)/200);
        distance = Math.min(Math.max(40, speed), 100);
        prevTime = time;
        index = (index+1)%limit;
    }

    function drawMice(count){
        c.clearRect(0, 0, canvas.width, canvas.height);

        for(var i=count; i>=0; i--){
            var dir = direction + i*variance;
            drawMouse(curX - distance*Math.cos(dir), curY - distance*Math.sin(dir), dir - Math.PI/2, i/count);
            dir = direction - i*variance;
            drawMouse(curX - distance*Math.cos(dir), curY - distance*Math.sin(dir), dir - Math.PI/2, i/count);
        }
    }

    canvas.onmousemove = function (event) {
        curX = event.clientX;
        curY = event.clientY;

        updateDistanceAndDirection(curX, curY);

        drawMice(cloudSize);

        prevX = curX;
        prevY = curY;
    };

2
가변 방향을 가리키는 포인터 대신 일련의 마우스 포인터 (고정 된 방향으로)를 표시 할 수 있습니까? 나는 "마우스 트레일"을 볼 것으로 예상했지만 아무것도 볼 수 없습니다. haha
— justhalf

매우 훌륭하지만 현재 포인터가 내려갈 때 포인터가 올라가는 것이 더 타당하지 않습니까? Imho, 프로그램은 포인터가 화면에 머무르는 것을 예측할 수 있도록 정확히 반대의 작업을 수행해야합니다.
— Madmenyo

@ MennoGouw 완벽하지는 않지만 그저 꽤 좋은
— NimChimpsky

@nimchimpsky 마우스가 현재 내려 가면 마우스가 올라갈 확률이 높다고 말하는 것입니다. 프로그램 자체는 훌륭합니다.
— Madmenyo

마우스 처리를 위해 일반적인 인간 행동을 사용하는 것이 가능하다고 생각하십니까? 원, 직선처럼 ... 다음은 (몇 쥐흐 mesures 후 원의 반지름을 계산하고, 원을 마무리 당신이 그것을 초안도 전에) 미래에 더욱 예측 될 수있다
— 사프란

14

자바

나는 타임머신 접근을하기로 결정했다. 타임 머신의 주요 구성 요소는 java.awt.Robot입니다. 내 프로그램을 사용하면 마우스를 10 초 동안 움직일 수 있습니다. 10 초 후에는 시간이 지남에 따라 마우스 움직임을 재현하면서 완벽하게 예측합니다.

여기에 이미지 설명을 입력하십시오

코드는 다음과 같습니다.

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.TimerTask;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;


public class TimeMachine extends JPanel implements MouseMotionListener {

    Timer timer;
    int time = 10;
    java.util.Timer taskTimer;
    ArrayList<Point> mousePoints;
    ArrayList<Long> times;
    Robot robot;
    int width, height;
    ArrayList<Point> drawMousePoints;

    public TimeMachine(){
        width = 500;
        height = 500;
        drawMousePoints = new ArrayList<Point>();

        robot = null;
        try{
            robot = new Robot();
        }
        catch(Exception e){
            System.out.println("The time machine malfunctioned... Reverting to 512 BC");
        }
        mousePoints = new ArrayList<Point>();
        times = new ArrayList<Long>();

        taskTimer = new java.util.Timer();

        ActionListener al = new ActionListener(){
            public void actionPerformed(ActionEvent e){
                time--;
                if(time == 0)
                    rewind();
                repaint();
            }
        };
        timer = new Timer(1000, al);
        start();
    }

    public void paint(Graphics g){
        g.clearRect(0, 0, width, height);
        g.drawString("Time Machine activiates in: " + time, 15, 50);
        for(int i=0; i<drawMousePoints.size(); i++){
            Point drawMousePoint = drawMousePoints.get(i);
            drawMouse(drawMousePoint.x-getLocationOnScreen().x, drawMousePoint.y-getLocationOnScreen().y, g, Color.BLACK, Color.LIGHT_GRAY, (double)i/drawMousePoints.size());
        }
    }

    public void drawMouse(int x, int y, Graphics g, Color line, Color fill, double alpha){
        Graphics2D g2d = (Graphics2D)g;
        g2d.setColor(new Color(fill.getRed(), fill.getGreen(), fill.getBlue(), (int)Math.max(Math.min(alpha*255, 255), 0)));
        g2d.fillPolygon(new int[]{x, x, x+4, x+8, x+10, x+7, x+12}, new int[]{y, y+16, y+13, y+20, y+19, y+12, y+12}, 7);

        g2d.setColor(new Color(line.getRed(), line.getGreen(), line.getBlue(), (int)Math.max(Math.min(alpha*255, 255), 0)));
        g2d.drawLine(x, y, x, y + 16);
        g2d.drawLine(x, y+16, x+4, y+13);
        g2d.drawLine(x+4, y+13, x+8, y+20);
        g2d.drawLine(x+8, y+20, x+10, y+19);
        g2d.drawLine(x+10, y+19, x+7, y+12);
        g2d.drawLine(x+7, y+12, x+12, y+12);
        g2d.drawLine(x+12, y+12, x, y);
    }

    public void start(){
        timer.start();
        prevTime = System.currentTimeMillis();
        mousePoints.clear();
    }

    public void rewind(){
        timer.stop();
        long timeSum = 0;
        for(int i=0; i<times.size(); i++){
            timeSum += times.get(0);
            final boolean done = i == times.size()-1;
            taskTimer.schedule(new TimerTask(){
                public void run(){
                    Point point = mousePoints.remove(0);
                    drawMousePoints.clear();
                    drawMousePoints.addAll(mousePoints.subList(0, Math.min(mousePoints.size(), 30)));
                    robot.mouseMove(point.x, point.y);
                    repaint();
                    if(done)
                        System.exit(0);
                }
            }, timeSum);
        }
    }

    long prevTime = 0;
    public void record(MouseEvent m){
        if(timer.isRunning()){
            long time = System.currentTimeMillis();
            mousePoints.add(new Point(m.getXOnScreen(), m.getYOnScreen()));
            times.add((time-prevTime)/10);
            prevTime = time;
        }
    }

    public static void main(String[] args){

        TimeMachine timeMachine = new TimeMachine();

        JFrame frame = new JFrame("Time Machine");
        frame.setSize(timeMachine.width, timeMachine.height);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.addMouseMotionListener(timeMachine);

        frame.add(timeMachine);
    }

    public void mouseDragged(MouseEvent m) {
        record(m);
    }

    public void mouseMoved(MouseEvent m) {
        record(m);
    }

}

: 코드는 약간 넷빈즈 (경고 제거되었다)에 의해 최적화 pastebin.com/E57LZ4zY
— 카즈 울프

10

바닐라 자바 ​​스크립트

일을 시작하기 위해 두 가지 값을 기반으로 한 간단한 예측이 있습니다. 마지막 n마우스 위치는 기억되고 큐에 보관되며, 예측은 큐의 첫 번째 요소와 마지막 요소의 간단한 선형 외삽입니다.

이것은 단지 예측 코드이며 데모를 포함한 전체 코드는 다음과 this fiddle같습니다.

function predict(trail) {
    var b = trail.pop(),
        a = trail[0],
        d = {
            x: b.x - a.x,
            y: b.y - a.y
        },
        m = Math.sqrt( d.x * d.x + d.y * d.y );

    d.x = 5 * d.x / m;
    d.y = 5 * d.y / m;

    var predictions = [];
    for(var i = 1; i <= 10; i++) {
        predictions.push({
            x: b.x + i * d.x,
            y: b.y + i * d.y
        });
    }

    return predictions;
}

데모에는 예측에 주석이 포함되어있어 예측을 위해 대기열에서 마지막 두 요소를 대신 사용할 수 있습니다. 결과를 "실시간"으로 만들지 만 "부드럽게"줄입니다.

누구나 boilerplate work예측 알고리즘 을 사용하여 다른 예측 알고리즘을 구현 하려는 경우 자유롭게 느끼십시오. 어쨌든 많은 일이 아닙니다.


선 대신 마우스 포인터를 표시 할 수 있습니까? 나는 하하, "마우스 포인터 자국"을 참조하십시오 기대했지만 어떤을 볼 수 없습니다
— justhalf

) 문제는 커서 일 필요는 없습니다 말한다
— 잉고 버크

4

자바 스크립트

과거는 미래를위한 최고의 예측입니다. 저와 다른 사람도 가능합니다

내 솔루션은 매우 간단합니다. 먼저 >>> Fiddle입니다! <<<

그것이하는 것은 과거의 흔적을 바꾸는 것이므로 미래의 흔적처럼 보입니다. 기본적으로 수학은 관여하지 않습니다 (I Know, 꽤 지루합니다). 특히 커서를 원으로 움직일 때 오류를 쉽게 볼 수 있습니다. 그래서 트레일을 너무 짧게 만들었습니다.)

코드:

<!DOCTYPE html>
<html>
    <head>
        <style type="text/css">
            .cursor {
                width: 12px;
                height: 19px;
                position: absolute;
                background-image: url(https://i.imgur.com/h8imKBP.png);
            }
        </style>
        <script type="text/javascript">

            var x, y;
            window.onmousemove = function(e) {x=e.clientX; y=e.clientY;}

            var p = [0,0,0,0,0,0,0,0,0,0];
            window.setInterval(function() {
                p.shift();
                p.push([x, y]);
                var diff = [x-p[0][0], y-p[0][1]];
                for (var i = 0; i < 10; i++) {
                    var e = document.getElementById(i);
                    e.style.left = (p[9-i][0]+diff[0])+"px";
                    e.style.top = (p[9-i][1]+diff[1])+"px";
                }
            }, 10);

        </script>
    </head>
    <body>
    <div id="0" class="cursor"></div>
    <div id="1" class="cursor"></div>
    <div id="2" class="cursor"></div>
    <div id="3" class="cursor"></div>
    <div id="4" class="cursor"></div>
    <div id="5" class="cursor"></div>
    <div id="6" class="cursor"></div>
    <div id="7" class="cursor"></div>
    <div id="8" class="cursor"></div>
    <div id="9" class="cursor"></div>
    </body>
</html>

하하 나는 방금 날짜를 보았습니다. 어쨌든, 나는 그것을 좋아
— Felk
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.