为何多组视频动画的时序随时间推移逐渐变慢且错乱?
视频动画时序错乱问题解决
我实现了一个每隔几秒切换的视频,带有旋转动画,且旋转过程中视频会缩小再放大。但随着时间推移,动画的时序逐渐错乱。代码如下:
let degree = 720; function rotateElement(){ let spin = `rotate(${degree}deg)`; document.getElementById('myVideo').style.transform = spin; document.getElementById('myVideo').style.transitionDuration = "1s"; degree += 720; } function smaller(){ document.getElementById('myVideo').style.maxWidth = "10px"; document.getElementById('myVideo').style.maxHeight = "10px"; document.getElementById('myVideo').style.transitionDuration = "1s"; } function bigger(){ document.getElementById('myVideo').style.maxWidth = "30vw"; document.getElementById('myVideo').style.maxHeight = "19vw"; document.getElementById('myVideo').style.transitionDuration = "1s"; } window.onload = function () { setInterval(change, 5000); setInterval(rotateElement, 4900); setInterval(smaller, 4850); setInterval(bigger, 5050); };
问题原因
你用了4个独立的setInterval定时器,每个定时器的触发时机是各自独立计算的。但JavaScript的定时器并非绝对精确,会受事件循环中其他任务的影响产生微小误差。多个独立定时器的误差会不断累积,时间一长,缩小、旋转、放大、视频切换这几个动作的执行顺序就会彻底混乱。
解决方案
把所有动画逻辑整合到一个时序流程中,用嵌套的setTimeout或异步函数串联所有动作,让所有步骤按预定顺序依次执行,避免多个定时器的误差累积。
修改后的代码示例(嵌套setTimeout版)
let degree = 720; const video = document.getElementById('myVideo'); // 提前统一设置过渡时长,避免重复操作DOM video.style.transitionDuration = '1s'; function runAnimationCycle() { // 第一步:缩小视频 video.style.maxWidth = '10px'; video.style.maxHeight = '10px'; // 150ms后执行旋转 setTimeout(() => { video.style.transform = `rotate(${degree}deg)`; degree += 720; // 200ms后执行放大 setTimeout(() => { video.style.maxWidth = '30vw'; video.style.maxHeight = '19vw'; // 等待至5秒周期结束,切换视频并开启下一轮循环 setTimeout(() => { change(); // 调用你的视频切换函数 runAnimationCycle(); // 启动下一个5秒周期 }, 4650); // 5000 - 150 - 200 = 4650,保证总周期严格为5秒 }, 200); }, 150); } window.onload = function () { // 启动第一个动画周期 runAnimationCycle(); };
更易读的async/await版
let degree = 720; const video = document.getElementById('myVideo'); video.style.transitionDuration = '1s'; // 封装延时工具函数 function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function runAnimationCycle() { // 缩小视频 video.style.maxWidth = '10px'; video.style.maxHeight = '10px'; await delay(150); // 执行旋转 video.style.transform = `rotate(${degree}deg)`; degree += 720; await delay(200); // 放大视频 video.style.maxWidth = '30vw'; video.style.maxHeight = '19vw'; await delay(4650); // 切换视频并开启下一轮循环 change(); runAnimationCycle(); } window.onload = () => runAnimationCycle();
内容的提问来源于stack exchange,提问作者taymaz
相关产品推荐
相关产品推荐

