0

再次回来问愚蠢的问题...... :)

我做了一些功能,一个用于存储图像,一个用于检索,一个用于检查图像是否已加载。图像存储在这样的数组中:

tiles = [ ["ID", "Image Object", "Loaded boolean"] ];

然而,Javascript 运行我的代码的顺序让我大吃一惊。我添加了几个 console.logs 来查看代码中发生了什么,这就是我得到的:

    START
    Storing http://funxion.wippiespace.com/js/mario/question.gif...  
    Storing http://funxion.wippiespace.com/js/mario/wall.gif...  
    Storing http://funxion.wippiespace.com/js/mario/floor.gif...  
    Map.draw initiated  
    Checking if all images are loaded...  
    Amount of tile images = 3  
    Checking [0]  
    [0]: q,[object HTMLImageElement],false is not loaded  
    Images not loaded!  
    http://funxion.wippiespace.com/js/mario/question.gif stored!  
    http://funxion.wippiespace.com/js/mario/wall.gif stored!  
    http://funxion.wippiespace.com/js/mario/floor.gif stored!  

我不明白为什么loaded=true 是最后一件事。另外,我试过把 setTimeout(this.draw, 1000); 在 Map.prototype.draw 中,因此在再次检查 allImgLoaded 之前会有 1 秒的延迟,这是行不通的。没有加载检查图纸工作正常。此外, Start() 在 .

编码:

    var canvas = document.getElementById("surface");
    var ctx = canvas.getContext("2d");

    function Map()
    {
        this.tiles = [];
    }
    Map.prototype.draw = function(tileid)
    {
        console.log("Map.draw initiated");
        if (!allImgLoaded(this.tiles))
        {
            console.log("Images not loaded!");
        }
        else
        {
            console.log("All good, proceeding.");
            var img = this.getImg(tileid);
            ctx.drawImage(img, 100, 100);
        }
    }
    Map.prototype.storeImg = function(identifier, imgSrc)
    {
        var nextIndex = this.tiles.length;
        var tile = [identifier, new Image(), false];
        tile[1].src = imgSrc;
        console.log("Storing " + imgSrc + "...");
        tile[1].onload = function()
        {
            tile[2] = true;
            console.log(this.src + " stored!");
        }
        this.tiles[nextIndex] = tile;

    }
    Map.prototype.getImg = function(identifier)
    {
        for (var i in this.tiles)
        {
            console.log("Checking index " + i + " for " + identifier + "...");
            if (this.tiles[i][0] === identifier)
            {
                console.log("Found " + this.tiles[i][1] + "! Returning it now.");
                return this.tiles[i][1];
            }
        }
    }

    function allImgLoaded(array)
    {
        console.log("Checking if all images are loaded...");
        console.log("Amount of tile images = " + array.length);
        for (var i in array)
        {
            console.log("Checking ["+i+"]");
            if(array[i][2] === false)
            {
                console.log("["+i+"]: " + array[i] + " is not loaded");
                return false;
            }
        }
        console.log("All loaded!");
        return true;
    }
    function Start()
    {
        console.log("START");
        var mappi = new Map();
        mappi.storeImg("q", "http://funxion.wippiespace.com/js/mario/question.gif");
        mappi.storeImg("w", "http://funxion.wippiespace.com/js/mario/wall.gif");
        mappi.storeImg("f", "http://funxion.wippiespace.com/js/mario/floor.gif");
        mappi.draw("w");
    }
4

1 回答 1

0

您似乎不了解图像的加载是异步的。它发生在后台,而您的其他 javascript 继续运行。您开始操作,您的其他代码继续运行,一段时间后图像完成加载 onload 回调函数被调用。

如果要在加载图像后运行操作,则需要从该图像的 onload 处理程序启动该操作。现在您的代码开始加载所有图像,然后mappi.draw()在图像加载完成之前立即调用。更具体地说.storeImg(),只是开始加载图像。图像的实际加载直到一段时间后才完成(正如您从console.log()跟踪中看到的那样。

如果您想预加载一堆图像,然后在加载所有图像时触发操作,您可以使用此答案中的代码:Image preloader javascript that support events which will start the loading of a beam images 然后当它们全部加载时调用回调。.draw()然后,您可以从该回调中调用您的方法。像这样使用回调是 javascript 中异步编程的一部分,并且在任何时候通过网络加载某些东西(图像、ajax 调用等)时都需要。

于 2012-10-19T21:35:07.067 回答