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

Canvas中弹跳方块边缘缩放功能失效问题排查

Canvas方块碰撞边缘卡顿且尺寸异常增长的修复方案

问题根源

  1. 位置未修正导致重复碰撞:当方块触达边缘并增大尺寸后,新尺寸会让边界判断条件(比如x >= canvas.width - size)仍然成立,下一帧会再次触发碰撞逻辑,反复反转方向并放大尺寸,最终卡滞在边缘,尺寸呈指数级增长。
  2. 尺寸增长无限制触发:每次碰撞都会无条件执行尺寸放大,即使碰撞是上一次尺寸变化引发的“伪碰撞”,也会重复触发增长操作。

修复方案

  1. 碰撞时先修正位置:在反转运动方向前,将方块位置调整到画布合法范围内,避免尺寸变化后仍满足碰撞条件。例如:
    • 碰到左边缘:x = 0
    • 碰到右边缘:x = canvas.width - size
    • 碰到上边缘:y = 0
    • 碰到下边缘:y = canvas.height - size
  2. 确保单次碰撞仅触发一次尺寸增长:通过位置修正,让碰撞后的方块不再满足边界判断条件,避免同一碰撞事件被多次触发。

修正后的代码

JavaScript

canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");

canvas.width = parseInt(window.innerWidth, 10);
canvas.height = parseInt(window.innerHeight, 10);

let x = 0;
let y = 0;
let size = 50;
let dx = 5;
let dy = 5;
let hue = 0;

function animate() {
    x += dx;
    y += dy;

    hue = (hue + 10) % 360;

    // 处理水平方向碰撞
    if (x <= 0 || x >= canvas.width - size) {
        dx = -dx;
        // 修正位置,避免尺寸变化后再次触发碰撞
        x = x <= 0 ? 0 : canvas.width - size;
        size = Math.ceil(size * 1.10);
    }

    // 处理垂直方向碰撞
    if (y <= 0 || y >= canvas.height - size) {
        dy = -dy;
        // 修正位置,避免尺寸变化后再次触发碰撞
        y = y <= 0 ? 0 : canvas.height - size;
        size = Math.ceil(size * 1.10);
    }

    ctx.fillStyle = `hsl(${hue}, 100%, 50%)`;
    ctx.fillRect(x, y, size, size);
    ctx.strokeStyle = 'black';
    ctx.lineWidth = 1;
    ctx.strokeRect(x, y, size, size);

    window.requestAnimationFrame(animate);
}

animate();

HTML

<canvas id="canvas"></canvas>

额外优化建议

如果希望方块运动更平滑,还可以考虑:

  • 尺寸增长后,根据新尺寸微调位置偏移,避免方块出现突兀的“跳跃感”
  • 设置最大尺寸阈值,防止方块过大后无法在画布内继续运动

内容的提问来源于stack exchange,提问作者Matías Cánepa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 12:03:39