为什么这个Javascript图像对象不会被添加到图像数组中?

时间:2013-07-13 03:44:45

标签: javascript html5 image canvas

我一直在尝试创建一个基于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 个答案:

答案 0 :(得分: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范围而无需在其他地方设置。

更新以处理@RobD提出的i问题。

答案 1 :(得分:2)

(this)处理程序定义后删除onload。您实际上是在立即调用此函数,将undefined(因为它不返回任何内容)指定为img.onload值。

答案 2 :(得分: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;

Images是一个用作普通对象的数组。那么最好使用普通对象。

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

由于IIFE,必须传入外部。删除IIFE并且无需传递。如果对函数的引用存储在函数中,则调用函数的方式无关紧要(即,您不必在调用中设置 this )。

>             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
}

答案 3 :(得分:0)

我还没有测试过您的代码,但我想这就是问题所在: 您正在尝试在加载图像之前访问该图像。您可以在加载之后使用回调事件处理程序,如:

var data = new ImageData();

data.loadResources(function(imgObj){
 // imgObj is the newly load image here. Have fun with it now!
})