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

求助:如何设置定时器实现随机圆形动画的无限循环生成?

问题分析与修复:圆形依次出现+循环动画失效问题

问题原因拆解

1. 全局变量导致setTimeout后参数被覆盖

你代码里的X、Y、Size、RGB未用let/const声明,属于全局变量。当用setTimeout(circ, N * 100)延迟执行时,forEach循环会先跑完所有迭代,这些变量会被最后一次循环的值完全覆盖,最终所有延迟触发的circ函数都使用最后一个圆的参数,看起来就只显示了一个圆。

2. 循环调用时CSS动画未重新触发

CSS的animation默认仅执行一次,当循环调用go函数重置圆的样式时,元素的animation属性没有发生变化,浏览器不会重新触发动画逻辑,导致后续循环看不到放大渐隐的效果。

修复方案

核心修复点

  • 给变量添加let声明,限定作用域在每次循环内
  • 通过强制重绘的方式,让CSS动画在循环时重新触发
  • 调整循环延迟时间,确保上一轮动画完全结束后再启动下一轮

修改后的完整代码

HTML(无改动)

<html>
    <head>
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
        <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 src="script.js"></script>
    </body>
</html>

CSS(微调动画状态)

body {
    background-color: #000;
    width: 100vw;
    height: 100vh;
    margin: 0;
    overflow: hidden;
}

.circle {
    position: absolute;
    border-radius: 50%;
    transform: translate(-50%, -50%) scale(0.1);
    opacity: 1;
    animation: scale 1s ease-out forwards;
}

@keyframes scale {
    to {
        transform: translate(-50%, -50%) scale(3);
        opacity: 0;
    }
}

JS(修复作用域+重新触发动画+循环调用)

const circles = document.querySelectorAll('.circle')

function getRandomCircleProps() {
    const width = window.innerWidth
    const height = window.innerHeight
    return {
        x: Math.floor(Math.random() * width),
        y: Math.floor(Math.random() * height),
        size: Math.floor((Math.random() * 6) + 5) * 10,
        color: `#${Math.floor(Math.random() * 0xFFFFFF).toString(16).padStart(6, '0')}`
    }
}

function go() {
    let delay = 0
    circles.forEach(circle => {
        const {x, y, size, color} = getRandomCircleProps()
        
        setTimeout(() => {
            // 强制重新触发动画:先移除类,强制重绘后再加回
            circle.classList.remove('circle')
            void circle.offsetWidth
            circle.classList.add('circle')
            
            // 设置随机样式
            circle.style.left = `${x}px`
            circle.style.top = `${y}px`
            circle.style.width = `${size}px`
            circle.style.height = `${size}px`
            circle.style.backgroundColor = color
        }, delay)
        
        delay += 100
    })
    
    // 等待上一轮所有动画结束(10个圆共1s动画+0.1s缓冲)后重启循环
    setTimeout(go, 1100)
}

go()

内容的提问来源于stack exchange,提问作者Blackwolf

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 00:22:07