Как остановить прыгучую анимацию JQuery?

В веб-приложении, над которым я работаю, я хочу создать несколько слайдеров div, которые будут перемещаться вверх и вниз с помощью наведения и удаления мыши (соответственно). В настоящее время я реализовал его с помощью функции hover() JQuery, используя animate(). и уменьшая/увеличивая его значение top css по мере необходимости. Это работает довольно хорошо, на самом деле.

Проблема в том, что он имеет тенденцию застревать. Если вы наведете на него указатель мыши (особенно внизу) и быстро удалите его, он будет непрерывно скользить вверх и вниз и не остановится, пока не завершит 3-5 циклов. Мне кажется, что проблема может быть связана с тем, что одна анимация запускается до завершения другой (например, две пытаются бежать, поэтому они скользят вперед и назад).

Хорошо, теперь о коде. Вот базовый JQuery, который я использую:

$('.slider').hover(
    /* mouseover */
    function(){
        $(this).animate({
            top : '-=120'
        }, 300);
    },
    /* mouseout*/
    function(){
        $(this).animate({
            top : '+=120'
        }, 300);
    }
);

Я также воссоздал поведение в JSFiddle.

Любые идеи о том, что происходит? :)

== РЕДАКТИРОВАТЬ == ОБНОВЛЕНО JSFiddle


person Miguel    schedule 04.06.2012    source источник
comment
Кажется, он скользит вверх и вниз только один раз для меня, когда я быстро удаляю его на скрипке.   -  person Hunter McMillen    schedule 04.06.2012
comment
Когда вы наводите курсор на innerContent, он перемещается вверх, таким образом, он больше не находится под мышью, вызывая событие mouseleave, заставляющее его анимироваться обратно в исходное положение. Что вы на самом деле пытаетесь сделать?   -  person Kevin B    schedule 04.06.2012
comment
@ Кевин, проблема, о которой он говорит, заключается в том, что иногда, когда вы наводите указатель мыши на ползунок только один раз, анимация выполняет несколько циклов, то есть несколько раз поднимается и опускается.   -  person sv_in    schedule 04.06.2012
comment
@sv_in Верно, но это вызвано тем, что div анимируется из-под мыши, вызывая событие выхода, которое, в свою очередь, снова запускает событие ввода, когда оно анимируется, а затем снова уходит, вызывая цикл.   -  person Kevin B    schedule 04.06.2012
comment
@KevinB Ты прав. Однако в реальной реализации div имеет height достаточно большой, чтобы не срабатывал mouseleave. Я обновил JSFiddle, чтобы отразить это.   -  person Miguel    schedule 04.06.2012
comment
Попробуйте это, все, что я добавил, это .stop(true,true), чтобы предотвратить резервное копирование очереди анимации. jsfiddle.net/W5EsJ/18   -  person Kevin B    schedule 04.06.2012
comment
@KevinB Если вы быстро наведете курсор снизу вверх, он иногда будет двигаться вперед и назад так быстро, что мигает.   -  person Miguel    schedule 04.06.2012
comment
Я не думаю, что вы можете что-то с этим поделать. Выполняя это действие мыши, вы неоднократно наводите курсор на div и выходите из него, действие jQuery в этом случае имеет смысл.   -  person Kevin B    schedule 04.06.2012
comment
@KevinB Тогда хорошо. Хотя это и не так эффектно, как мне бы хотелось, ваша идея работает хорошо, и это единственное предложение, которое не приводит к тому, что div исчезает из поля зрения. Если бы вы опубликовали это как ответ, я был бы более чем счастлив принять его.   -  person Miguel    schedule 04.06.2012
comment
Смотрите мой обновленный ответ, я решил мерцание.   -  person Kevin B    schedule 04.06.2012


Ответы (5)


Это не идеально, но добавление .stop(true,true) предотвратит большую часть того, что вы видите.

http://jsfiddle.net/W5EsJ/18/

Если вы быстро наведете курсор снизу вверх, он все равно будет мерцать, потому что вы перемещаете мышь из div, вызывая срабатывание события mouseout, анимируя div обратно вниз.

Вы можете уменьшить мерцание, уменьшив задержку, однако оно все равно будет присутствовать до тех пор, пока задержка не станет равной 0 (без анимации).

Обновить

Я подумал и понял, что есть очевидное решение. Hoverintent-подобная функциональность!

http://jsfiddle.net/W5EsJ/20/

$(document).ready(function() {
    var timer;
    $('.slider').hover(
        /* mouseover */
        function(){
            var self = this;
            timer = setTimeout(function(){
                $(self).stop(true,true).animate({
                    top : '-=120'
                }, 300).addClass('visible');
            },150)
        },
        /* mouseout*/
        function(){
            clearTimeout(timer);
            $(this).filter(".visible").stop(true,true).animate({
                top : '+=120'
            }, 300).removeClass("visible");
        }
    );
});
person Kevin B    schedule 04.06.2012
comment
Потрясающий! Я просто хотел бы +1 немного больше. В любом случае, спасибо! :) - person Miguel; 05.06.2012

Вы можете использовать .stop(), а также использовать позицию внешнего контейнера

$(document).ready(function() {
    $('.slider').hover(
        /* mouseover */
        function(){
            $(this).stop().animate({
                    top : $('.outer').position().top
            }, 300);
        },
        /* mouseout*/
        function(){
            $(this).stop().animate({
                top : $('.outer').position().top + 120
            }, 300);
        }
    );
});
​

ДЕМО

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

person Dhiraj    schedule 04.06.2012
comment
В вашей демонстрации, похоже, проблема с отскоком исправлена, но она имеет тенденцию ускользать из поля зрения... :P - person Miguel; 04.06.2012
comment
обновил демо. заметил, что положение ползунка является относительным, поэтому используемое положение внешнего контейнера может помочь в текущей ситуации - person Dhiraj; 04.06.2012

Не удалось воспроизвести вашу проблему, но я считаю, что hover вызывается несколько раз. Чтобы обойти это, вы можете проверить, находится ли div уже в анимации. Если да, то не запускайте еще одну анимацию.

Добавьте следующий фрагмент кода, чтобы проверить, анимируется ли уже div:

if ($(this).is(':animated')) {
   return;
}

Код: http://jsfiddle.net/W5EsJ/2/
Ссылка: http:/ /api.jquery.com/анимированный-селектор/

person sv_in    schedule 04.06.2012
comment
Кажется, что он анимируется вне поля зрения вашей скрипки - person Kevin B; 04.06.2012

Проблему понял и воспроизвел, бывает при наведении снизу вверх. Наведение курсора мыши является причиной проблемы, поскольку функция анимации будет вызываться при наведении указателя мыши на изображение. Вам нужно контролировать то, что здесь происходит, с помощью ввода и отпускания мыши, посмотрите аналогичный пример: Jquery Animate on Наведите

person AGE    schedule 04.06.2012

Причина этого в том, что наведение ставится в очередь, заставляя его скользить вверх и вниз несколько раз. Есть плагин под названием hoverIntent, который решает эту проблему. http://cherne.net/brian/resources/jquery.hoverIntent.html

Если вы решите использовать hoverIntent, единственное, что вам нужно изменить в своем коде, это .hover > .hoverIntent.

person wirey00    schedule 04.06.2012