Изменение CSS-преобразования во время перехода приводит к потере текущего состояния и переходу к началу (ошибка Chrome) - PullRequest
10 голосов
/ 12 апреля 2019

Протестировано в Google Chrome 73 (официальная сборка) (64-разрядная версия).

Также протестировано в последних стабильных Mozilla, Opera и Safari.

Похоже, что это ошибка только Chrome. Надеюсь, что есть обходной путь, пока команда Chrome не исправит ошибку.

Демо

Я создал Codepen , чтобы показать проблему.

const div = document.querySelector('div');

const cssTransition = 2500;
const states = [
  ['INITIAL', 'translate(0)', cssTransition / 2],
  ['A', 'translate(0, 100px)', cssTransition + 500],
  ['B', 'translate(100px, 100px)', cssTransition / 2],
];

let cursor = 0;

const animate = () => {
  cursor = (cursor + 1) % states.length;
  const [name, value, delay] = states[cursor];
  setTimeout(() => {
    div.innerText = name;
    div.style.transform = value;
    animate();
  }, delay);
};

animate();
div {
  width: 100px;
  height: 100px;
  background: brown;
  color: white;
  font-size: 25px;
  font-family: sans-serif;
  text-align: center;
  line-height: 100px;
  margin: 50px auto;
  transition: 2.5s ease;
}
<div>INITIAL</div>

Задача

Анимируйте элемент с помощью JavaScript, чтобы изменить его положение на экране, используя свойство преобразования CSS3.

Условия:

  1. Элемент имеет фиксированное время перехода (определено в файле CSS).
  2. В любой момент анимации JavaScript может установить новую позицию элемента, т. Е. Изменение произойдет до завершения существующей анимации.
  3. Новая позиция элемента заранее не известна => т.е. список классов CSS здесь не вариант.

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

Фактическое поведение

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

wrong, jumpy css transition

  • шаги 1-5 - первая анимация (переход между начальным и A-состояниями).
  • шаги 6-10 - вторая анимация (переход между начальным и B-состояниями).
  • шаг 3 - это место, где первая анимация была прервана из-за изменения свойства финального преобразования, то есть здесь начинается вторая анимация.

Как видите, анимация переходит в начальное состояние, которое является неправильным (нежелательным). Позиция на шаге 6 должна быть рядом с шагом 3.

Ожидаемое поведение

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

proper, expected css transition

  • шаги 1-5 - первая анимация (переход между начальным и A-состояниями).
  • шаги 6-10 - вторая анимация (переход между промежуточными состояниями «ПЕРВОНАЧАЛЬНО в А» и В).
  • шаг 3 - это место, где первая анимация была прервана из-за изменения свойства финального преобразования, то есть здесь начинается вторая анимация.

Как видите, новая анимация начинается именно там, где и ожидается - с шага 3 и приятно перемещает элемент в новую позицию.

Спасибо за чтение. Ждем вашей помощи.

1 Ответ

0 голосов
/ 20 июня 2019

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

div.style.transform = getComputedStyle(div).transform;
// Cause a reflow to force the browser to apply the set transform
div.innerWidth;
div.style.transform = value;

Вот вилка вашего пера , включая исправление.

getComputedStyle широко поддерживается , поэтому вам не нужно беспокоиться о полифилле, если вы не хотитеподдержка IE <9 </p>

...