Rolando
Rolando

Reputation: 62704

Realistic mouse movement coordinates in javascript?

In javascript, is there a way I can create a variable and a function that "simulates" smooth mouse movement? i.e., say the function simulates a user starts from lower left corner of the browser window, and then moves mouse in a random direction slowly...

The function would return x and y value of the next position the mouse would move each time it is called (would probably use something like setInterval to keep calling it to get the next mouse position). Movement should be restricted to the width and height of the screen, assuming the mouse never going off of it.

What I don't want is the mouse to be skipping super fast all over the place. I like smooth movements/positions being returned.

Upvotes: 5

Views: 4424

Answers (3)

Kaiido
Kaiido

Reputation: 137113

A "realistic mouse movement" doesn't mean anything without context :

Every mouse user have different behaviors with this device, and they won't even do the same gestures given what they have on their screen.

If you take an FPS game, the movements will in majority be in a small vertical range, along the whole horizontal screen.
Here is a "drip painting" I made by recording my mouse movements while playing some FPS game.

If we take the google home page however, I don't even use the mouse. The input is already focused, and I just use my keyboard.

On some infinite scrolling websites, my mouse can stay at the same position for dozens of minutes and just go to a link at some point.

I think that to get the more realistic mouse movements possible, you would have to record all your users' gestures, and repro them.

Also, a good strategy could be to get the coordinates of the elements that will attract user's cursor the more likely (like the "close" link under SO's question) and make movements go to those elements' coordinates.

Anyway, here I made a snippet which uses Math.random() and requestAnimationFrame() in order to make an object move smoothly, with some times of pausing, and variable speeds.

// Canvas is here only to show the output of  function
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
document.body.appendChild(canvas);
var maxX = canvas.width = window.innerWidth;
var maxY = canvas.height = window.innerHeight;

window.onresize = function(){  
  maxX = canvas.width = window.innerWidth;
  maxY = canvas.height = window.innerHeight;
  }
gc.onclick = function(){
  var coords = mouse.getCoords();
  out.innerHTML = 'x : '+coords.x+'<br>y : '+coords.y;
  }

var Mouse = function() {
  var that = {},
    size = 15,
    border = size / 2,
    maxSpeed = 50, // pixels per frame
    maxTimePause = 5000; // ms

  that.draw = function() {
    if (that.paused)
      return;
    that.update();
    // just for the example
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    if(show.checked){
      ctx.drawImage(that.img, that.x - border, that.y - border, size, size)
      }
    // use requestAnimationFrame for smooth update
    requestAnimationFrame(that.draw);
  }

  that.update = function() {
    // take a random position, in the same direction
    that.x += Math.random() * that.speedX;
    that.y += Math.random() * that.speedY;
    // if we're out of bounds or the interval has passed
    if (that.x <= border || that.x >= maxX - border || that.y <= 0 || that.y >= maxY - border || ++that.i > that.interval)
      that.reset();
  }
  that.reset = function() {
    that.i = 0; // reset the counter
    that.interval = Math.random() * 50; // reset the interval
    that.speedX = (Math.random() * (maxSpeed)) - (maxSpeed / 2); // reset the horizontal direction
    that.speedY = (Math.random() * (maxSpeed)) - (maxSpeed / 2); // reset the vertical direction
    // we're in one of the corner, and random returned farther out of bounds
    if (that.x <= border && that.speedX < 0 || that.x >= maxX - border && that.speedX > 0)
    // change the direction
      that.speedX *= -1;
    if (that.y <= border && that.speedY < 0 || that.y >= maxY - border && that.speedY > 0)
      that.speedY *= -1;
    // check if the interval was complete
    if (that.x > border && that.x < maxX - border && that.y > border && that.y < maxY - border) {
      if (Math.random() > .5) {
        // set a pause and remove it after some time
        that.paused = true;
        setTimeout(function() {
          that.paused = false;
          that.draw();
        }, (Math.random() * maxTimePause));

      }
    }
  }

  that.init = function() {
    that.x = 0;
    that.y = 0;
    that.img = new Image();
    that.img.src ="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAABJUlEQVRIic2WXbHEIAyFI6ESKgEJkVIJlYCTSqiESIiESqiEb19gL9Od3f5R5mbmPPHwBTgnIPJfChiAGbCkCQgtG7BpmgAWIALaDDyOI2bGuq40BasqIoKZATgwNAWHEEjHbkBsBhYRVJUYIwBNwVlFaVOwiDDPMylmQ1OwquY7d0CBrglYkuEeidoeOKt61I6Cq0ftKFhqR+0MOKuo2BQsInnndvnOr4JvR+0qWO5G7Q44K0XtOXDf96jqh9z9WXAy1FJ8l0qd+zbtvU7lWs7wIzkuh8SvpqqDi3zGndPQauDkzvdESm8xZvbh4mVZ7k8ud/+aR0C3YPk7mVvgkCZPVrdZV3dHVem6bju1roMPNmbAmq8kG+/ynD7ZwNsAVVz9dL0AhBrZq7F+CSQAAAAASUVORK5CYII=";
    that.reset();
  }
  that.getCoords = function(){
    return {x: that.x, y:that.y};
  }
  that.init()
  return that;
}
var mouse = new Mouse()
mouse.draw();
html,body {margin: 0}
canvas {position: absolute; top:0; left:0;z-index:-1}
#out{font-size: 0.8em}
<label for="show">Display cursor</label><input name="show" type="checkbox" id="show" checked="true"/><br>
<button id="gc">get cursor Coords</button>
<p id="out"></p>

Upvotes: 6

cronoklee
cronoklee

Reputation: 6722

Having something smoothly follow the cursor is quite straight forward. You may be able to reverse this process to achieve what you need. Here's a code snippet which simply calculates the distance between the cursor and a div every frame and then moves the div 10% of that distance towards the cursor:

http://jsfiddle.net/hpp0qb0d/

var p = document.getElementById('nextmove')
var lastX,lastY,cursorX,cursorY;

window.addEventListener('mousemove', function(e){
    cursorX = e.pageX;
    cursorY = e.pageY;
})
setInterval(function(){
    var newX = p.offsetLeft + (cursorX - lastX)/10
    var newY = p.offsetTop + (cursorY - lastY)/10

    p.style.left = newX+'px'
    p.style.top = newY+'px'

    lastX = p.offsetLeft
    lastY = p.offsetTop
},20)

Upvotes: 0

ojrask
ojrask

Reputation: 2828

Last I heard the browser's mouse position cannot be altered with JavaScript, so the question really has no answer "as is". The mouse position can be locked though. I'm not certain whether it would be possible to implement a custom cursor that allows setting the position. This would include hiding and perhaps locking the stock cursor.

Upvotes: 0

Related Questions