如何用 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 html><html><head> <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></head><body> <!-- 10 个占位圆点 --> <span class="circle"></span> <span class="circle"></span> <span class="circle"></span> <span class="circle"></span> <span class="circle"></span> <span class="circle"></span> <span class="circle"></span> <span class="circle"></span> <span class="circle"></span> <span class="circle"></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是一款自动视频编辑工具,可以将文本、文章或故事转换为视频。

相关推荐
EQUINOX11 小时前
【论文阅读】| MoCo精读
论文阅读·人工智能·python·深度学习·机器学习
哥是强混1 小时前
Means:基于 .NET 10 打造的开源自部署 S3 兼容对象存储服务
网络·数据库·.net
ffqws_1 小时前
redis面试:如何保证双写一致
数据库·redis·缓存
水无痕simon2 小时前
6 数据库同义词
数据库
用户8356290780512 小时前
使用 Python 自动化 Excel 公式和函数:完整指南
后端·python
敲代码的嘎仔2 小时前
实习日志day6--实习日志day6--title命名规范化&businessType纠正&补充缺失的@Log注解&报警与通信模块补充&产出阶段总结文档
java·开发语言·人工智能·git·python·实习·大二
江华森2 小时前
Python 实现高德地图找房(一):环境搭建与数据爬虫
开发语言·爬虫·python
杜子不疼.2 小时前
【Qt初识】信号槽(三):机制意义、断开连接与 Lambda 表达式
开发语言·数据库·qt
VIP_CQCRE3 小时前
用 Ace Data Cloud 快速接入 OpenAI Chat Completions:对话、流式、多轮和多模态一篇打通
python·ai·openai·api·教程
AOwhisky3 小时前
Python 学习笔记(第三期)——流程控制:条件判断与循环结构
运维·笔记·python·学习·云原生·流程控制·循环