Простая анимация наведения DIV

Я использую animate() анимировать тег DIV слева, когда указатель находится над DIV. И когда указатель покидает тег DIV, он возвращается в исходное положение. Проблема здесь заключается в том, что анимация перемещает тег DIV на 50 пикселей влево при наведении мыши и на 50 пикселей влево при отпускании мыши.

Это заставит DIV переместиться на 50 пикселей вправо, даже если анимация не завершена.

$('body').on('mouseenter', '.image-photo-previous', function() {
    $(this).animate({marginLeft: '-=50px'}, 300, 'swing');
});

$('body').on('mouseleave', '.image-photo-previous', function() {
    $(this).animate({marginLeft: '+=50px'}, {queue: false}, 300, 'swing');
});

http://jsfiddle.net/edgren/CubZy/

Как сделать так, чтобы тег DIV анимировался обратно в исходное положение, даже если анимация не завершена при отпускании мыши?

5 ответов

Решение

(Без JS!) Вы можете сделать это с помощью CSS3 transition:

ДЕМО (только CSS)

.image-photo-previous {
    background-color: #222222;
    height: 100px;
    width: 200px;
    transition: 0.3s;         /* Transition! */
}
.image-photo-previous:hover{
    margin-left: -50px;
}

Используя jQuery:

LIVE DEMO

$(".image-photo-previous").on('mouseenter mouseleave', function( e ) {
    $(this).stop().animate({marginLeft: e.type=="mouseenter"?-50:0}, 300);
});

.stop() метод будет предотвращать некоторые уродливые анимации, и с небольшим Ternary Operator (?:) ты на правильном пути.

Ваш пример не соответствует вашим потребностям, потому что на любом новом событии вы возились с некоторыми новыми дополнительными вычислениями маржи (для бесконечной анимации) из-за += а также -= которые были добавлены к текущему стилю DIV, что привело к неправильным позициям элементов, особенно при быстром перемещении мыши. stop() очищает это поведение и все, что вам нужно, это строго определить позиции: -50 а также 0 и привязать их к текущему событию.

Попробуй это:

$(document).ready(function() {

    $('body').on('mouseenter', '.image-photo-previous', function() {
        $(this).stop(true,true).animate({marginLeft: '-=50px'}, 300, 'swing');
    });

    $('body').on('mouseleave', '.image-photo-previous', function() {
        $(this).stop(true,true).animate({marginLeft: '+=50px'}, {queue: false}, 300, 'swing');
    });

});

Узнайте больше о.stop (): http://api.jquery.com/stop/

jsFiddle Demo

Если вы хотите, чтобы анимация не прерывалась, вы должны позволить jquery управлять ею в fx очередь. Вы явно говорите это не здесь:

{queue: false}

так что вам нужно изменить это на это:

$(this).animate({marginLeft: '+=50px'}, {queue: true}, 300, 'swing');

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

Ссылка: Как узнать с помощью jQuery, анимируется ли элемент?

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

if( $('.image-photo-previous').is(':animated') ) {...}

Если это так, вы можете использовать функцию обратного вызова в ссылке выше, чтобы подождать (используя setTimeOut) или рассчитать ожидаемое количество пикселей в пикселях, необходимое для возврата div в исходное положение

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

Также звоните $(this).stop(); в вашем mouseleave отменить предыдущую анимацию.

$(document).ready(function() {
    $('body').on('mouseenter', '.image-photo-previous', function() {
        startMargin = $(this).css('marginLeft');
        $(this).animate({marginLeft: '-=50px'}, 300, 'swing');
    });

    $('body').on('mouseleave', '.image-photo-previous', function() {
        $(this).stop();
        $(this).animate({marginLeft: ''}, {queue: false}, 300, 'swing');
    });
});

скрипка: http://jsfiddle.net/ExUzJ/2/

Дайте мне знать, если это то, что вы искали или нет.

Другие вопросы по тегам