【问题标题】:JavaScript loop/scope issue with Image.onload()Image.onload() 的 JavaScript 循环/范围问题
【发布时间】:2026-02-24 01:25:01
【问题描述】:

我正在尝试使用 JavaScript 遍历一个对象并将该对象的所有子对象添加到 HTML5 画布。

canvas-bit 正在工作,这没问题,但由于某种原因,我所有的图像最终都具有相同的大小 - 最后一个子对象“背景”的大小。我假设它与我的循环范围和“this”有关,但我真的看不出要改变什么;

var stage;
var items = {
    head: {image: null, path: "images/avatar-elements/head01.png", w:200, h:200},
    hair: {image: null, path: "images/avatar-elements/hair01.png", w:200, h:200},
    nose: {image: null, path: "images/avatar-elements/nose01.png", w:200, h:200},
    eyes: {image: null, path: "images/avatar-elements/eyes01.png", w:200, h:200},
    eyebrows: {image: null, path: "images/avatar-elements/eyebrows01.png", w:200, h:200},
    ears: {image: null, path: "images/avatar-elements/ears01.png", w:200, h:200},
    background: {image: null, path: "images/avatar-elements/background01.png", w:500, h:370}
};

function initCanvas() {
    stage = new Kinetic.Stage("canvas", 500, 370);
    makeBasis();
}


function makeBasis() {
    for(i in items) {
        var img = new Image();
        img.onload = function() {
            items[i].image = makeCanvasImage(this, items[i].w, items[i].h);
        }
        img.src = items[i].path;
    }


}

function makeCanvasImage(tar, w, h) {
    var theImage = new Kinetic.Image({
        imageObj: tar,
        x: 250 - (w / 2),
        y: 185 - (h / 2),
        width: w,
        height: h
    });
    stage.add(theImage);
    return theImage;
}

initCanvas();

【问题讨论】:

标签: javascript image loops scope


【解决方案1】:

错误在 makeBasis() 中。在循环所有图像后,我设置为最后一个 - 经典的闭包问题。尝试使用这个:

function makeBasis() {
    for(i in items) {
        var img = new Image();
        img.onload = (function (nr) {
            return function() {
                items[nr].image = makeCanvasImage(this, items[nr].w, items[nr].h);
            }
        }(i));      
        img.src = items[i].path;
    }
}

【讨论】:

  • 漂亮,修复了它。你能告诉我“返回功能”是做什么的吗?它是在加载图像后执行的吗?如果图像没有按照加载顺序完成加载,会发生什么情况,不会将错误的图像添加到items 中的子对象中吗?
  • @Reinoud: return function(){...} 返回由function(){...} 定义的函数。这是立即执行的,因为外部函数会立即执行(function(){...}())(注意末尾的括号)。
  • 谢谢,已加入书签以供日后阅读。我会看看我能走多远,在 AS3 中从未遇到过这些问题;)