JS:如何同步多个动画的时间?
JS: how to sync timing of multiple animations?
当我动态添加一个使用 JS 制作动画的项目时,如何使它们在同一时间轴上同步,如下所示:http://youtube.com/watch?v=AGiTmjFHs8M&t=9m23s?我看到一个教程显示使用 JS 动画与 CSS 的好处是它们继承了相同的时间轴。
<div class="body"></div>
<button onclick="addItem()">Add</button>
function addItem() {
let body = document.querySelector('.body');
let newEl = document.createElement('div');
newEl.innerText = "I am a new Item";
newEl.animate([
{
transform: 'translate(0px, 0px)',
transform: 'translate(500px, 500px)',
}
],
{
duration: 2000,
iterations: Infinity,
});
body.appendChild(newEl);
}
如果你所有的Animation objects do share the same duration
and you want them to start and end at the same time, you can simply set the iterationStart
EffectTiming of your new Animation object to the ComputedTiming.progress
价值已经运行一个。
但是请注意,您必须等待新的 Animation 对象准备就绪,然后才能获取前一个动画对象的计算值,否则您将延迟一帧。为此,您只需等待 animation.ready
Promise。
要获取之前的 Animation 对象,您可以在创建它时通过 Element.animate()
, or you can access the set of currently running Animations on the document through document.getAnimations()
存储它,然后从那里获取它。
let i = 0;
async function addItem() {
i++;
const body = document.querySelector(".body");
const newEl = document.createElement("div");
newEl.classList.add("item");
newEl.textContent = "I am a new Item " + i;
// get a previous Animation if any
const previous_animation = document.getAnimations()[0];
// create the new Animation object
// slightly offset on the x axis only
// to check if they are indeed in sync
const anim = newEl.animate([{
transform: "translate(" + (i * 10) + "px, 0px)",
transform: "translate(" + (i * 10 + 250) + "px, 250px)",
}], {
duration: 2000,
iterations: Infinity
});
// when it's ready to start
await anim.ready;
// get the current progress of the first Animation object
const computed_timing = previous_animation?.effect.getComputedTiming();
if( computed_timing ) {
// update our new Animation object to the same progress value
anim.effect.updateTiming( {
iterationStart: computed_timing.progress
});
}
body.appendChild(newEl);
}
.item {
position: absolute;
}
<div class="body"></div>
<button onclick="addItem()">Add</button>
请注意,正如用户所指出的那样 brianskold in a , the startTime
property 动画可以设置为更早的时间。这样做会使动画did在此时开始。
所以对于同步两个动画,这可能是最好的方法:
let i = 0;
function addItem() {
i++;
const body = document.querySelector(".body");
const newEl = document.createElement("div");
newEl.classList.add("item");
newEl.textContent = "I am a new Item " + i;
// get a previous Animation if any
const previous_animation = document.getAnimations()[0];
// create the new Animation object
// slightly offset on the x axis only
// to check if they are indeed in sync
const anim = newEl.animate([{
transform: "translate(" + (i * 10) + "px, 0px)",
transform: "translate(" + (i * 10 + 250) + "px, 250px)",
}], {
duration: 2000,
iterations: Infinity
});
if( previous_animation ) {
// set the startTime to the same
// as the previously running's one
// note this also forces anim.ready to resolve directly
anim.startTime = previous_animation.startTime;
}
body.appendChild(newEl);
}
.item {
position: absolute;
}
<div class="body"></div>
<button onclick="addItem()">Add</button>
当我动态添加一个使用 JS 制作动画的项目时,如何使它们在同一时间轴上同步,如下所示:http://youtube.com/watch?v=AGiTmjFHs8M&t=9m23s?我看到一个教程显示使用 JS 动画与 CSS 的好处是它们继承了相同的时间轴。
<div class="body"></div>
<button onclick="addItem()">Add</button>
function addItem() {
let body = document.querySelector('.body');
let newEl = document.createElement('div');
newEl.innerText = "I am a new Item";
newEl.animate([
{
transform: 'translate(0px, 0px)',
transform: 'translate(500px, 500px)',
}
],
{
duration: 2000,
iterations: Infinity,
});
body.appendChild(newEl);
}
如果你所有的Animation objects do share the same duration
and you want them to start and end at the same time, you can simply set the iterationStart
EffectTiming of your new Animation object to the ComputedTiming.progress
价值已经运行一个。
但是请注意,您必须等待新的 Animation 对象准备就绪,然后才能获取前一个动画对象的计算值,否则您将延迟一帧。为此,您只需等待 animation.ready
Promise。
要获取之前的 Animation 对象,您可以在创建它时通过 Element.animate()
, or you can access the set of currently running Animations on the document through document.getAnimations()
存储它,然后从那里获取它。
let i = 0;
async function addItem() {
i++;
const body = document.querySelector(".body");
const newEl = document.createElement("div");
newEl.classList.add("item");
newEl.textContent = "I am a new Item " + i;
// get a previous Animation if any
const previous_animation = document.getAnimations()[0];
// create the new Animation object
// slightly offset on the x axis only
// to check if they are indeed in sync
const anim = newEl.animate([{
transform: "translate(" + (i * 10) + "px, 0px)",
transform: "translate(" + (i * 10 + 250) + "px, 250px)",
}], {
duration: 2000,
iterations: Infinity
});
// when it's ready to start
await anim.ready;
// get the current progress of the first Animation object
const computed_timing = previous_animation?.effect.getComputedTiming();
if( computed_timing ) {
// update our new Animation object to the same progress value
anim.effect.updateTiming( {
iterationStart: computed_timing.progress
});
}
body.appendChild(newEl);
}
.item {
position: absolute;
}
<div class="body"></div>
<button onclick="addItem()">Add</button>
请注意,正如用户所指出的那样 brianskold in a startTime
property 动画可以设置为更早的时间。这样做会使动画did在此时开始。
所以对于同步两个动画,这可能是最好的方法:
let i = 0;
function addItem() {
i++;
const body = document.querySelector(".body");
const newEl = document.createElement("div");
newEl.classList.add("item");
newEl.textContent = "I am a new Item " + i;
// get a previous Animation if any
const previous_animation = document.getAnimations()[0];
// create the new Animation object
// slightly offset on the x axis only
// to check if they are indeed in sync
const anim = newEl.animate([{
transform: "translate(" + (i * 10) + "px, 0px)",
transform: "translate(" + (i * 10 + 250) + "px, 250px)",
}], {
duration: 2000,
iterations: Infinity
});
if( previous_animation ) {
// set the startTime to the same
// as the previously running's one
// note this also forces anim.ready to resolve directly
anim.startTime = previous_animation.startTime;
}
body.appendChild(newEl);
}
.item {
position: absolute;
}
<div class="body"></div>
<button onclick="addItem()">Add</button>