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

如何修复HTML Canvas中点击添加小球数量异常递增的问题

问题解决:每次点击仅添加1个Canvas弹跳小球

问题根源

  1. addBall()函数中调用create(numBalls),而numBalls是累加变量,第一次点击传1、第二次传2……导致create内的循环执行对应次数,每次添加多个小球。
  2. create函数每次被调用都会重复添加4条边界线到lines数组,后续碰撞检测会遍历越来越多的无效线条,加剧卡顿。

修改方案

1. 分离边界线初始化,避免重复添加

把边界线创建逻辑单独抽成初始化函数,只执行一次:

// 初始化画布边界线,仅执行一次
function initCanvasBounds() {
    lines.push(new Line(-10, 10, ctx.canvas.width + 10, 5));
    lines.push((new Line(-10, ctx.canvas.height - 2, ctx.canvas.width + 10, ctx.canvas.height - 10)).reverse());
    lines.push((new Line(10, -10, 4, ctx.canvas.height + 10)).reverse());
    lines.push(new Line(ctx.canvas.width - 3, -10, ctx.canvas.width - 10, ctx.canvas.height + 10)); 
}

2. 改造create函数,仅负责创建指定数量小球

移除原create内的边界线代码,专注于小球创建:

function create(bCount) {
    while (bCount--) {
        let tries = 100;
        while (tries--) {
            const dir = Math.rand(0, Math.TAU);
            const vel = Math.rand(velMin, velMax);
            const ball = new Ball(
                Math.rand(maxBallSize + 10, canvas.width - maxBallSize - 10), 
                Math.rand(maxBallSize + 10, canvas.height - maxBallSize - 10),
                Math.cos(dir) * vel,
                Math.sin(dir) * vel,
                Math.rand(minBallSize, maxBallSize),
            )

            if (canAdd(ball)) {
                balls.push(ball);
                break;
            }
        }
    }
}

3. 修改addBall函数,每次仅创建1个小球

将调用create的参数固定为1,不再传递累加的numBalls:

function addBall() {
    numBalls++;
    ballCount.innerHTML = numBalls;
    create(1); // 强制每次仅创建1个小球
}

4. 调整初始化执行顺序

在启动主循环前,先执行边界线初始化:

initCanvasBounds();
mainLoop();

内容的提问来源于stack exchange,提问作者That New Coder

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 22:27:03