Javascript 画布精灵表错误
我在画布spritesheet动画中发现了一个可爱的代码片段。这是ts: 我试图通过编写一个接受图像对象的动画函数来美化这段代码,这样我就可以在画布上同时为多个图像设置动画。这是我的尝试:Javascript 画布精灵表错误,javascript,html,canvas,sprite-sheet,Javascript,Html,Canvas,Sprite Sheet,我在画布spritesheet动画中发现了一个可爱的代码片段。这是ts: 我试图通过编写一个接受图像对象的动画函数来美化这段代码,这样我就可以在画布上同时为多个图像设置动画。这是我的尝试: $(function(){ var canvas=document.getElementById("canvas"); var ctx=canvas.getContext("2d"); var spritePosition=0; var
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var spritePosition=0;
var spriteWidth=100;
var spriteHeight=100;
var spriteCount=40;
var spritePlayCount=0;
var maxSpritePlays=2;
var objectS=new Image();
objectS.src="sprites/first.png";
var fps = 50;
function animate(sprite) {
setTimeout(function() {
if(spritePlayCount<maxSpritePlays){
requestAnimationFrame(animate);
}
// Drawing code goes here
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.drawImage(sprite,spritePosition*spriteWidth, 0,spriteWidth, spriteHeight, 0,0,spriteWidth, spriteHeight);
spritePosition++;
if(spritePosition>spriteCount-1){
spritePosition=0;
spritePlayCount++;
}
}, 1000 / fps);
}
objectS.onload=function(){
animate(objectS);
}
}); // end $(function(){});
我发现了一个非常明显的错误,但我似乎找不到解决方法:
index3.html:59未捕获类型错误:无法在上执行“drawImage”
“CanvasRenderingContext2D”:提供的值不是类型
'CSSImageValue或HTMLImageElement或HTMLVideoElement或
HTMLCanvasElement或ImageBitmap或OffscreenCavas'
你能帮我找到我的bug吗?在使用requestAnimationFrame调用animate函数时,你还需要传递sprite参数 天哪!
想象一下,你有50张精灵表要制作动画 五十 查看代码接受的答案版本
function animate(sprite) {
// create a timer event to fire in 1/50th second
setTimeout(function() {
if (spritePlayCount < maxSpritePlays) {
// create a animation frame event that may fire at some time
// between 0 and 16ms or 32ms from now
requestAnimationFrame(function() {
animate(sprite);
});
}
// Drawing code etc... Make canvas dirty
// exiting with dirty canvas outside the requestAnimationFrame
// forces DOM to swap canvas backbuffer immediately on exit.
}, 1000 / 50);
}
这是最糟糕的动画制作方法,更不用说多个精灵了
时间与显示屏刷新不同步。
使用requestAnimationFrame的回调创建渲染的定时事件,完全否定了使用requestAnimationFrame的原因。requestAnimationFrame告诉DOM您在回调中绘制的内容是动画的一部分。使用计时器绘制意味着您不会在请求的帧中绘制任何内容,从而使请求变得多余。
requestAnimationFrame尽最大努力在下一次显示刷新1/60之前获取所有回调,但如果在下一次刷新之前没有时间更新DOM交换所有脏缓冲区,它将延迟回调。您无法控制动画的计时,它们可能会在20毫秒到36毫秒或更长时间内的任何位置触发,并且随着时间的推移没有一致性。
通过使用计时器绘制到画布,您正在为绘制的每个精灵强制backbuffer交换。这是一个昂贵的过程,将严重限制绘制精灵的速度,并导致精灵在动画期间随机闪烁和剪切。
最佳实践方法
使用由requestAnimationFrame触发的单个动画循环。
使用数组存储所有精灵,并根据需要在主循环中更新它们。
仅从主循环中渲染。在主循环执行之外,不要以固定的间隔向DOM渲染或执行任何操作。
不要渲染内部事件,如计时器、IO或任何其他快速触发事件。
想象一下,有50张你想要设置动画的精灵表。这可能是50个函数调用或1000行代码,因为我没有重新构造代码。显然,将代码重写为接受参数的函数是必要的。
function animate(sprite) {
// create a timer event to fire in 1/50th second
setTimeout(function() {
if (spritePlayCount < maxSpritePlays) {
// create a animation frame event that may fire at some time
// between 0 and 16ms or 32ms from now
requestAnimationFrame(function() {
animate(sprite);
});
}
// Drawing code etc... Make canvas dirty
// exiting with dirty canvas outside the requestAnimationFrame
// forces DOM to swap canvas backbuffer immediately on exit.
}, 1000 / 50);
}