6

I have an image with a hover effect (higher opacity when mouse is over it). It works as desired when the mouse moves in and out.

However, the image itself is moving (I'm periodically changing the css attribute top). When the mouse does not move and the image moves under the mouse cursor, no related events are triggered. That means, the hover functions are not called. I also tried using the mouseenter and mouseleave events instead, but they don't work either.

What would be a good approach to get the desired behavior (hover effect whenever the mouse is over the image, regardless of why it got there)?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
travelboy
  • 2,647
  • 3
  • 27
  • 37

4 Answers4

8

You won't be able to trigger mouse events if the mouse isn't moving, though you will be able to check where the mouse is when the image is moving. What you need to do is track the mouse position in a global variable, and check to see if that position is inside your image when it moves.

jQuery has a nice article about how to do it using their library: http://docs.jquery.com/Tutorials:Mouse_Position

To find the position of your image you can use the jQuery position function: http://api.jquery.com/position/

With that position you can create a bounds using the height/width of your image. On your image move check to see if that global mouse position is inside your image bounds and you should be good to go.

This is how I would write the code(completely untested btw):

var mousex = 0;
var mousey = 0;

jQuery(document).ready(function(){
   $(document).mousemove(function(e){
      mousex = e.pageX;
      mousey = e.pageY;
   }); 
})

img.move(function(){
  ...move code...
  var p = $(this).position();
  if(mousex >= p.left && mousex <= p.left + $(this).width
     && mousey <= p.top && mousey >= p.top + $(this).height)
  {
   ...opacity code...
  }
});
wajiw
  • 12,239
  • 17
  • 54
  • 73
  • I was hoping there is a more elegant way to do it, but apparently there isn't. Thank you for this excellent and detailed answer. I implemented it like this with one improvement: I am now also keeping track in a local variable whether the image is already being hovered or not. This way, I can only fire events once the mouse enters or leaves (in your code the opacity section is executed all the time while the image is moving under the mouse). This allows me to do opacity animations without constantly re-triggering them. – travelboy Dec 09 '10 at 23:17
  • Awesome, glad I could help. I bet your implementation could be turned into a jQuery plugin to make it a more elegant solution for other users. – wajiw Dec 09 '10 at 23:27
  • This is a great solution, but unfortunately you have a bunch of typos in your solution meaning this does not actually work. I will post a working solution below. – Matthew O'Riordan Oct 26 '11 at 10:40
  • @matthew-oriordan I wrote it blind, which is why it was prefaced with (completely untested btw) =) the user just needed direction, not the code actually written for him – wajiw Oct 26 '11 at 15:48
2

You could manually test to see if the mouse is in the image when you move the image then fire the desired event.

Mouse position using jQuery outside of events will show you how to keep track of the mouse position. Then just find the offset of the image and see if it's inside the image.

Community
  • 1
  • 1
Ryan
  • 4,602
  • 8
  • 37
  • 43
2

In addition to wajiw's and ryan's answers, you should trigger the mouseenter and mouseleave events as you detect that the mouse is over/not over the image, so that whatever code you bound to .hover() is still executed:

$(".my-image").trigger("mouseenter");
$(".my-image").trigger("mouseleave");
David Tang
  • 92,262
  • 30
  • 167
  • 149
1

@wajiw has posted a great solution, but unfortunately it's plagued with typos meaning it won't work out of the box until you fix it.

Here is a class you can use which is tested and works which will allow you to test if an object is under the mouse.

Class definition

// keeps track of recent mouse position and provides functionality to check if mouse is over an object
// useful for when nodes appear underneath the mouse without mouse movement and we need to trigger hover
// see http://stackoverflow.com/questions/4403518
function MouseTracker($) {
  var mouseX, mouseY;

  $(document).mousemove(function(e) {
    mouseX = e.pageX;
    mouseY = e.pageY;
  });

  return {
    isOver: function(node) {
      var p = $(node).offset();
      if (mouseX >= p.left && mouseX <= p.left + $(node).width()
         && mouseY >= p.top && mouseY <= p.top + $(node).height())
      {
        return true;
      }
      return false;
    }
  }
}

Usage example

var mouseTracker = new MouseTracker(jQuery);
if (mouseTracker.isOver($('#my-object-in-question'))) {
  $('#my-object-in-question').trigger("mouseenter");
}

Hope that helps.

I could make this into a jQuery plugin very easily if anyone wants it, just drop me a line and I'll go ahead.

Matt

Matthew O'Riordan
  • 7,981
  • 4
  • 45
  • 59