【问题标题】:CSS transformation change during transition causes current state to get lost and jumps to the beginning (Chrome bug)过渡期间的 CSS 转换更改导致当前状态丢失并跳转到开头(Chrome 错误)
【发布时间】:2019-09-02 21:33:27
【问题描述】:

在 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 变换属性在过渡期间(即在当前动画完成之前)发生变化时,下一个动画将从上一个动画的初始状态开始。

  • 步骤 1-5 是第一个动画(INITIAL 和 A 状态之间的转换)。
  • 步骤 6-10 是第二个动画(INITIAL 和 B 状态之间的转换)。
  • 第 3 步是第一个动画被中断的地方,因为最终的变换属性发生了变化,即第二个动画从这里开始。

如您所见,动画跳转到错误(不希望的)初始状态。第 6 步的位置应靠近第 3 步。

预期行为

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

  • 步骤 1-5 是第一个动画(INITIAL 和 A 状态之间的转换)。
  • 步骤 6-10 是第二个动画(中间“INITIAL 到 A”和 B 状态之间的转换)。
  • 第 3 步是第一个动画被中断的地方,因为最终的变换属性发生了变化,即第二个动画从这里开始。

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

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

【问题讨论】:

  • 现在正在测试,它有时确实有效,即使它不是很流畅(只需多次刷新你的笔)。似乎是一个奇怪的错误。
  • 看看我的pen,右边的行为基本上是你想要实现的,但是有动画中断(这不能通过css动画来实现)对吧?
  • @Jake 是的,类似的。顺便说一句,我看到您设置了几乎可以正常工作的“线性”过渡类型。但是如果你设置“transition: transform 2.5s ease;”它会跳转到最初始的状态。
  • 2020 年仍然发生 :(。解决方法是使用 left / top 而不是 translate

标签: javascript css animation css-transforms


【解决方案1】:

我不确定为什么会发生这种情况,但一种解决方案是在更改为新的所需属性之前手动将转换后的属性(此处为 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 所以你不需要担心 polyfill 除非你想支持 IE

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-04
    • 2021-05-14
    • 1970-01-01
    • 2015-11-16
    • 2018-09-01
    • 2015-11-15
    相关资源
    最近更新 更多