Javascript 清除画布对象的以前位置,而不是整个画布

Javascript 清除画布对象的以前位置,而不是整个画布,javascript,html,canvas,Javascript,Html,Canvas,我相信有一个逻辑错误,我的逻辑是为了找到我的画布对象的先前坐标,一个运动图像,并删除在它之前绘制的帧,这样它就不会在每次绘制到画布上时复制图像 下面有一个可复制的演示,我在我认为出现问题的地方添加了评论 var canvas=document.getElementById(“c”); var ctx=canvas.getContext(“2d”); var the_background=document.getElementById(“the_background”); var imgTag=

我相信有一个逻辑错误,我的逻辑是为了找到我的画布对象的先前坐标,一个运动图像,并删除在它之前绘制的帧,这样它就不会在每次绘制到画布上时复制图像

下面有一个可复制的演示,我在我认为出现问题的地方添加了评论

var canvas=document.getElementById(“c”);
var ctx=canvas.getContext(“2d”);
var the_background=document.getElementById(“the_background”);
var imgTag=新图像();
var X_POS=画布宽度;
变量Y_POS=0;
imgTag.src=”http://i.stack.imgur.com/Rk0DW.png"; // 加载图像
函数animate(){
/*错误就在这里*/
var-coords={};
coords.x=数学地板(this.x_POS-imgTag);
coords.y=数学楼层(this.y_POS-imgTag);
ctx.clearRect(coords.x,coords.y,x_POS,y_POS);
/*到这里*/
ctx.drawImage(imgTag、X_位置、Y_位置);
X_POS-=5;
如果(X_POS>200)请求动画帧(动画)
}
window.onload=函数(){
ctx.drawImage(_背景,0,0,canvas.width,canvas.height);
制作动画();
}
html,
身体{
宽度:100%;
身高:100%;
边际:0px;
边界:0;
溢出:隐藏;
显示:块;
}

只清除正在更改的画布子集似乎是合乎逻辑的,但通常的方法是每帧清除并重新绘制整个画布。汽车移动后,需要填充其下方已清除的背景,并尝试仅重新绘制该子集将导致视觉伪影和总体混乱。清除屏幕的一小部分是过早的优化

画布无法跟踪像素以外的任何内容,因此动画更像是静止帧的动画书,而不像纸板剪切动画,相同的纸板片在其中移动并相互重叠

Math.floor(this.X_POS-imgTag)
看起来不对--
imgTag
是一个图像对象,从数字中减去它没有意义。您可能想从中获取
x
属性

使用
image.onload
确保在运行循环之前实际加载映像。在DOM中使用图像标记只是为了加载画布的图像,这有点奇怪。我会通过JS编程实现这一点,这样可以节省一些输入并使数据管理更容易

const loadImg=url=>新承诺((解析、拒绝)=>{
const img=新图像();
img.onerror=拒绝;
img.onload=()=>resolve(img);
img.src=url;
});
常量图像=[
"https://img.freepik.com/free-photo/hand-painted-watercolor-background-with-sky-clouds-shape_24972-1095.jpg?size=626&ext=jpg",
"http://i.stack.imgur.com/Rk0DW.png",
];
允诺
.all(images.map(loadImg))
.然后(([backgroundImg,carImg])=>{
const canvas=document.getElementById(“canvas”);
const ctx=canvas.getContext(“2d”);
const car={x:canvas.width,y:0};
(函数更新(){
clearRect(0,0,canvas.width,canvas.height);
ctx.drawImage(
背景img,0,0,canvas.width,canvas.height
);
ctx.drawImage(
carImg,car.x,car.y,carImg.宽度,carImg.高度
);
car.x-=5;
如果(汽车x>200){
requestAnimationFrame(更新);
}
})();
})
.catch(err=>console.error(err))
;

好的,谢谢你的全面回复,因为我知道画布是如何在图像对象被重画时运行的。我还看到您创建了一个名为
Promise
的类,但我的问题是
。所有(images.map(loadImg))
。然后(([backgroundImg,carImg])
按照我想理解的逻辑部分去做。请参阅文档,和