Что это самый чистый способ, чтобы временно отключить эффекты перехода в CSS?



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



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

743   8  

8 ответов:

Короткий Ответ:

используйте этот CSS:

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

плюс либо это JS (без 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

или это JS с jQuery...

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

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

объяснение

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

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

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

(незначительные в сторону-обратите внимание на отсутствие -ms-transition там. Тебе это не нужно. Первая версия Internet Explorer для поддержки переходов на всех был IE 10, который поддерживал их незакрепленными.)

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

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

вы можете подумать, что разумным и чистым способом обойти это было бы обернуть удаление класса "notransition" в тайм-аут 1ms, например:

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

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

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

CSS:

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

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

JQuery:

$('#elem').addClass('notransition'); // to remove transition
$('#elem').removeClass('notransition'); // to return to previouse transition

Я бы рекомендовал отключить анимацию, как это предлагает DaneSoul, но сделать переключатель глобальным:

/*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');

для чистого решения JS (без классов CSS) просто установите transition до 'none'. Чтобы восстановить переход, как указано в CSS, установите transition на пустую строку.

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

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

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

elem.style.webkitTransition = 'none'

вы можете отключить анимацию, переход, его конвертирует для всех элементов на странице с помощью CSS кода

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);

Я думаю, вы могли бы создать отдельный класс 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');

тут

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

в вашем js убить его?

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

у меня был бы класс В вашем CSS, как это:

.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

Comments

    Ничего не найдено.