1

小さな HTML5 ベースの例を作成しようとしてきましたが、いくつかの問題に遭遇しました。に岩をレンダリングしたいのです<canvas>が、この Javascript オブジェクトが正しく動作しません。

function ImageData() {
    this.image_names = ["rock1"];
    this.images = new Array();
    this.loadResources = function () {
        for (var i = 0; i < this.image_names.length; i++) {
            var img = new Image();
            img.onload = (function (a) {
                a.images[a.image_names[i]] = img;
                console.log(a.images); //log is successful, image is in array
            })(this);
            img.src = "images/" + this.image_names[i] + ".png";
        }
    }
}

その用途は次のとおりです。

var a = new ImageData();
a.loadResources();
var rock1_image = a.images["rock1"]; //the "rock1.png" image

コンソール経由でオブジェクトにアクセスしようとすると、画像がロードされたことを確認した後、画像配列に画像がないことがわかります。なぜ機能しないのかわかりません。何度も見直しました。

編集:これが私の最終的な作業結果です:

function ImageData() {
    this.image_names = ["rock1"];
    this.images = new Array();
    this.loadResources = function (callback) {
        for (var i = 0; i < this.image_names.length; i++) {
            var img = new Image();
            img.onload = (function (a, i) {
                return function() {
                    a.images[a.image_names[i]] = img;
                    if (i == (a.image_names.length - 1)) callback();
                };
            })(this, i);
            img.src = "images/" + this.image_names[i] + ".png";
        }
    }
}
4

4 に答える 4

2

配列に追加される前にアクセスしようとしていると思います。メソッドにコールバックなどを追加して、loadResourcesメソッドにアクセスする前にメソッドがそこにあることを確認することをお勧めします。

this.loadResources = function (callback) {
    for (var i = 0; i < this.image_names.length; i++) {
        var img = new Image();
        img.onload = (function (a, i) {
            return function() {
                a.images[a.image_names[i]] = img;
                console.log(a.images); //log is successful, image is in array
                callback();
            };
        })(this, i);
        img.src = "images/" + this.image_names[i] + ".png";
    }
} 

それから

var a = new ImageData();
var rock1_image;
a.loadResources(function() {
    rock1_image = a.images["rock1"];
    // do whatever you need to do with the image in here.
});

また、@Igor が言及しているもの。私はそれを完全に逃しました。this上記のコードを調整して、別の場所に設定しなくてもスコープを維持できるようにしました。

i@RobD によって提起された問題に対処するために更新されました。

于 2013-07-13T03:49:26.103 に答える
2

ハンドラー定義の(this)後に削除します。実際には、 (何も返さないため) 値としてonload代入して、この関数をすぐに呼び出しています。undefinedimg.onload

于 2013-07-13T03:50:40.653 に答える
1

コード内:

> function ImageData() {
>     this.image_names = ["rock1"];
>     this.images = new Array();
>     this.loadResources = function () {
>         for (var i = 0; i < this.image_names.length; i++) {
>             var img = new Image();
>             img.onload = (function (a) {

この関数はすぐに実行され、値を返さないため、未定義が割り当てられます。したがって、割り当てには意味がありません。コードを実行するだけです。

>                 a.images[a.image_names[i]] = img;

画像は、プレーン オブジェクトとして使用される配列です。その場合は、プレーン オブジェクトを使用することをお勧めします。

>                 console.log(a.images); //log is successful, image is in array
>             })(this);

IIFE のため、外側のthisを渡す必要があります。IIFE を削除すると、これを渡す必要はありません。また、インスタンスへの参照が関数に格納されている場合、関数がどのように呼び出されても問題ありません (つまり、呼び出しでこれを設定する必要はありません)。

>             img.src = "images/" + this.image_names[i] + ".png";
>         }
>     }
> }

次のようなものが必要な場合があります。

function ImageData() {
    this.image_names = ['rock1'];
    this.images = {};
    imageData = this;
    this.loadResources = function (callback) {

        for (var i = 0; i < imageData.image_names.length; i++) {
            var img = new Image();
            imageData.images[a.image_names[i]] = img;
            img.src = 'images/' + this.image_names[i] + '.png';

            if (callback) {
                img.onload = callback;
            }
        }
    }
}

var a = new ImageData();
a.loadResources(function(){console.log('loaded: ' + this.src);}); // loaded: …

window.onload = function() {
    document.body.appendChild(a.images.rock1); // image appears in document
}
于 2013-07-13T04:29:56.290 に答える
0

あなたのコードはまだテストしていませんが、これが問題だと思います: イメージがロードされる前にアクセスしようとしています。次のようにロードされた後、コールバックイベントハンドラーを使用できます。

var data = new ImageData();

data.loadResources(function(imgObj){
 // imgObj is the newly load image here. Have fun with it now!
})
于 2013-07-13T03:59:14.130 に答える