You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 12:05:08