如何实现随动画重启同步计数的JavaScript计数器?
解决方案:让计数与动画循环精确同步
你之前用setInterval固定时间计数,浏览器定时器调度和CSS动画帧调度无法完全对齐,导致不同步。正确思路是监听CSS动画的循环事件,在动画每次回到起始状态(对应tacospin中degree=0的逻辑)时触发计数。
步骤1:调整CSS动画(更直观的完整循环)
把原来的alternate来回动画改成完整的跳跃循环,让动画从地面跳起、落下再回到起始状态,每次循环结束对应一次完整跳跃:
#center{ display: block; margin-left: auto; margin-right: auto; width: 20%; } .centerfloor{ display: block; margin-left: auto; margin-right: auto; margin-top: 193px; width: 30%; } @keyframes jump { 0% {transform: translate3d(0,0,0) scale3d(1,1,1);} /* 初始状态:地面 */ 40% {transform: translate3d(0,30%,0) scale3d(1,1,1);} /* 跳到最高点 */ 80% {transform: translate3d(0,100%,0) scale3d(1,1.2,1);} /* 接近地面 */ 100% {transform: translate3d(0,0,0) scale3d(1,1,1);} /* 回到地面,完成一次跳跃 */ } .jump { transform-origin: 50% 50%; animation: jump 1.4s linear infinite; /* 完整循环时长1.4s,和原来回时间一致 */ }
步骤2:修改JavaScript代码,监听动画循环事件
删除原setInterval逻辑,改用animationiteration事件监听每次动画循环完成,此时计数加1:
let jumpCount = 0; const counterEl = document.getElementById('seconds-counter'); const dogImg = document.getElementById('center'); // 监听动画每次循环完成事件 dogImg.addEventListener('animationiteration', () => { jumpCount++; counterEl.innerText = `小狗已经跳了 ${jumpCount} 次`; });
步骤3:HTML结构保持不变
你的现有HTML无需修改,确保图片路径正确即可。
原理说明
animationiteration事件会在CSS动画完成一次完整循环时触发(infinite动画每次循环都会触发),这和tacospin中检测degree=0(动画回到起始状态)的逻辑完全匹配。- 这种方式完全依赖浏览器的动画调度,避免了定时器与动画不同步的问题,即使页面卡顿或后台运行,计数也会和动画实际循环次数保持一致。
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

