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


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.