简体   繁体   中英

Mouseover and mouseout not firing with animating element

I need to detect if a user is hovering over an element, which is straightforward. However, these events don't seem to fire when the element is animating. If you check out my fiddle, just have the element animate past your mouse without moving your mouse, and you'll see that the events don't fire. It makes sense why this would happen, but I haven't been able to find a good way to get the behavior I want, which is to detect hovering even if the user doesn't move his/her mouse and the element animates under it.

Any thoughts?

Thanks!

Note: solutions without use of external libraries are optimal, but any help is still appreciated :)

HTML

<div id='moving'></div>
<ul id="message"></ul>

CSS

#moving {
  width: 50px;
  height: 50px;
  background-color: red;
  animation: move 7s linear;
}

@keyframes move {
    from {transform: translateX(0px)}
    to {transform: translateX(500px)}
}

JS

var counter = 0;

document.getElementById("moving").addEventListener("mouseover", function(){
    counter++;
    var node = document.createElement("LI");
    var textnode = document.createTextNode("Entered " + counter);
    node.appendChild(textnode);
    document.getElementById("message").appendChild(node);
});

document.getElementById("moving").addEventListener("mouseout", function(){
    var node = document.createElement("LI");
    var textnode = document.createTextNode("Left " + counter);
    node.appendChild(textnode);
    document.getElementById("message").appendChild(node);
});

Here's a fiddle of it: https://jsfiddle.net/w5j842Lx/

You can check if the mouse is in or out within an interval. Here is a working fiddle extending from your fiddle.

 // This is the helper method I have written var addMoveListener = function(element, onmouseover, onmouseout) { var over = false; var mouseX, mouseY; var checkOver = function(ev) { if (ev) { mouseX = ev.clientX; mouseY = ev.clientY; } if (mouseX == null || mouseY == null) return; var rect = element.getBoundingClientRect(); var isInside = mouseX >= rect.left && mouseX < rect.right && mouseY >= rect.top && mouseY < rect.bottom; if (over && !isInside && onmouseout) onmouseout(); if (!over && isInside && onmouseover) onmouseover(); over = isInside; } document.addEventListener("mousemove", checkOver); var interval = setInterval(checkOver.bind(null, null), 100); } // Code below is for the sake of demonstration var counter = 0; var mouseovercallback = function() { counter++; console.log("Entered " + counter); }; var mouseoutcallback = function() { console.log("Left " + counter); }; addMoveListener(document.getElementById("moving"), mouseovercallback, mouseoutcallback); 
 #moving { width: 50px; height: 50px; background-color: red; animation: move 7s linear; } @keyframes move { from { transform: translateX(0px) } to { transform: translateX(500px) } } 
 <div id='moving'></div> 

The code checks if the mouse is contained for every 100 miliseconds and also if the mouse is moved. If you want to handle cases where the element is not a rectangle or is rotated, skewed etc., you have to improve the code.

Take a look at this jsfiddle https://jsfiddle.net/3vpaoj59/ It includes a function like this

  setInterval(checkMouse, 100);

that basically calls a function 10 times a second to check if the mouse's coordinates are within the animated shape. Your shape is a square and not a circle, so you would have to do some different math. This code is nice because it doesn't use a plugin, but it's probably CPU intensive and might have poor performance in some cases.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM