анимация addClass / removeClass с помощью jQuery

226

Я использую 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. Никакая анимация не перегружается, когда пользователь быстро перемещает свою мышь внутрь и наружу от div.
  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 не работает.

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

Когда animating 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бы просто вернуть содержимое предоставленного класса. Ключевым моментом является то, что таким образом мне не нужно хранить определения стилей повсюду, но я могу хранить их в классах в моей таблице стилей.

Johannes
источник
1
Какие версии IE вам нужно поддерживать? Будете ли вы довольны IE9? Или нужно поддерживать ниже?
16
1
Я не забочусь об IE вообще, если честно. Все это было протестировано только с браузерами webkit (safari / chrome).
Йоханнес
как getClassContentвыглядит?
sreginogemoh

Ответы:

311

Поскольку вы не беспокоитесь о 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;
}
tw16
источник
14
По состоянию на 2015-06-12 это поддерживается в - IE 10+ - Chrome 26+ - FireFox 16+ - Safari 6.1+ - Opera 12.1+ -webkit, -moz, -o требуется только для более старых браузеров. Вы можете оставить это, чтобы сэкономить место.
clst
3
@clst, я бы предпочел обратную совместимость со старыми браузерами, а не экономить несколько байтов.
Арман Х
96

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

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

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

Смотрите jsfiddle: - http://jsfiddle.net/6hvZT/1/

Омар Тарик
источник
28
Обратите внимание, что для этого требуется пользовательский интерфейс jQuery. jQuery из коробки не поддерживает анимацию анимации для xxxClass()функций.
Ричард Нил Илаган
@Richard Neil Ilagan: Спасибо за уведомление. Я действительно упустил этот момент.
Омар Тарик
4
Можете ли вы указать, какой файл загрузить и включить в файл .html, чтобы я мог использовать jQueryUI только для xxxClassанимации анимации таким образом?
нитрат натрия
[jqueryui.com] (jqueryui.com) @sodiumnitrate
joe_young
1
Это решение также не анимирует так же, как slide () или animate (). Значение в миллисекундах - это задержка, а не анимация.
Солона Армстронг,
38

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

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

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

by0
источник
1
-1. Вы не выполнили ограничения 1, 2 и 3, которые я перечислил в исходном посте. В частности, SwitchClass плохо обрабатывает требования 2 и 3.
Йоханнес
12

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

Патрик
источник
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 секунд.

Вот скрипка

Ти Дженгер
источник
2

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

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

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

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

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

Анураг
источник