如何仅清除canvas对象上一帧位置而非清除整个画布?
错误原因
- 上一帧坐标计算逻辑完全错误:你用数值变量
X_POS/Y_POS减去Image对象imgTag,计算结果为非法值NaN,导致clearRect接收到无效坐标,根本没有执行清除操作,之前绘制的帧自然会残留。 clearRect参数使用错误:该API的第三、第四位参数是待清除区域的宽度、高度,你传入的X_POS/Y_POS是图片的定位坐标,不是图片尺寸,就算坐标正确也无法覆盖要清除的区域。- 缺少背景补绘逻辑:你提前绘制了全局背景,清除图片区域后会把对应位置的背景也清掉,需要补绘对应区域的背景,不然会出现黑块。
推荐修正方案
小尺寸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
相关产品推荐
相关产品推荐

