在HTML5画布上使用drawImage的奇怪错误

时间:2013-11-22 21:01:00

标签: javascript html5 canvas

JsFiddle(注意:它没有显示任何内容,它只是我用一种整洁的格式显示我的代码的一种方式)http://jsfiddle.net/h6tVR/

我是HTML5画布的新手,决定玩一下,看看我能用它做些什么。到目前为止,我已经能够在画布上绘制本地托管的图像,甚至可以做一些基本的平铺:

window.onload = function(){

    var GameClosure = function() {

        var canv = document.getElementById("canv");
        var canvContext = canv.getContext("2d");

        var sprite = new Image();
        sprite.src = "sprite.png"

        var tile = new Image();
        tile.src = "tile.png"

        function loadSprite(){
            sprite.onload = function(){
                canvContext.drawImage(sprite, 50, 50);
                };
        }

        function loadTiles(){
            tile.onload = function(){
                for(var i = 0; i < 800; i += 16){
                    for(var r = 0; r < 608; r += 16){
                        canvContext.drawImage(tile, i, r);
                    }
                }
            };
        }

        return{
            loadTiles: loadTiles,
            loadSprite: loadSprite
            };

    }();

    GameClosure.loadTiles();
    GameClosure.loadSprite();

}

我遇到了一个奇怪的问题。当我加载它时,大多数时候,只有瓷砖会加载。到目前为止,我已经尝试了几件事,我已经切换了GameClosure.loadTiles() and GameClosure.loadSprite();次调用,看看加载顺序是否有所不同。它没有。我甚至尝试创建第二个上下文并将tile分配给一个,将sprite分配给另一个,但这没有任何区别。注释掉tile调用会正确生成精灵。

甚至更奇怪。我正在快速刷新页面,我偶尔注意到(没有模式,有时它可能连续发生3次,其他时间一次发生在20次),瓷砖会加载并且精灵会加载到顶部,就像我期望的那样到。

这可以修复吗?我唯一的猜测是我的代码运行有点异步,并且在加载sprite之后创建tile的for循环正在完成,但是查看我的代码我看不出这可能发生的地方。

2 个答案:

答案 0 :(得分:2)

分开关注点。等待加载所有资源(和文档),然后启动游戏。始终确保在分配src之前挂钩事件处理程序以避免“随机”(事实上与缓存相关)行为。

答案 1 :(得分:1)

当您设置onload处理程序时,您的javascript将在资源在后台加载时继续。处理器将在资源加载时执行。你无法分辨何时会发生这种情况以及以何种顺序发生。

如果您有多个资源并想在最后一个加载时调用绘图函数,那么您可以拥有一个全局预加载器对象。每个onload-handler应该调用预加载器上的一个函数来通知它资源已经加载。该函数应该检查是否所有资源都已报告,并且在这种情况下执行draw-function。

此外,当您设置onload-handler并且资源已加载时。当您设置.src并且资源位于浏览器缓存中时,它将立即加载。因此,您始终需要首先设置.onload然后设置.src