Capturing Cursor Speed with jQuery

I’ve been playing around with the canvas element lately, and I came up with a few fun ideas that would require capturing the speed of the User’s cursor movements. I looked around a little and only found a few bare scripts here and there, so I decided to package the logic into a jQuery plug-in called Cursometer.

How to Use

Using Cursometer is easy. Simply include the core jQuery library (1.6.2+) and the Cursometer plug-in script (minified):

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script src="script/jquery.cursometer.1.0.0.js"></script>

And then hook up Cursometer to an element:

$('canvas').cursometer();

Now Cursometer will start tracking the speed of the User’s cursor movements whenever they move their mouse over the canvas elements on the page. You can retrieve the User’s cursor speed at any time with the getCurrentSpeed function:

var currSpeed = $('canvas').cursometer('getCurrentSpeed');

The speed is measured in pixels per milliseconds.

Options

Cursometer provides a few options to let you customize the behavior of the plug-in:

$('canvas').cursometer({
	onUpdateSpeed: function(speed) { },
	updateSpeedRate: 20
);

The onUpdateSpeed is a callback function that is called whenever the plug-in polls the User’s cursor movements for calculating speed. The User’s current cursor speed is passed as the first parameter. Thus, if you have something that is dynamically controlled by the speed of the User’s cursor movements, you would want to put the logic for updating that dynamic piece within this function. Check out this example, in which the speed of your cursor determines how fast Mario runs.

On a related note, the updateSpeedRate controls how often (in milliseconds) the plug-in polls (or checks) the User’s cursor movements. The higher the number, the more accurate the measurement but the lower the performance. The default value is 20 milliseconds.

Behind the Scenes

This plug-in was a little trickier to write than I originally anticipated because I ended up needing two polling loops: one for continuously checking the User’s cursor speed (controlled by the updateSpeedRate described above) and another for checking the the current position of the User’s mouse (controlled by a secret option called captureMouseMoveRate). The reason for this second loop was to create an adhoc event that would capture the User’s cursor position, without pounding the DOM with an unnecessary and relentless series of mousemove events (I got the idea from this Stackoverflow article).

  • Sorin

    how can i display directly the mouse speed using this plugin?

  • Logan

    Sorin, I created a jsFiddle demonstrating how you would accomplish that: http://jsfiddle.net/edUVs/ Let me know if that’s what you needed!

  • Sorin

    This is what I was searching for. Thanks Logan!

  • Logan

    I want to extend and improve this plug-in (I’ll probably put it up on GitHub), so please let me know if there’s anything you want me to add/improve. Thanks!

  • lluis

    Is there any way to detect the coordinates speed (only X or only Y) ?

    thanks Logan

  • lluis

    Well, i guess that was a stupid question. I supose the direction can be resolved using other js/jquery tools. Thanks for sharing your effort 🙂 i’m trying to implement your code in the big zoom picture product in motocross.es

  • Pingback: Detect mouse speed using jQuery | Technology & Programming Answers()

  • Fred

    sir logan what is the unit of measurement used in the sample that you gave? thankyou sir

  • Logan

    Hey Fred! The “speed” value that is fed into the “onUpdateSpeed” callback is pixels/milliseconds. Hope that helps!

  • sharayu

    hey, logan
    how can i display speed of cursor of user in numbers in m/s.
    Means, i want the changing speed of user on a single webpage.

  • Logan

    Hey Sharayu! Does this JSFiddle (http://jsfiddle.net/edUVs/) do what you need? “Meters per second” won’t really work with this plug-in (we would need to do some extra logic to try and calculate the actual physical width of the viewing device). Would “pixels per milliseconds” work for you?

  • Harmen Meijer

    Hi Logan, I’ve been trying to get the speed measurement (speedometer.text(speed)) readout on (http://jsfiddle.net/edUVs/) to become more ‘relaxed’. So Instead of updating the value every 20 milliseconds I would like it to update say only twice per second. I’ve also tried averaging out the last 10 measurements but that didn’t help much. The parameter updateSpeedRate doesn’t seem to do anything. Values like .01 or 10000 make no difference to the readout. Do you have any ideas?

  • loganfranken

    Hey @harmenmeijer:disqus! Sorry for the late response!

    Unfortunately, there’s a bug where updateSpeedRate isn’t actually getting used by the plug-in. However, there is a secret option (captureMouseMoveRate) that I think should do what you want:
    http://jsfiddle.net/edUVs/71/

    Let me know if that does the trick for you!

    (And sorry for the confusion with this plug-in: hopefully I’ll get a chance in the near future to loop back and clean it up a little)

  • Harmen Meijer

    Hi Logan, Yes, that works better indeed. Thanks! I’m almost there. What strikes me is that after I stop moving the mouse the value never returns to zero. Is that because without mouse movement there’s no event triggered? And to fire the event I need to move the mouse again. I’ve had a look at your plugin code but can’t see a solution as I don’t fully understand how it works. Can you point me in the right direction? Thank you.

  • loganfranken

    Hey @harmenmeijer:disqus! Sorry again for another late response (I was traveling):

    Actually, someone fixed up the very problem you’re describing in a recent pull request. Here’s a new fiddle with the URL updated to the latest version: http://jsfiddle.net/edUVs/73/

  • Harmen Meijer

    Hi Logan, That solution works! Thanks a bunch. Maybe you have a suggestion for the following problem: the plugin was designed for mouse movements. However, I need to track drag speed on mobile platforms as well. I’m not sure if your plugin can be adapted to work with both.

  • loganfranken

    Hey @harmenmeijer:disqus !

    I’ll have to think more about whether or not this is in scope for the core plug-in, but I created a version that uses touch events:
    https://github.com/loganfranken/Cursometer/blob/mobile/script/jquery.cursometer.1.0.0.js

    Here’s a JS Fiddle:
    http://jsfiddle.net/edUVs/74/

    Let me know if that works for you!

  • Harmen Meijer

    Hi Logan, Whether in or out of scope, I’m happy with it! Works like a charm. Thank you for this update! Cheers, Harmen