繁体   English   中英

画布精灵表错误

[英]canvas sprite sheet error

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

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

我试图通过编写一个接受Image对象的动画函数来美化此代码,以便可以同时对画布中的多个图像进行动画处理。 这是我的尝试:

    $(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未捕获的TypeError:无法在'CanvasRenderingContext2D'上执行'drawImage':提供的值不是'(CSSImageValue或HTMLImageElement或HTMLVideoElement或HTMLCanvasElement或ImageBitmap或OffscreenCanvas)类型的值

你能帮我找到我的虫子吗?

OMDG!

引用OP “想象一下,要创建50个要制作动画的Spritesheets。”

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

这是制作一个动画的最糟糕的方法,更不用说一个以上的精灵了。

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

最佳做法。

  • 使用由requestAnimationFrame触发的单个动画循环。
  • 使用数组存储所有精灵,并根据需要在主循环中更新它们。
  • 仅从主循环内渲染。 不要在主循环执行之外对DOM进行渲染或进行任何操作(以固定间隔)。
  • 不要渲染内部事件,例如计时器,IO或任何其他快速触发事件。

使用requestAnimationFrame调用动画函数时,还需要传递sprite参数。

$(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(function() {
                    animate(sprite);
                });
            }
            // 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);
    };
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM