簡體   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