Применяются ли переходы CSS, даже если они активированы после изменения состояния? - PullRequest
1 голос
/ 19 марта 2012

У меня есть плагин jQuery, который перемещает элемент на экране, но имеет переключатель «анимировать», чтобы показать переход слайдов или нет.Пытаясь использовать CSS-переходы, а не переходы Javascript для изменения, я столкнулся с этим, и я не уверен, является ли это ошибкой / причудой, или я просто делаю это неправильно:

var $item = $('#myItem');
if (!animate) {
  $item.removeClass('csstransitions'); // Class that has "transition:left 0.25s ease-out" 
  $('#myItem').css('left', '300px'); // Move the element
  $('#myItem').addClass('csstransitions'); // Re-apply transitions class
}

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

Смотрите это в действии в this jsFiddle ;В Chrome или Safari нажмите кнопку «Без задержки» и убедитесь, что она все еще анимирует положение поля, в то время как кнопка «Задержка» (которая использует тайм-аут, установленный на одну миллисекунду позже) не анимирует изменение CSS.

Как указано в jsFiddle, мне нужно использовать вызов setTimeout (setTimeout(function() { $el.addClass('csstransition'); }, 1);), чтобы получить правильное поведение в Chrome и Safari.Это просто потому, что переходы CSS - это крайний случай, или я делаю что-то не так, и есть более простой способ временно «повернуть» переходы?

РЕДАКТИРОВАТЬ: Заметил этовопрос похож, и хотя ответ на этот вопрос состоит в том, чтобы просто разделить два вызова, остается вопрос: «Почему мы (веб-разработчики) должны разделять эти два вызова?»Это метод, который мы должны использовать для переключения CSS-переходов?

1 Ответ

2 голосов
/ 19 марта 2012

Я бы проголосовал за причуду или разницу в реализации.

До переходов действительно не имело значения, какие стили порядка были применены, потому что на практике порядок не имел значения, только специфичность.Но с переходами, элемент задержки был добавлен в стили, что является сутью проблемы.

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

Некоторые различия подробно описаны здесь:
http://taligarsiel.com/Projects/howbrowserswork1.htm

Хотя, я не знаю, покрыта ли эта конкретная проблема.

В качестве демонстрации , другой способ решить эту проблему - это иметь 2 обработчика щелчков:

$('button#nodelay').on('click', function() {
    var $el = $('#square');
    $el.removeClass('csstransition');
    $el.css('left', '100px');
}).on('click', function() {
    $el.addClass('csstransition');
});

Это в основном разделяет два обновления на отдельные блоки кода, во многом как метод setTimeout.

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

Редактировать

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

  1. CSS left: 300px добавляется к элементу DOM
  2. Отображаемый стиль: браузер проверяет напосмотрим, есть ли переход на элемент.Если так, оживите, если нет, примените немедленно.В этом случае не является переходом (пока), поэтому анимация не выполняется.
  3. CSS transition: left 2s ease-out добавлено к элементу DOM
  4. Стиль визуализации: без изменения рендерингапереход применяется к будущим left изменениям.

Однако, если браузер оптимизирует рендеринг CSS, сгруппировав в конце блоки кода (или что-то в этом роде), вы получите следующее:

  1. CSS left: 300px добавлен к элементу DOM
  2. CSS transition: left 2s ease-out добавлен к элементу DOM
  3. Достигнута точка рендеринга (конец блока кода и т. Д.), Всеотображаемые стили:
  4. Когда применяется left, браузер проверяет, есть ли переход к элементу.Если так, оживите, если нет, примените немедленно.В этом случае - это переход, поэтому происходит анимация.

Итак, длина анимации и время ожидания не имеют значения.Важно то, что left: 300px отображается до перехода применяется.В настоящее время в WebKit это означает применение стиля transition в отдельном, более позднем кодовом блоке, чем стиль left.Это достигается всеми предлагаемыми ответами setTimeout (событие с задержкой 0), отдельным обработчиком щелчка (если применяется секунда) или обратным вызовом функции.

Вот еще один способ, который работает:

$('button#nodelay').on('click', function() {
    var $el = $('#square');
    $el.removeClass('csstransition');
    $el.css('left', '100px').css('left'); // <-- This (or .show() even)
    $el.addClass('csstransition');
});

Это работает, потому что вы заставляете браузер останавливать и оценивать CSS, чтобы вы могли получить значение left (хотя вы можете поместить любой действительный атрибут css во второй вызов .css()).В этом случае он применяет весь CSS и заставляет элемент (-ы) выполнить повторную визуализацию.

...