【问题标题】:Multiple animation in canvas画布中的多个动画
【发布时间】:2015-07-18 00:42:25
【问题描述】:

我想在我的页面上为 2 个人物设置动画。因此我使用Javascript。问题是我无法定义他必须采用哪个“精灵”。因为 requestAnimationFrame 的原因,我无法将对象“动画”之类的参数添加到 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);

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

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

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

【问题讨论】:

    标签: javascript animation sprite-sheet


    【解决方案1】:

    requestAnimationFrame 函数不允许传递你自己的参数,一个解决方案/技巧将 gameLoop 函数绑定到精灵对象,这样我们就可以访问this 作为精灵对象。

    例如: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);
    

    【讨论】:

    • 谢谢,对我帮助很大:)
    • 是否也可以给函数添加回调?我想知道我的动画什么时候完成。所以当“this.stopAtLastFrame == true”时,我想得到一个消息,所以我可以和应用程序一起去。
    • 变量this绑定到你的gameLoop函数,所以你可以访问this的任何属性,例如this.context, this.width,只需将你的回调作为类sprite的属性,你可以通过this访问它
    猜你喜欢
    • 1970-01-01
    • 2016-04-29
    • 1970-01-01
    • 2017-10-21
    • 2015-10-22
    • 2021-11-03
    • 2011-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多