如何用 CSS 动画与 animationend 事件实现循环渐进式圆点动画

张开发
2026/4/20 22:21:16 15 分钟阅读

分享文章

如何用 CSS 动画与 animationend 事件实现循环渐进式圆点动画
本文详解如何通过分离动画类、利用 animationend 事件触发链式执行配合 setTimeout 实现 10 个圆点依次随机出现、缩放淡出并无限循环——彻底解决定时器重置导致动画失效的问题。 本文详解如何通过分离动画类、利用 animationend 事件触发链式执行配合 settimeout 实现 10 个圆点依次随机出现、缩放淡出并无限循环——彻底解决定时器重置导致动画失效的问题。要实现「10 个圆点在 1 秒内以 0.1 秒间隔依次随机出现 → 各自从中心缩放放大并透明度归零 → 整个序列无缝循环」的效果关键不在于堆叠 setTimeout 或强行重启函数而在于解耦样式状态与动画触发时机。原始代码中直接在 forEach 中连续调用 circ() 并依赖 setTimeout(..., N * 100) 启动动画会导致所有圆点共享同一轮动画状态更严重的是CSS 动画在 class 未变化时不会重播即使 animation 属性值未变因此后续循环中 .circle 元素无法再次触发动画。? 正确解法的核心是三步策略 分离动画控制类将 animation 声明移至独立类如 .anim而非写死在基础 .circle 上 动态增删动画类每次展示前先移除 .anim再通过 setTimeout 异步添加强制浏览器重绘并触发新动画 用 animationend 驱动下一轮每个圆点动画结束时监听事件递归调度自身下一次出现形成闭环避免全局 setTimeout(go, 1000) 破坏节奏。以下是完整可运行实现!DOCTYPE htmlhtmlhead style body { background-color: #000; width: 100vw; height: 100vh; margin: 0; overflow: hidden; position: relative; /* 确保绝对定位子元素相对于 viewport */ } .circle { position: absolute; border-radius: 50%; transform: translate(-50%, -50%) scale(0.1); /* 初始状态无动画 */ } .anim { animation: scale 1s ease-out forwards; } keyframes scale { to { transform: translate(-50%, -50%) scale(3); opacity: 0; } } /style/headbody !-- 10 个占位圆点 -- span classcircle/span span classcircle/span span classcircle/span span classcircle/span span classcircle/span span classcircle/span span classcircle/span span classcircle/span span classcircle/span span classcircle/span script function go() { const circles document.querySelectorAll(.circle); const width window.innerWidth; const height window.innerHeight; const createCircleStyle () { const X Math.floor(Math.random() * width); const Y Math.floor(Math.random() * height); const Size Math.floor((Math.random() * 6) 5) * 10; const R Math.floor(Math.random() * 255).toString(16).padStart(2, 0); const G Math.floor(Math.random() * 255).toString(16).padStart(2, 0); const B Math.floor(Math.random() * 255).toString(16).padStart(2, 0); return { left: ${X}px, top: ${Y}px, width: ${Size}px, height: ${Size}px, backgroundColor: #${R}${G}${B} }; }; const animateCircle (circle) { const style createCircleStyle(); // 清除动画类重置状态 circle.classList.remove(anim); Object.assign(circle.style, style); // 异步添加动画类确保样式已应用后再触发动画 setTimeout(() circle.classList.add(anim), 0); }; // 为每个圆点绑定 animationend 事件实现自我循环 circles.forEach((circle, index) { circle.addEventListener(animationend, () animateCircle(circle)); // 初始序列第 i 个圆点延迟 i × 100ms 启动 setTimeout(() animateCircle(circle), index * 100); }); } // 首次启动 go(); // 可选响应窗口大小变化如旋转设备 window.addEventListener(resize, () { // 重置所有圆点位置/尺寸需重新触发此处仅做示意 document.querySelectorAll(.circle).forEach(c c.classList.remove(anim)); }); /script/body/html? 关键注意事项 Tellers AI Tellers是一款自动视频编辑工具可以将文本、文章或故事转换为视频。

更多文章