如何避免CSS动画随JS setInterval执行反复重启?
问题根源
你遇到的问题是因为每秒执行updateTimer时,都通过innerHTML替换了整个#timer容器的内容,这会销毁原来的子div元素并创建新的。每个新创建的div都会重新触发CSS动画,导致动画每秒重启一次。
解决方案
要让动画只执行一次,核心是保留原来的子div元素,只更新它们的内容而不是重新创建。下面提供两种可行的方案:
方案一:直接更新现有子div的内容
修改JS代码,不再替换#timer的innerHTML,而是获取已存在的子div并逐个更新内容:
function updateTimer(){ const target = Date.parse("9 January 2023, 00:00:00"); const today = new Date(); const diff = target - today; let days = Math.floor(diff / (1000 * 60 * 60 * 24)); let hours = Math.floor(diff / (1000 * 60 * 60)); let mins = Math.floor(diff / (1000 * 60)); let secs = Math.floor(diff / 1000); hours = hours - days * 24; const minutes = mins - hours * 60; const seconds = secs - mins * 60; // 获取已存在的子div元素 const timerDivs = document.getElementById("timer").children; // 逐个更新内容,不重新创建div timerDivs[0].innerHTML = `${days}<span> Days</span>`; timerDivs[1].innerHTML = `${hours}<span> Hours</span>`; timerDivs[2].innerHTML = `${minutes}<span> Minutes</span>`; timerDivs[3].innerHTML = `${seconds}<span> Seconds</span>`; } // 立即执行一次,避免初始空白状态 updateTimer(); // 每秒更新倒计时 setInterval(updateTimer, 1000);
方案二:拆分数字与标签元素(更推荐)
调整HTML结构,为每个数字单独设置元素,仅更新数字的文本内容,完全不修改元素结构:
HTML修改为:
<div id="timer"> <div><span class="num"></span><span class="label">Days</span></div> <div><span class="num"></span><span class="label">Hours</span></div> <div><span class="num"></span><span class="label">Minutes</span></div> <div><span class="num"></span><span class="label">Seconds</span></div> </div>
对应的JS代码:
function updateTimer(){ const target = Date.parse("9 January 2023, 00:00:00"); const today = new Date(); const diff = target - today; let days = Math.floor(diff / (1000 * 60 * 60 * 24)); let hours = Math.floor(diff / (1000 * 60 * 60)); let mins = Math.floor(diff / (1000 * 60)); let secs = Math.floor(diff / 1000); hours = hours - days * 24; const minutes = mins - hours * 60; const seconds = secs - mins * 60; // 获取所有数字元素 const numElements = document.querySelectorAll("#timer .num"); // 仅更新文本内容 numElements[0].textContent = days; numElements[1].textContent = hours; numElements[2].textContent = minutes; numElements[3].textContent = seconds; } updateTimer(); setInterval(updateTimer, 1000);
修正CSS动画错误
你把animation-delay写在了关键帧内部,这是无效的。应该将延迟属性放在元素的动画声明中:
@keyframes timerSlideUp{ 0%{ opacity: 0; } 100%{ opacity: 1; } } #timer{ color: white; padding: 20px; text-align: center; } #timer div{ display: inline-block; min-width: 40px; padding: 15px; background: transparent; border-radius: 3px; border: 5px solid white; margin-top: 30%; margin-left: 5px; margin-right: 5px; text-align: center; font-size: 2em; font-weight: bold; /* 动画延迟5秒,持续5秒,保持结束状态 */ animation: timerSlideUp 5s forwards 5s; }
这样修改后,子div元素只会在页面加载时执行一次入场动画,后续倒计时更新不会再触发动画重启,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Dam
相关产品推荐
相关产品推荐

