1

我一直在尝试创建一个基于 HTML5 的小型示例,但遇到了一些问题。我想在 a 上渲染一块石头,<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您实际上是立即调用此函数,将undefined(因为它不返回任何内容)分配为img.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) {

此函数将立即运行并且不返回值,因此将分配undefined 。因此,分配没有意义,只需运行代码即可。

>                 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 回答