Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculating mouse velocity with accuracy

Tags:

javascript

I made a little script intended to output the speed at which the mouse moves. The issues I am having is that occasionally the script will output an inaccurate number among the numbers and throw the whole thing off. As well, the script does not always terminate when the user releases the mouse button. To solve the first issue I assume I could probably place the values into an array and then determine the outlier, but I'm hoping somebody here can just tell me I'm doing something stupid and there is a way to fix my code to make it more efficient.

JS:

var test_obj = {
    mouse_coors: function(x2) {

        $(document).on("mousemove", function(e) {
            var x = e.clientX,
            velocity = Math.abs(x-x2);

            console.log(velocity);
            $(document).off("mousemove");

            setTimeout(function() {
                x2 = e.clientX;
                test_obj.mouse_coors(x2);
            }, 100);
        });

        $(document).on("mouseup", function() {
            $(document).off("mouseup").off("mousemove");
        });
    },
};


$(document).ready(function() {

    $('#testbox').on("mousedown", function() {
        test_obj.mouse_coors(0);
    });

});

HTML:

JSfiddle: http://jsfiddle.net/mkb2t/

like image 816
tom c Avatar asked Dec 08 '22 14:12

tom c


1 Answers

Simply because that is not the velocity of the mouse. What you currently are counting is how far the mouse moved in x-direction. That's called distance.

The inaccuracy you experience might both stem from ignoring the y-direction and the inaccuracy of setTimeout - use Date timestamps.

Also, you are building a cascade of mousemove handlers (which not only is incorrect but bad efficiency-wise). On every event (and they're quite often!) you are waiting 0.1s and then add a new listener that will output on every event from then how far the mouse moved since the first event. Another issue is that you're calling the mouse_coors function with a value of 0 when the mouse is pressed, yet the mouse hardly will be there.

Better: Store the current coordinates of the mouse globally. Every time when you will update them, compute the difference and divide that by the time that passed since last update. Then log the velocity.

function makeVelocityCalculator(e_init, callback) {
    var x = e_init.clientX,
        y = e_init.clientY,
        t = Date.now();
    return function(e) {
        var new_x = e.clientX,
            new_y = e.clientY,
            new_t = Date.now();
        var x_dist = new_x - x,
            y_dist = new_y - y,
            interval = new_t - t;
        var velocity = Math.sqrt(x_dist*x_dist+y_dist*y_dist)/interval;
        callback(velocity);
        // update values:
        x = new_x;
        y = new_y;
        t = new_t;
    };
}
$(document).ready(function() {
    $('#testbox').on("mousedown", function(e) {
        var log = makeVelocityCalculator(e, function(v) {
            console.log(v+"pixel/ms");
        });
        $(document).on("mousemove", log).one("mouseup", function(){
            $(document).off("mousemove", log);
        });
    });
});

updated fiddle

like image 65
Bergi Avatar answered Dec 11 '22 08:12

Bergi