анимация addClass / removeClass с помощью jQuery - PullRequest
213 голосов
/ 05 сентября 2011

Я использую jQuery и jQuery-ui и хочу анимировать различные атрибуты различных объектов.

Для объяснения этой проблемы я упростил ее до одного деления, которое меняется с синего на красный, когда пользователь наводит на него курсор.

Я могу получить желаемое поведениепри использовании animate(), однако, при этом анимируемые стили должны быть в коде анимации и поэтому отделены от моей таблицы стилей.(см. пример 1 )

Альтернативой является использование addClass() и removeClass(), но мне не удалось воссоздать точное поведение, которое я могу получить с помощью animate().(см. пример 2 )


Пример 1

Давайте посмотрим на код, который у меня есть с animate():

$('#someDiv')
  .mouseover(function(){
    $(this).stop().animate( {backgroundColor:'blue'}, {duration:500});
  })
  .mouseout(function(){
    $(this).stop().animate( {backgroundColor:'red'}, {duration:500});
  });

он отображает все варианты поведения, которые я ищу:

  1. Плавно анимирует между красным и синим.
  2. Нет анимации, вызывающей чрезмерный перегрев, когда пользователь быстро перемещает указатель мыши внутрь и наружуделения.
  3. Если пользователь перемещает указатель мыши во время воспроизведения анимации, он корректно перемещается между текущим состоянием «на полпути» и новым состоянием «цель».

Но так как изменения стиля определены в animate(), я должен изменить там значения стиля, и я не могу просто указать, чтобы они указывали на мою таблицу стилей.Этот «фрагмент» определения стилей меня действительно беспокоит.


Пример 2

Вот моя лучшая на данный момент попытка с использованием addClass() и removeClass (обратите внимание, чточтобы анимация работала, вам нужен jQuery-ui):

//assume classes 'red' and 'blue' are defined

$('#someDiv')
  .addClass('blue')
  .mouseover(function(){
    $(this).stop(true,false).removeAttr('style').addClass('red', {duration:500});
  })
  .mouseout(function(){
    $(this).stop(true,false).removeAttr('style').removeClass('red', {duration:500});
  });

Это свойство 1 и 2 соответствует моим первоначальным требованиям, однако 3 не работает.

Я понимаюПричина этого:

При анимации addClass() и removeClass() jQuery добавляет временный стиль к элементу, а затем увеличивает соответствующие значения до тех пор, пока они не достигнут значений предоставленного класса, и только тогда это происходит на самом деле.Добавить / удалить класс.

Из-за этого я должен удалить атрибут style, иначе, если анимация остановится на полпути, атрибут style останется и навсегда перезапишет любые значения класса, так как атрибуты стиля в теге имеютважнее стилей классов.

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


В идеале я хочу иметь возможность сделать что-то вроде этого:

$('#someDiv')
  .mouseover(function(){
    $(this).stop().animate( getClassContent('blue'), {duration:500});
  })
  .mouseout(function(){
    $(this).stop().animate( getClassContent('red'), {duration:500});
  });

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

Ответы [ 6 ]

298 голосов
/ 06 сентября 2011

Поскольку вы не беспокоитесь о IE, почему бы просто не использовать переходы CSS для предоставления анимации и JQuery для изменения классов. Живой пример: http://jsfiddle.net/tw16/JfK6N/

#someDiv{
    -webkit-transition: all 0.5s ease;
    -moz-transition: all 0.5s ease;
    -o-transition: all 0.5s ease;
    transition: all 0.5s ease;
}
89 голосов
/ 18 августа 2013

Другое решение (но оно требует jQueryUI, как отметил Ричард Нил Илаган в комментариях): -

addClass, removeClass и toggleClass также принимают второй аргумент; время перехода из одного состояния в другое.

$(this).addClass('abc',1000);

См. Jsfiddle: - http://jsfiddle.net/6hvZT/1/

37 голосов
/ 23 ноября 2013

Вы можете использовать jquery ui's switchClass, вот пример:

$( "selector" ).switchClass( "oldClass", "newClass", 1000, "easeInOutQuad" );

Или посмотрите это jsfiddle .

12 голосов
/ 14 ноября 2013

Вам просто нужно ядро ​​эффектов jQuery UI (13 КБ), чтобы включить продолжительность добавления (как указывал Омар Тарик)

4 голосов
/ 06 февраля 2015

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

Это то, что я в итоге сделал:

//css
.addedClass {
    background: #5eb4fc;
}

// js
function setParentTransition(id, prop, delay, style, callback) {
    $(id).css({'-webkit-transition' : prop + ' ' + delay + ' ' + style});
    $(id).css({'-moz-transition' : prop + ' ' + delay + ' ' + style});
    $(id).css({'-o-transition' : prop + ' ' + delay + ' ' + style});
    $(id).css({'transition' : prop + ' ' + delay + ' ' + style});
    callback();
}
setParentTransition(id, 'background', '0s', 'ease', function() {
    $('#elementID').addClass('addedClass');
});

setTimeout(function() {
    setParentTransition(id, 'background', '2s', 'ease', function() {
        $('#elementID').removeClass('addedClass');
    });
});

Это мгновенно меняет цвет фона на # 5eb4fc, а затем медленно возвращается к нормальному состоянию в течение 2 секунд.

Вот скрипка

2 голосов
/ 26 февраля 2014

Хотя вопрос довольно старый, я добавляю информацию, отсутствующую в других ответах.

ОП использует stop (), чтобы остановить текущую анимацию, как только событие завершится.Однако использование правильного сочетания параметров с функцией должно помочь.например.stop (true, true) или stop (true, false), поскольку это хорошо влияет на анимацию, поставленную в очередь.

Следующая ссылка иллюстрирует демонстрацию, которая показывает различные параметры, доступные с помощью stop (), и их отличие от финиша ().

http://api.jquery.com/finish/

Хотя у OP не было проблем с использованием JqueryUI, это для других пользователей, которые могут сталкиваться с похожими сценариями, но не могут использовать JqueryUI / нуждаются в поддержке IE78 тоже.

...