javascript - Canvas Sprite 表错误

原文 标签 javascript html canvas sprite-sheet

我在 Canvas spritesheet 动画上找到了一个可爱的代码片段。这是 ts:

http://jsfiddle.net/m1erickson/h85Gq/

我试图通过编写一个接受 Image 对象的 animate 函数来美化这段代码,以便我可以同时为 Canvas 中的多个图像设置动画。这是我的尝试:

    $(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 Uncaught TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas)'



你能帮我找出我的错误吗?

最佳答案

天啊!

quote OP "Imagine having 50 spritesheets you want to animate."


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);
}
这是动画一个最糟糕的方法,更不用说多个 Sprite 了。
  • 时间与显示刷新不同步。
  • 使用 requestAnimationFrame 的回调来创建渲染的定时事件,完全否定了使用 requestAnimationFrame 的原因。 requestAnimationFrame 告诉 DOM 您在回调中绘制的内容是动画的一部分。使用计时器进行绘制意味着您不会在请求的帧中绘制任何内容,从而使请求变得多余。
  • requestAnimationFrame 尽最大努力在下一次显示刷新(1/60)之前获取所有回调,但如果在下一次刷新之前没有时间更新 DOM(交换所有脏缓冲区),它将延迟回调。您无法控制动画的时间,它们可能会在 20 毫秒到 36 毫秒或更长时间的任何时间触发,并且随着时间的推移没有一致性。
  • 通过使用计时器在 Canvas 上绘制,您将强制为您绘制的每个 Sprite 进行后台缓冲交换。这是一个昂贵的过程,会严重限制您绘制 Sprite 的速度,并导致 Sprite 在动画过程中随机闪烁和剪切。

  • 最佳实践方式。
  • 使用由 requestAnimationFrame 触发的单个动画循环。
  • 使用数组来存储所有 Sprite ,并根据需要在主循环中更新它们。
  • 仅从主循环内渲染。不要在主循环执行之外对 DOM 进行渲染或执行任何操作(定期)。
  • 不要渲染内部事件,如计时器、IO 或任何其他快速触发的事件。
  • 关于javascript - Canvas Sprite 表错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43159465/

    相关文章:

    python - GAE 是否支持 django 管理表单

    python - 如何使圆的运动更流畅?

    html - 加载时更改的默认文本框值

    javascript - 鼠标悬停在div上时,JavaScript文件应加载

    javascript - 如何同步2 iframe的滚动条

    java - 如何在解析html页面时从html页面中的javascript函数中提取变量的值

    css - 在 div 中使用两种类型的测量(仅 css?)

    javascript - KineticJS 调整文本大小以适合带有一些填充的矩形

    javascript - 在 Vuex 中存储 Fabric.js Canvas 引用 - [vuex] 不要在变异处理程序之外改变 vuex 存储状态

    javascript - 捕获所选单词出现的句子