如何用 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是一款自动视频编辑工具,可以将文本、文章或故事转换为视频。

相关推荐
黑马水牛1 分钟前
Carla仿真系列:9_Carla 单目障碍物测距,四种方法原理与实测
经验分享·python·深度学习·计算机视觉·ros·传感器·carla仿真
茉莉玫瑰花茶7 分钟前
SQL 调优 [ 1 ]
数据库·sql
Databend7 分钟前
从传统分区到微分区,Snowflake 与 Databend 如何减少数据扫描
大数据·数据库·sql
ruleslol17 分钟前
Redis 雪崩与服务降级
数据库·redis
Python私教29 分钟前
多个项目怎么安全合并?适配层、双轨验证与可回滚切换
python·软件架构·系统迁移
船厂电气自动化ai大模型40 分钟前
AI大模型与数学第42课:泰勒级数完整展开(神经网络近似核心)
人工智能·python·深度学习·算法·机器学习
易番番ERP1 小时前
品牌代理商SKU繁多,ERP如何高效处理新旧规格替换?
数据库·微服务·云原生·sku·易番番erp
leo_yu_yty1 小时前
Mysql 面试准备
数据库·mysql·面试
刘新洲1 小时前
我以为 AI Agent 只是调模型,直到我亲手补上审批、Outbox 和故障恢复
python·agent·fastapi
SelectDB1 小时前
拉卡拉统一金融 OLAP:基于 Apache Doris / SelectDB 实现查询提速 15 倍、资源直降 52%
数据库