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

使用setInterval时为何仅显示一个Canvas弹跳球动画?

解决Canvas双弹跳球动画的常见问题

嘿,刚接触Canvas做动画很容易踩坑!虽然你没说具体碰到了什么问题,但根据新手常遇到的情况,我来帮你梳理一下核心问题和修正方案,顺便给你一个完整的可运行示例。

最容易踩的坑:忘记清除画布

你现在的代码里没有清除画布的逻辑,每帧绘制新的球时,旧的球会留在画布上,看起来像拖了长长的尾巴。解决方法很简单:每帧绘制前调用clearRect清空整个画布。

用requestAnimationFrame替代setInterval

setInterval的时间间隔并不精确,容易导致动画卡顿或不同步。浏览器专门为动画提供了requestAnimationFrame,它会和屏幕刷新频率同步,让动画更流畅。

完善运动与边界检测逻辑

你只给出了绘制球的函数,还需要给球添加速度、位置更新,以及碰到画布边缘反弹的逻辑——不然球只会停在原地或者跑出画布。

完整的可运行代码示例

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

<script>
const canvas = document.getElementById('bounceCanvas');
const c = canvas.getContext('2d');

// 适配窗口尺寸
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

// 蓝色球属性
let bx = 100;
let by = 100;
const bRadius = 20;
let bDx = 3; // X方向速度
let bDy = 2; // Y方向速度

// 红色球属性
let rx = 300;
let ry = 200;
const rRadius = 20;
let rDx = -2; // X方向速度
let rDy = 3; // Y方向速度

// 绘制蓝色球
function drawBCircle() { 
  c.beginPath(); 
  c.arc(bx, by, bRadius, 0, Math.PI * 2, false); 
  c.strokeStyle = "cornflowerblue"; 
  c.stroke(); 
  c.fillStyle = "cornflowerblue"; 
  c.fill(); 
  c.closePath(); 
} 

// 绘制红色球
function drawRCircle() { 
  c.beginPath(); 
  c.arc(rx, ry, rRadius, 0, Math.PI * 2, false); 
  c.strokeStyle = "red"; 
  c.stroke(); 
  c.fillStyle = "red"; 
  c.fill(); 
  c.closePath(); 
}

// 动画核心:更新位置+绘制
function animate() {
  // 第一步:清空画布!
  c.clearRect(0, 0, canvas.width, canvas.height);

  // 更新蓝色球位置与边界检测
  bx += bDx;
  by += bDy;
  if (bx + bRadius > canvas.width || bx - bRadius < 0) {
    bDx = -bDx; // 碰到左右边缘,反转X速度
  }
  if (by + bRadius > canvas.height || by - bRadius < 0) {
    bDy = -bDy; // 碰到上下边缘,反转Y速度
  }

  // 更新红色球位置与边界检测
  rx += rDx;
  ry += rDy;
  if (rx + rRadius > canvas.width || rx - rRadius < 0) {
    rDx = -rDx;
  }
  if (ry + rRadius > canvas.height || ry - rRadius < 0) {
    rDy = -rDy;
  }

  // 绘制两个球
  drawBCircle();
  drawRCircle();

  // 循环调用,持续动画
  requestAnimationFrame(animate);
}

// 启动动画
animate();
</script>

额外提示

  • 如果你的问题是两个球碰撞后不会反弹,那还需要添加球与球之间的碰撞检测逻辑(计算两球中心距离是否小于半径之和,然后调整速度),需要的话可以再问我。
  • 记得给Canvas设置尺寸,不然默认的小尺寸会导致球被拉伸。
  • 可以调整速度值来改变球的弹跳快慢,调整半径改变球的大小。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:05:46