【发布时间】: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 转换属性更改其在屏幕上的位置。
条件:
- 元素具有固定的过渡时间(在 CSS 文件中定义)。
- 在动画的任何时候,JavaScript 可能会设置元素的新位置,即在现有动画完成之前会发生变化。
- 事先不知道元素的新位置 => 即 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