Как следует из названия, существует ли подходящий способ установить некоторые начальные свойства CSS (или класс) и сообщить браузеру перевести их на другое значение?
Например (fiddle):
var el = document.querySelector('div'),
st = el.style;
st.opacity = 0;
st.transition = 'opacity 2s';
st.opacity = 1;
Это не будет анимировать непрозрачность элемента в Chrome 29/Firefox 23. Это происходит потому, что (source):
[...] вы найдете, что если вы примените оба набора свойств, сразу после другой браузер пытается оптимизировать свойство изменения, игнорируя ваши первоначальные свойства и предотвращая переход. За кулисами браузеры дорабатывают изменения свойств до рисования которые, хотя обычно ускоряют рендеринг, могут иногда иметь неблагоприятные влияет.
Решение состоит в том, чтобы заставить перерисовать между применением двух наборов свойства. Простой способ сделать это - просто получить доступ к DOM Элементы
offsetHeight
свойство [...]
Фактически, хак действительно работает в текущих версиях Chrome/Firefox. Обновленный код (fiddle - нажмите Run
после открытия скрипта для запуска анимации снова):
var el = document.querySelector('div'),
st = el.style;
st.opacity = 0;
el.offsetHeight; //force a redraw
st.transition = 'opacity 2s';
st.opacity = 1;
Однако это довольно хакерское поведение, и, как сообщается, он не работает на некоторых устройствах Android.
В другом ответе предлагается использовать setTimeout
, чтобы браузер имел время выполнить перерисовку, но он также терпит неудачу, поскольку мы не знаем, сколько времени потребуется для перерисовки. Угадайте приличное количество миллисекунд (30-100?), Чтобы обеспечить перерисовку, означающую потерю производительности, излишне холостую в надежде на то, что браузер немного поработает за это время.
Через тестирование я нашел еще одно решение, которое отлично работает в последнем Chrome, используя requestAnimationFrame
(fiddle):
var el = document.querySelector('div'),
st = el.style;
st.opacity = 0;
requestAnimationFrame(function() {
st.transition = 'opacity 2s';
st.opacity = 1;
});
Я предполагаю, что requestAnimationFrame
ждет до начала следующей перерисовки перед выполнением обратного вызова, поэтому браузер не вносит изменения в свойства. Не совсем уверен здесь, но хорошо работает на Chrome 29.
Обновление: после дальнейшего тестирования метод requestAnimationFrame
работает не очень хорошо в Firefox 23 - похоже, он больше не работает. (fiddle)
Есть ли подходящий или рекомендуемый (кросс-браузерный) способ достижения этого?