canvas 中的多个动画

Multiple animation in canvas

我想在我的页面上制作 2 个图形的动画。因此我使用 Javascript。问题是我无法定义他必须接受哪个"sprite"。由于 requestAnimationFrame,我无法将对象 "animation" 之类的一些参数添加到 gameLoop() 方法中。知道我该如何解决这个问题吗?

var animation,
    image,
    canvas,
    stopAtLastFrame = false,
    amountAnimation = 0,
    amountAnimated = 1;

image = new Image();

function sprite (options) {
    var that = {},
        frameIndex = 0,
        currentRow = 0,
        currentColumn = 0,
        tickCount = 0,
        rowOfLastFrame = 0,
        columnOfLastFrame = 0,
        ticksPerFrame = options.ticksPerFrame,
        numberOfFrames = options.numberOfFrames,
        numberOfColumns = options.totalColumns,
        numberOfRows = options.totalRows,
        widthOfOneFrame = options.width/numberOfColumns,
        heightOfOneFrame = options.height/numberOfRows;

    that.context = options.context;
    that.width = options.width;
    that.height = options.height;
    that.image = options.image;
    rowOfLastFrame = numberOfRows-1;
    columnOfLastFrame = numberOfColumns - 1 - ((numberOfRows *numberOfColumns) - numberOfFrames);

    that.render = function () {
        that.context.save();
        that.context.scale(0.5,0.5);
        // Clear the canvas
        that.context.clearRect(0, 0, that.width, that.height);
        // Draw the animation
        that.context.drawImage(
            that.image,
            currentColumn * widthOfOneFrame,
            currentRow * heightOfOneFrame,
            widthOfOneFrame,
            heightOfOneFrame,
            0,
            0,
            widthOfOneFrame,
            heightOfOneFrame);
        that.context.restore();
        if(rowOfLastFrame==currentRow && columnOfLastFrame==currentColumn && amountAnimated==amountAnimation)
        {
            stopAtLastFrame=true;
        }
    };

    that.update = function () {
        tickCount += 1;
        if (tickCount > ticksPerFrame) {
            tickCount = 0;
                if (frameIndex < numberOfFrames-1) {
                frameIndex++;
                currentColumn++;
                if (currentColumn == numberOfColumns) {
                    currentRow++;
                    currentColumn = 0;
                }
            }else{
                amountAnimated++;
                frameIndex=0;
                currentColumn=0;
                currentRow=0;
            }
        }
    };
    return that;
}

function gameLoop () {
    if(stopAtLastFrame==true)
    {
        stopAtLastFrame=false;
    }
    else
    {
        window.requestAnimationFrame(gameLoop);

        animation.update();
        animation.render();
    }
}

function startAnimation(canvas, imageUrl, amount){
    canvas = document.getElementById(canvas);
    canvas.width = 7680/4;
    canvas.height = 2880/4;
    image.src = imageUrl;
    amountAnimation=amount;
    animation = sprite({
        context: canvas.getContext("2d"),
        width: 7684,
        height: 2880,
        image: image,
        numberOfFrames:16,
        totalRows : 4,
        totalColumns: 4,
        ticksPerFrame:  5
    });
    gameLoop();
}

startAnimation("imageAnimation", "img/16.png", 3);
startAnimation("imageAnimation2", "img/32.png", 5);

在这个例子中,我假装我的 spritesheet 具有相同的大小和列,只是为了测试代码。 这当然行不通,但这是我需要的:

function gameLoop (animation) {
        if(stopAtLastFrame==true)
        {
            stopAtLastFrame=false;
        }
        else
        {
            window.requestAnimationFrame(gameLoop(animation));

            animation.update();
            animation.render();
        }
    }

requestAnimationFrame 函数不允许传递自己的参数,一个 solution/trick 将 gameLoop 函数绑定到 sprite 对象,以便我们可以访问 this 作为 sprite 对象。

例如:http://jsfiddle.net/XQpzU/6110/

您的代码可以修改为:

    var animation,
        image,
        canvas,
        stopAtLastFrame = false,
        amountAnimation = 0,
        amountAnimated = 1;

    image = new Image();

    function sprite (options) {
        var that = {},
            frameIndex = 0,
            currentRow = 0,
            currentColumn = 0,
            tickCount = 0,
            rowOfLastFrame = 0,
            columnOfLastFrame = 0,
            ticksPerFrame = options.ticksPerFrame,
            numberOfFrames = options.numberOfFrames,
            numberOfColumns = options.totalColumns,
            numberOfRows = options.totalRows,
            widthOfOneFrame = options.width/numberOfColumns,
            heightOfOneFrame = options.height/numberOfRows;

        that.context = options.context;
        that.width = options.width;
        that.height = options.height;
        that.image = options.image;
        rowOfLastFrame = numberOfRows-1;
        columnOfLastFrame = numberOfColumns - 1 - ((numberOfRows *numberOfColumns) - numberOfFrames);

        that.render = function () {
            that.context.save();
            that.context.scale(0.5,0.5);
            // Clear the canvas
            that.context.clearRect(0, 0, that.width, that.height);
            // Draw the animation
            that.context.drawImage(
                that.image,
                currentColumn * widthOfOneFrame,
                currentRow * heightOfOneFrame,
                widthOfOneFrame,
                heightOfOneFrame,
                0,
                0,
                widthOfOneFrame,
                heightOfOneFrame);
            that.context.restore();
            if(rowOfLastFrame==currentRow && columnOfLastFrame==currentColumn && amountAnimated==amountAnimation)
            {
                stopAtLastFrame=true;
            }
        };

        that.update = function () {
            tickCount += 1;
            if (tickCount > ticksPerFrame) {
                tickCount = 0;
                    if (frameIndex < numberOfFrames-1) {
                    frameIndex++;
                    currentColumn++;
                    if (currentColumn == numberOfColumns) {
                        currentRow++;
                        currentColumn = 0;
                    }
                }else{
                    amountAnimated++;
                    frameIndex=0;
                    currentColumn=0;
                    currentRow=0;
                }
            }
        };
        that.gameLoop = gameLoop.bind(that);
        return that;
    }

    function gameLoop () {
        if(stopAtLastFrame==true)
        {
            stopAtLastFrame=false;
        }
        else
        {
            // this will be your sprite

            window.requestAnimationFrame(this.gameLoop);

            animation.update();
            animation.render();
        }
    }

    function startAnimation(canvas, imageUrl, amount){
        canvas = document.getElementById(canvas);
        canvas.width = 7680/4;
        canvas.height = 2880/4;
        image.src = imageUrl;
        amountAnimation=amount;
        animation = sprite({
            context: canvas.getContext("2d"),
            width: 7684,
            height: 2880,
            image: image,
            numberOfFrames:16,
            totalRows : 4,
            totalColumns: 4,
            ticksPerFrame:  5
        });
        animation.gameLoop();
    }

    startAnimation("imageAnimation", "img/16.png", 3);
    startAnimation("imageAnimation2", "img/32.png", 5);