如何在CSS关键帧结束时调用JS函数?解决动画与setTimeout不同步问题
解决CSS滚动动画与JS定时器不同步的问题
核心思路是放弃固定定时器,改用CSS动画结束事件触发文本更新,彻底避免浏览器后台节流导致的不同步问题。
实现步骤
1. 基础HTML结构
<div class="news-scroller" id="newsScroller">欢迎来到游戏,今日开启双倍经验活动!</div>
2. 定义CSS滚动动画
根据布局需求调整动画逻辑,这里以从右向左滚动为例:
.news-scroller { position: fixed; top: 10px; left: 100%; white-space: nowrap; padding: 0 20px; /* 动画时长设为你需要的滚动时间,比如20秒 */ animation: scroll-news 20s linear forwards; } @keyframes scroll-news { to { /* 滚动到容器左侧外,确保文本完全移出视野 */ transform: translateX(calc(-100% - 100vw)); } }
3. JS监听动画结束事件
利用animationend事件,在动画真正结束时切换文本并重新触发动画:
const newsEl = document.getElementById('newsScroller'); const newsContent = [ "欢迎来到游戏,今日开启双倍经验活动!", "新地图「深渊峡谷」已上线,快来探索!", "本周排行榜前十可获得专属头像框", "修复了部分玩家技能失效的Bug" ]; let currentIdx = 0; function switchNews() { // 切换到下一条新闻 currentIdx = (currentIdx + 1) % newsContent.length; newsEl.textContent = newsContent[currentIdx]; // 重置动画:先清除动画,强制重绘后再重新添加 newsEl.style.animation = 'none'; // 强制浏览器重绘,否则动画不会重新执行 void newsEl.offsetWidth; newsEl.style.animation = 'scroll-news 20s linear forwards'; } // 绑定动画结束事件 newsEl.addEventListener('animationend', switchNews);
关键说明
animationend事件是浏览器原生支持的,会在CSS动画真正完成时触发,不受浏览器后台节流、标签切换等影响,从根源解决同步问题。- 重置动画时需要先清除动画样式,再通过
void newsEl.offsetWidth强制浏览器重绘,否则浏览器会忽略重复的动画属性,不会重新执行动画。 - 如果你的动画包含多个关键帧或多个动画,可以通过事件对象的
animationName属性判断是哪个动画结束,避免误触发:newsEl.addEventListener('animationend', (e) => { if (e.animationName === 'scroll-news') { switchNews(); } });
内容的提问来源于stack exchange,提问作者Robocittykat
相关产品推荐
相关产品推荐

