Анимация addClass/removeClass с jQuery

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

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

Я могу получить поведение, которое я хочу при использовании 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});
  });

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

  • Анимирует плавно между красным и синим.
  • Отсутствие анимации "переизбытка", когда пользователь быстро перемещает свою мышь в и из div.
  • Если пользователь перемещает мышь в/в, пока анимация все еще воспроизводится, она корректно работает между текущим состоянием "halfway" и новым состоянием "цель".

Но поскольку изменения стиля определены в 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 добавляет временный стиль к элементу и затем увеличивает соответствующие значения до тех пор, пока они не достигнут значений предоставленного класса, и только тогда он фактически добавит/удалит класс.

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

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


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

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

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

Ответ 1

Поскольку вы не беспокоитесь об 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;
}

Ответ 2

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

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

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

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

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

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

Вот что я сделал:

//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 секунд.

Здесь fiddle

Ответ 6

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

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

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

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

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