0

I just want to preface this post with the disclaimer that I am a beginner with javascript/jquery and would really appreciate it if explanations/examples came slow :)

Editing the post to narrow the question for clarity: I want a HTML element to follow your cursor only if the cursor is hovering it; once the cursor "leaves" the element, I want the element to discontinue its following.

So far I have found code (from both w3schools: https://www.w3schools.com/jquery/event_hover.asp and another post on StackOverflow: how to animate following the mouse in jquery) to implement the "follow cursor" feature and to make it so that this occurs only once the cursor hovers an element: https://jsfiddle.net/rtwrtw8/og7ej0n8/

$(document).ready(function(){
  $("#follower").hover(function(){
    var mouseX = 0, mouseY = 0;
$(document).mousemove(function(e){
   mouseX = e.pageX;
   mouseY = e.pageY; 
});

// cache the selector
var follower = $("#follower");
var xp = 0, yp = 0;
var loop = setInterval(function(){
    // change 12 to alter damping higher is slower
    xp += (mouseX - xp) / 12;
    yp += (mouseY - yp) / 12;
    follower.css({left:xp, top:yp});
    
}, 30);
    }, function(){
    $(this).css("background-color", "pink");
  });
});
#follower{
  position : absolute;
  background-color : red;
  color : white;
  padding : 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="follower">Starts following once hovers</div>

The issue, however, is that the box continues to follow the cursor even if the cursor is no longer hovering over the element (which is confirmed by the box turning pink, as specified in the code). Instead, the box should just stay in the position when the cursor was last hovering over it.

If anyone has any suggestions as to how to implement this feature or knows of any working examples, I would greatly appreciate it! Thanks in advance!

2 Answers2

0

Once you start listening to mouseMove you need to stop listening using off('mousemove') when mouse leaves the element

Try changing:

$(this).css("background-color", "pink");

To

$(this).off('mousemove').css("background-color", "pink");

You should also clear the interval using clearInterval(intervalId) also

charlietfl
  • 170,828
  • 13
  • 121
  • 150
  • Thanks for the reply and for the explanation -- totally makes sense! However, I added the line and it appears that the .off('mousemove') is not stopping the element from listening. What could be preventing this from working properly? –  Mar 30 '19 at 19:11
  • Just saw your `clearInterval(intervalId)` addition. Sorry to trouble you further but I was wondering if you could explain a little bit more about what's going on with the interval and why/how we need to clear it? –  Mar 30 '19 at 19:23
  • https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Loops_and_intervals MDN is about the best javascript documentation resource around – charlietfl Mar 30 '19 at 21:19
0

I would suggest something along these lines:

mouseover event handler: set insideObject = true
mouseout event handler: set insideObject = false
mousemove event handler: if (insideObject) then do the 'follower' action (otherwise do nothing)

I don't think an interval timer is appropriate for this in the first place.

<style>
#myrect
{
 height:100px;
 width:100px;
 background-color:lightblue;
 position:absolute;
 left: 200;
 top: 200;
}
</style>

<div id=myrect> 
  XYZ
</div>

<script>
var following=false;
function gotIn()
{
 following = true;
 setDark();
}
function gotOut()
{
 following = false;
 setLight();
}
function moved(e)
{
 if (!following) return;
 var x = e.pageX;
 var y = e.pageY;
 var r = document.getElementById("myrect");
 r.style.left = x - 10;
 r.style.top = y - 10;
}
function setDark()
{
 document.getElementById("myrect").style.backgroundColor = "#00f";
}
function setLight()
{
 document.getElementById("myrect").style.backgroundColor = "lightblue";
}

document.getElementById("myrect").addEventListener('mousemove', moved, false);
document.getElementById("myrect").addEventListener('mouseover', gotIn, false);
document.getElementById("myrect").addEventListener('mouseout', gotOut, false);
</script>
T G
  • 445
  • 3
  • 7
  • Thanks for the comment! From my understanding, the interval is used to modify the speed at which the HTML element follows your cursor. If the element follows you at default (?) speed, I think it would be impossible for your cursor to ever "leave" the element. –  Mar 31 '19 at 06:11
  • I coded up an example, and yes - if you move the mouse slowly, it's hard to 'leave' the object - it takes a quick swipe.to 'escape'. (I put the cursor 10 x 10 pixels away from the corner to that end.) A way around that is only do the following if the mouse button is down, but in your app you might not want to do that. – T G Mar 31 '19 at 07:21
  • Ahh I see what you mean now. Thank you so much for outlining it with the example code -- very helpful and works perfectly! –  Mar 31 '19 at 19:09
  • Hey sorry, just one more thing: I'm getting a "Uncaught (in promise) TypeError: Cannot read property 'split' of undefined" error in the console when I try running your code. I tried looking this error up and most of the results dealt with text (which seems unrelated). I was wondering if you know why this might be occurring? –  Mar 31 '19 at 20:26
  • Edit: here's the fiddle for your code: https://jsfiddle.net/rtwrtw8/gh49r710/ I can't seem to always replicate the error (sometimes the console shows no error) but the animation doesn't work properly. –  Mar 31 '19 at 20:45
  • Both problems ( error related to split(), which I don't use) and the lack of animation) are probably related to the jsfiddle environment. I suggest just putting the code into a standalone html document (which you can do on your own computer, and then open in a browser.) I have done a version tracking mousedown and mouseup, and that is much more user friendly. – T G Apr 02 '19 at 01:54