过渡期间CSS转换的变化会导致当前状态迷失并跳到开头(Chrome错误)

时间:2019-04-12 07:03:13

标签: javascript css css3 animation css-transforms

在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 是第一个动画(INITIAL和A状态之间的转换)。
  • 步骤6-10 是第二个动画(INITIAL和B状态之间的转换)。
  • 第3步是第一个动画被中断的原因,因为最终的变换属性已更改,即第二个动画从此处开始。

如您所见,动画跳转到错误的INITIAL状态(不需要)。步骤6的位置应靠近步骤3。

预期行为

更改CSS变换属性应将内部动画计时器重置为0(因此,新动画将按照过渡属性中的定义持续运行),但将当前变换状态保留为下一个动画的初始状态。

proper, expected css transition

  • 步骤1-5 是第一个动画(INITIAL和A状态之间的转换)。
  • 步骤6-10 是第二个动画(中间“ INITIAL到A”状态与B状态之间的转换)。
  • 第3步是第一个动画被中断的原因,因为最终的变换属性已更改,即第二个动画从此处开始。

如您所见,新动画将从所需的位置精确开始-从第3步开始,将元素很好地移动到新位置。

感谢您的阅读。期待您的帮助。

1 个答案:

答案 0 :(得分:0)

我不确定为什么会发生这种情况,但是解决方案是在将过渡属性(此处为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;

这是一个fork of your pen,包括修复程序。

getComputedStylewidely supported,因此除非您想支持IE <9

,否则无需担心polyfill。