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 supports events that will start the loading of images of images and thenそれらがすべて読み込まれたときにコールバックを呼び出します。.draw()その後、そのコールバックからメソッドを呼び出すことができます。このようなコールバックの使用は、javascript での非同期プログラミングの一部であり、ネットワーク経由で何かが読み込まれるときは常に必要です (画像、ajax 呼び出しなど)。

于 2012-10-19T21:35:07.067 に答える