Javascript 画布精灵表错误

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

我在画布spritesheet动画中发现了一个可爱的代码片段。这是ts:

我试图通过编写一个接受图像对象的动画函数来美化这段代码,这样我就可以在画布上同时为多个图像设置动画。这是我的尝试:

    $(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);
}