Вопрос по javascript, jquery, css – Какой самый чистый способ временно отключить эффекты CSS-перехода?

180

У меня есть элемент DOM с некоторыми / всеми из следующих эффектов:

#elem {
  -webkit-transition: height 0.4s ease;
  -moz-transition: height 0.4s ease;
  -o-transition: height 0.4s ease;
  transition: height 0.4s ease;
}

Я пишу плагин jQuery, который изменяет размеры этого элемента, мне нужно временно отключить эти эффекты, чтобы я мог плавно изменить его размер.

Каков самый элегантный способ временно отключить эти эффекты (а затем повторно включить их), учитывая, что они могут применяться от родителей или не применяться вообще.

Это выглядит многообещающе:ricostacruz.com/jquery.transit, Это лицензия MIT, так что вы можете либо включить ее, либо изучить, чтобы узнать, как он это делает. Robert Harvey♦

Ваш Ответ

8   ответов
425
Short Answer

Use this CSS:

.  -webkit-transition: none !important;
  -moz-transition: none !important;
  -o-transition: none !important;
  transition: none !important;
}

Plus either this JS (without jQuery)...

someElement.classList.add('notransition'); // Disable transitions
doWhateverCssChangesYouWant(someElement);
someElement.offsetHeight; // Trigger a reflow, flushing the CSS changes
someElement.classList.remove('notransition'); // Re-enable transitions

Or this JS with jQuery...

$someElement.addClass('notransition'); // Disable transitions
doWhateverCssChangesYouWant($someElement);
$someElement[0].offsetHeight; // Trigger a reflow, flushing the CSS changes
$someElement.removeClass('notransition'); // Re-enable transitions

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

Explanation

Это на самом деле довольно тонкая проблема.

Прежде всего, вы, вероятно, хотите создать «notransition». класс, который вы можете применить к элементам, чтобы установить их*-transition CSS атрибуты дляnone, Например:

.
  -webkit-transition: none !important;
  -moz-transition: none !important;
  -o-transition: none !important;
  transition: none !important;
}

(Minor aside - note the lack of an -ms-transition in there. You don't need it. The first version of Internet Explorer to support transitions at all was IE 10, which supported them unprefixed.)

Но это просто стиль, и это легко. Когда вы попытаетесь использовать этот класс, вы попадете в ловушку. Ловушка заключается в том, что подобный код не будет работать так, как вы могли бы наивно ожидать:

// Don't do things this way! It doesn't work!
someElement.classList.add('notransition')
someElement.style.height = '50px' // just an example; could be any CSS change
someElement.classList.remove('notransition')

Наивно, вы могли бы подумать, что изменение высоты не будет анимированным, потому что это происходит в то время, когда «notransition» класс применяется. В действительности, однако, этоwill быть анимированным, по крайней мере, во всех современных браузерах, которые я пробовал. Проблема заключается в том, что браузер кэширует изменения стиля, которые необходимо внести, пока не завершится выполнение JavaScript, а затем вносит все изменения за один раз. В результате он выполняет перекомпоновку, где нет чистого изменения того, включены ли переходы, но есть чистое изменение высоты. Следовательно, это оживляет изменение высоты.

Вы могли бы подумать, что разумным и чистым способом обойти это было бы завершение удаления «notransition». Класс в 1 мс, как это:

// Don't do things this way! It STILL doesn't work!
someElement.classList.add('notransition')
someElement.style.height = '50px' // just an example; could be any CSS change
setTimeout(function () {someElement.classList.remove('notransition')}, 1);

но это также не работает надежно. Я не смог разорвать приведенный выше код в браузерах WebKit, но в Firefox (как на медленных, так и на быстрых машинах) вы иногда (на первый взгляд, случайным образом) получаете то же поведение, что и при использовании наивного подхода. Я предполагаю, что причина этого в том, что выполнение JavaScript может быть достаточно медленным, чтобы функция тайм-аута ожидала выполнения к тому моменту, когда браузер бездействует, и в противном случае думала бы о выполнении оппортунистического перекомпоновки, и если этот сценарий случается, Firefox выполняет функцию из очереди перед перекомпоновкой.

Единственное решение, которое я нашел для этой проблемы, заключается вforce перекомпоновка элемента, сбрасывающая CSS-изменения, внесенные в него, перед удалением «notransition» учебный класс. Есть разные способы сделать это - смотритеВот для некоторых. Самая близкая вещь к «стандартному» способ сделать это, чтобы прочитатьoffsetHeight свойство элемента.

Одно из решений, которое действительно работает,

someElement.classList.add('notransition'); // Disable transitions
doWhateverCssChangesYouWant(someElement);
someElement.offsetHeight; // Trigger a reflow, flushing the CSS changes
someElement.classList.remove('notransition'); // Re-enable transitions

Вот скрипта JS, которая иллюстрирует три возможных подхода, которые я описал здесь (как один успешный подход, так и два неудачных): http://jsfiddle.net/2uVAA/131/

Ваше решение правильное, но для тех, кто ищет дополнительную справочную информацию:stackoverflow.com/a/31862081/1026
Превосходный ответ. Хорошая работа, и ценится, так как я придумал ту же проблему. Что если я хочу удалить только один тип перехода?
Интересно, что простая проверка высоты смещения элемента запускает перекомпоновку. Жаль, что я знал это год назад, когда я бился головой об стену с этой же проблемой. Это все еще считается самым идеальным способом справиться с этим?
Minor второстепенный, IE10 был первымstable версия IE для доставки с безфиксированными переходами. В предварительных версиях, за исключением Release Preview, требовался префикс -ms- для переходов, а также множество других вещей. Я подозреваю, что это одна из причин появления префикса -ms- сегодня. Другой, гораздо более вероятной причиной, конечно же, является обычный культ груза, который мы все узнаем и любим в отношении префиксов поставщиков.
Но это не сработает для: before и: after, потому что вы не можете добавлять классы для псевдоэлементов. я делаю.notransition, .notransition:before, .notransition:after {transition: none !important;} и добавить класс для самого элемента. Но если вам нужно отключить только анимацию псевдоэлемента, но не элемент, я рекомендую добавить разные классы для элемента, например..notransition, .notransition-before:before, .notransition-after:after {transition: none !important;}
15

eSoul, но сделав переключение глобальным:

/*kill the transitions on any descendant elements of .notransition*/
.notransition * { 
  -webkit-transition: none !important; 
  -moz-transition: none !important; 
  -o-transition: none !important; 
  -ms-transition: none !important; 
  transition: none !important; 
} 

.notransition может быть применен кbody элемент, эффективно перекрывающий любую анимацию перехода на странице:

$('body').toggleClass('notransition');
По производительности я не могу ожидать, что это будет хорошей идеей. & quot; О, просто примените это ко ВСЕМУ на странице, это упростит задачу! & quot;
Вероятно, следует выбрать оба ".notransition" и ".notransition *" быть полностью эффективным.
Я закончил тем, что использовал это в angularjs, в несколько сложном сценарии, но, черт возьми, это было так полезно после нескольких дней стука моей головы.
Это правильный ответ для ситуаций, когда вы просто хотите сделать все сразу. Например, я хочу отключить переходы во время вращения на мобильном телефоне, и это идеально подходит для этого.
17

который блокирует переход, а затем удалите его, чтобы вернуться в предыдущее состояние. Это делает код CSS и JQuery коротким, простым и понятным.

CSS:

.notransition {
  -webkit-transition: none !important;
  -moz-transition: none !important;
  -o-transition: none !important;
  -ms-transition: none !important;
  transition: none !important;
}

!important был добавлен, чтобы быть уверенным, что это правило будет иметь больший «вес», поскольку идентификатор обычно более специфичен, чем класс.

JQuery:

$('#elem').addClass('notransition'); // to remove transition
$('#elem').removeClass('notransition'); // to return to previouse transition
-1 потому что этого было недостаточно, чтобы решить эту проблему для меня в Chrome или Firefox - если у меня есть Javascript, который добавляет класс, вносит изменения и удаляет класс, иногда измененияstill анимации. Я провел последние час или два, изучая эту проблему более подробно, и позже опубликую ответ с скриптами, показывающими случаи, когда наивный подход терпит неудачу, плюс аккуратный хак, который исправляет решение здесь, заставляя перекомпоновку между внесением изменений и удалением «notransition» учебный класс.
8

transition в'none', Чтобы восстановить переход, как указано в CSS, установитеtransition в пустую строку.

// Remove the transition
elem.style.transition = 'none';

// Restore the transition
elem.style.transition = '';

Если вы используете префиксы поставщиков, вам также необходимо установить их.

elem.style.webkitTransition = 'none'
-4

.no-transition { 
  -webkit-transition: none;
  -moz-transition: none;
  -o-transition: none;
  -ms-transition: none;
  transition: none;
}

а затем в вашем JQuery:

$('#elem').addClass('no-transition'); //will disable it
$('#elem').removeClass('no-transition'); //will enable it
Вы уверены, что без! Важной линейки CLASS переопределит ID один?
Да, так будет, потому что теперь вы нацеливаетесь на # elem.no-transition, который более конкретен, чем просто идентификатор.
@MoinZaman Эмм, но тыhaven't целевое#elem.no-transition в вашем CSS вы только что настроили таргетинг.no-transition, Возможно, вы хотели написать#elem.no-transition в вашем CSS?
0

что вы могли бы создать отдельный класс CSS, который вы можете использовать в этих случаях:

.disable-transition {
  -webkit-transition: none;
  -moz-transition: none;
  -o-transition: color 0 ease-in;
  -ms-transition: none;
  transition: none;
}

Тогда в jQuery вы бы переключили класс следующим образом:

$('#<your-element>').addClass('disable-transition');
да, я думаю, что это лучший подход, на самом деле плагин может внедрить этот блок CSS на страницу Sam Saffron
Вы уверены, что без! Важной линейки CLASS переопределит ID один?
6

переход, trasforms для всех элементов на странице

var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = '* {' +
'/*CSS transitions*/' +
' -o-transition-property: none !important;' +
' -moz-transition-property: none !important;' +
' -ms-transition-property: none !important;' +
' -webkit-transition-property: none !important;' +
'  transition-property: none !important;' +
'/*CSS transforms*/' +
'  -o-transform: none !important;' +
' -moz-transform: none !important;' +
'   -ms-transform: none !important;' +
'  -webkit-transform: none !important;' +
'   transform: none !important;' +
'  /*CSS animations*/' +
'   -webkit-animation: none !important;' +
'   -moz-animation: none !important;' +
'   -o-animation: none !important;' +
'   -ms-animation: none !important;' +
'   animation: none !important;}';
   document.getElementsByTagName('head')[0].appendChild(style);
@Golly Эти другие свойства могут повлиять на окончательный дизайн
Во-первых, это здорово, спасибо! Во-вторых, есть также некоторые другие свойства, которые должны быть установлены; увидетьgithub.com/japgolly/test-state/blob/master/util/shared/src/test/…
-3

$('#elem').css('-webkit-transition','none !important'); 

в твоих js это убить?

очевидно, повторить для каждого.

тогда вам нужно сбросить его после факта, так что вам нужно хранить его, что приведет к достаточному количеству котельной плиты Sam Saffron

Похожие вопросы