jQuery hover не запускается, когда элемент программно перемещается под мышкой

У меня есть изображение с эффектом наведения (более высокая непрозрачность при наведении указателя мыши на него). Он работает по желанию, когда мышь двигается внутрь и наружу.

Однако само изображение движется (периодически меняю атрибут css top). Когда мышь не перемещается, а изображение перемещается под курсором мыши, никакие связанные события не запускаются. Это означает, что функции зависания не вызываются. Я также пробовал использовать вместо них события mouseenter и mouseleave, но они тоже не работают.

Что было бы хорошим подходом для получения желаемого поведения (эффект наведения при наведении курсора мыши на изображение, независимо от того, почему оно туда попало)?


person travelboy    schedule 09.12.2010    source источник
comment
Интересный вопрос, но мои подозрения напрасны. Тем не менее, +1 за хороший вопрос.   -  person Alastair Pitts    schedule 10.12.2010
comment
как насчет эффектов наведения CSS?   -  person rcravens    schedule 10.12.2010
comment
только что проверено, и эффекты наведения CSS в этой ситуации тоже не работают.   -  person rcravens    schedule 10.12.2010


Ответы (4)


Вы не сможете запускать события мыши, если мышь не движется, хотя вы сможете проверить, где находится мышь, когда изображение движется. Что вам нужно сделать, так это отслеживать положение мыши в глобальной переменной и проверять, находится ли эта позиция внутри вашего изображения при его перемещении.

В jQuery есть хорошая статья о том, как это сделать с помощью их библиотеки: http://docs.jquery.com/Tutorials:Mouse_Position

Чтобы узнать положение вашего изображения, вы можете использовать функцию положения jQuery: http://api.jquery.com/position/

С этой позицией вы можете создать границы, используя высоту / ширину вашего изображения. При перемещении изображения проверьте, находится ли эта глобальная позиция мыши внутри границ вашего изображения, и все должно быть в порядке.

Вот как я бы написал код (полностью непроверенный, кстати):

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...
  }
});
person wajiw    schedule 09.12.2010
comment
Я надеялся, что есть более элегантный способ сделать это, но, видимо, его нет. Спасибо за отличный и подробный ответ. Я реализовал это так, с одним улучшением: теперь я также отслеживаю в локальной переменной, зависает ли изображение уже или нет. Таким образом, я могу запускать события только после того, как мышь входит или выходит (в вашем коде секция непрозрачности выполняется все время, пока изображение перемещается под мышью). Это позволяет мне делать анимацию непрозрачности без постоянного их повторного запуска. - person travelboy; 10.12.2010
comment
Замечательно, рад, что смог помочь. Готов поспорить, вашу реализацию можно превратить в плагин jQuery, чтобы сделать его более элегантным решением для других пользователей. - person wajiw; 10.12.2010
comment
Это отличное решение, но, к сожалению, в вашем решении есть множество опечаток, что означает, что на самом деле это не работает. Ниже я выложу рабочее решение. - person Matthew O'Riordan; 26.10.2011
comment
@ matthew-oriordan Я написал это вслепую, поэтому перед ним было написано (полностью непроверено, кстати) =) пользователю просто нужно было направление, а не код, написанный для него - person wajiw; 26.10.2011

Вы можете вручную проверить, находится ли мышь в изображении при перемещении изображения, а затем запустить желаемое событие.

Положение мыши с использованием jQuery вне событий покажет вам, как отслеживать позиции мыши. Затем просто найдите смещение изображения и посмотрите, находится ли оно внутри изображения.

person Ryan    schedule 09.12.2010

В дополнение к ответам wajiw и ryan вы должны запускать события mouseenter и mouseleave, когда вы обнаруживаете, что указатель мыши находится над / не над изображением, так что любой код, который вы связали с .hover(), все еще выполняется:

$(".my-image").trigger("mouseenter");
$(".my-image").trigger("mouseleave");
person David Tang    schedule 09.12.2010

@wajiw опубликовал отличное решение, но, к сожалению, оно страдает опечатками, что означает, что оно не будет работать сразу после того, как вы его исправите.

Вот класс, который вы можете использовать, который протестирован и работает, что позволит вам проверить, находится ли объект под курсором мыши.

Определение класса

// 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;
    }
  }
}

Пример использования

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

Надеюсь, это поможет.

Я мог бы очень легко превратить это в плагин jQuery, если кто-то этого захочет, просто напишите мне, и я продолжу.

Мэтт

person Matthew O'Riordan    schedule 26.10.2011