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

如何仅清除canvas对象上一帧位置而非清除整个画布?

错误原因

  1. 上一帧坐标计算逻辑完全错误:你用数值变量X_POS/Y_POS减去Image对象imgTag,计算结果为非法值NaN,导致clearRect接收到无效坐标,根本没有执行清除操作,之前绘制的帧自然会残留。
  2. clearRect参数使用错误:该API的第三、第四位参数是待清除区域的宽度、高度,你传入的X_POS/Y_POS是图片的定位坐标,不是图片尺寸,就算坐标正确也无法覆盖要清除的区域。
  3. 缺少背景补绘逻辑:你提前绘制了全局背景,清除图片区域后会把对应位置的背景也清掉,需要补绘对应区域的背景,不然会出现黑块。

推荐修正方案

小尺寸canvas直接用「每次渲染前全量重绘背景」的方案即可,逻辑简单不易出错,性能也完全足够,修正后的核心代码如下:

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

var imgTag = new Image();
var X_POS = canvas.width;
var Y_POS = 0;

imgTag.src = "https://i.sstatic.net/Rk0DW.png";

function animate() {
  // 全量重绘背景,直接覆盖之前所有绘制内容,不需要手动计算清除区域
  ctx.drawImage(the_background, 0, 0, canvas.width, canvas.height);
  // 绘制当前帧的移动图片
  ctx.drawImage(imgTag, X_POS, Y_POS);
  X_POS -= 5;
  if (X_POS > 200) requestAnimationFrame(animate)
}

window.onload = function() {
  animate();
}

如果要追求极致性能,只清除上一帧的图片区域,可以用下面的方案:

function animate() {
  // 先清除上一帧图片的绘制区域
  ctx.clearRect(X_POS, Y_POS, imgTag.width, imgTag.height);
  // 补绘被清除区域的背景
  ctx.drawImage(
    the_background, 
    X_POS, Y_POS, imgTag.width, imgTag.height, 
    X_POS, Y_POS, imgTag.width, imgTag.height
  );
  // 更新坐标
  X_POS -= 5;
  // 绘制当前帧图片
  ctx.drawImage(imgTag, X_POS, Y_POS);
  if (X_POS > 200) requestAnimationFrame(animate)
}

剩余的CSS、HTML代码不需要修改可以直接使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 01:54:06