Attemping to get a div to "follow" the cursor on mousemove, but with a delay

I want to create an effect similar to the old mouse paths where the div lingers but follows the cursor.

I came close enough, using the given interval to start the animation at the cursor coordinates.

$("body").mousemove(function (e) { if (enableHandler) { handleMouseMove(e); enableHandler = false; } }); timer = window.setInterval(function(){ enableHandler = true; }, 250); function handleMouseMove(e) { var x = e.pageX, y = e.pageY; $("#cube").animate({ left: x, top: y }, 200); } 

Jsfiddle

Now there are two problems:

  • The 'chasing' gap is very unstable (due to the required use of the given interval)

  • If the mouse movement stops before starting the animation, the div remains in place, away from the cursor.

+8
javascript jquery
source share
5 answers

I did it a little differently. Instead of using setInterval (or even setTimeout ) - I just made the animation take x milliseconds. The longer the animation, the less responsive the next div will be.

The only problem that I notice is that the backup is done if the mouse is moving a lot.

 $(document).ready(function () { $("body").mousemove(function (e) { handleMouseMove(e); }); function handleMouseMove(event) { var x = event.pageX; var y = event.pageY; $("#cube").animate({ left: x, top: y }, 1); } }); 

https://jsfiddle.net/jvmravoz/1/

+5
source share

Remove SetInterval and add $ ("# cube"). stop (); to stop the old animation based on the old (x, y) so you can start a new "faster" one.

 $(document).ready(function() { $("body").mousemove(function (e) { $("#cube").stop(); handleMouseMove(e); }); function handleMouseMove(event) { var x = event.pageX, y = event.pageY; $("#cube").animate({ left: x, top: y }, 50); } }); 

Working example https://jsfiddle.net/jabnxgp7/

+4
source share

Here is a solution that can mimic the mouse paths a little more, because it only remembers the last 100 positions and discards the old ones that specify the length of the mouse cable.

https://jsfiddle.net/acmvhgzm/6/

 $(document).ready(function() { var pos = new Array(); $("body").mousemove(function (e) { handleMouseMove(e); }); timer = window.setInterval(function() { if (pos.length > 0) { $('#cube').animate(pos.shift(),15); } }, 20); function handleMouseMove(event) { var x = event.pageX, y = event.pageY; if (pos.length = 100) { pos.shift(); } pos.push({'left':x, 'top':y}); } }); 
+1
source share

Try removing setInterval using .css() , css transition

 $(document).ready(function () { var cube = $("#cube"); $("body").mousemove(function (e) { handleMouseMove(e); }); function handleMouseMove(event) { var x = event.pageX, y = event.pageY; cube.css({ left: x + cube.width() / 2 + "px", top: y + cube.height() / 2 + "px" }).parents("body").mousemove() } }); 
 body { overflow:hidden; position:absolute; height:100%; width:100%; background:#efefef; } #cube { height:50px; width:50px; margin-top:-25px; margin-left:-25px; background:red; position:absolute; top:50%; left:50%; transition:all 1.5s ease-in-out; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <div id="container"> <div id="cube"></div> </div> 
0
source share

The old mouse track function used a list of several windows in the form of cursors that updated their positions with each frame. In fact, he had a list of “cursors”, and each subsequent “cursor” of a frame in the list moved to the current cursor position, as a result of which each fake cursor updated its own position with a frame delay of fake cursors - 1 .

Smooth on-demand delayed movement for a single object can be modeled using requestAnimationFrame , performance.now and Event.timeStamp . The idea is to store mouse events in an internal list and only use them after a certain time after they are created.

 function DelayLine(delay, action){ capacity = Math.round(delay / 1000 * 200); this.ring = new Array(capacity); this.delay = delay; this.action = action; this._s = 0; this._e = 0; this._raf = null; this._af = this._animationFrame.bind(this); this._capacity = capacity; } DelayLine.prototype.put = function(value){ this.ring[this._e++] = value; if (this._e >= this._capacity) this._e = 0; if (this._e == this._s) this._get(); cancelAnimationFrame(this._raf); this._raf = requestAnimationFrame(this._af); } DelayLine.prototype._get = function(){ var value = this.ring[this._s++]; if (this._s == this._capacity) this._s = 0; return value; } DelayLine.prototype._peek = function(){ return this.ring[this._s]; } DelayLine.prototype._animationFrame = function(){ if (this._length > 0){ if (performance.now() - this._peek().timeStamp > this.delay) this.action(this._get()); this._raf = requestAnimationFrame(this._af); } } Object.defineProperty(DelayLine.prototype, "_length", { get: function() { var size = this._e - this._s; return size >= 0 ? size : size + this._capacity; } }); var delayLine = new DelayLine(100, function(e){ pointer.style.left = ex - pointer.offsetWidth/2 + "px"; pointer.style.top = ey - pointer.offsetHeight/2 + "px"; }); document.addEventListener("mousemove", function(e){ delayLine.put(e); }, false); 

https://jsfiddle.net/os8r7c20/2/

0
source share

All Articles