27

当我设置一个图像对象的 src 时,它会触发一个 onload 函数。如何向它添加参数?

x = 1;
y = 2;
imageObj = new Image();
imageObj.src = ".....";
imageObj.onload = function() {
    context.drawImage(imageObj, x, y);
};
x = 3;
y = 4;

在这里,我想使用在设置图像的 src 时设置的 x 和 y 值(即 1 和 2)。在上面的代码中,当 onload 函数完成时,x 和 y 可能是 3 和 4。

有没有办法可以将值传递给 onload 函数,或者它会自动使用 1 和 2?

谢谢

4

4 回答 4

45

所有其他答案都是“关闭”的某个版本。好的,这行得通。我认为闭包很酷,支持它们的语言很酷......

但是:IMO,有一种更清洁的方法可以做到这一点。只需使用图像对象来存储您需要的内容,并通过“ this”在加载处理程序中访问它:

imageObj = new Image();
imageObj.x = 1;
imageObj.y = 2;
imageObj.onload = function() {
    context.drawImage(this, this.x, this.y);
};
imageObj.src = ".....";

这是一种非常通用的技术,我一直在 DOM 中的许多对象中使用它。(当我有四个按钮并且我希望它们都共享一个“onclick”处理程序时,我特别使用它;我让处理程序从按钮中提取一些自定义数据来执行该按钮的特定操作。)

一个警告:您必须小心不要使用对象类本身具有特殊含义或用途的对象属性。(例如:您不能imageObj.src用于任何旧的自定义用途;您必须将其保留为源 URL。)但是,在一般情况下,您如何知道给定对象如何使用其所有属性?严格来说,你不能。因此,为了使这种方法尽可能安全:

  • 将所有自定义数据封装在一个对象中
  • 将该对象分配给对象本身不常见/不太可能使用的属性。

在这方面,使用“x”和“y”有点冒险,因为某些浏览器中的某些 Javascript 实现在处理 Image 对象时可能会使用这些属性。但这可能是安全的:

imageObj = new Image();
imageObj.myCustomData = {x: 1, y: 2};
imageObj.onload = function() {
    context.drawImage(this, this.myCustomData.x, this.myCustomData.y);
};
imageObj.src = ".....";

这种方法的另一个优点是:如果您要创建大量给定对象,它可以节省大量内存——因为您现在可以共享 onload 处理程序的单个实例。考虑一下,使用闭包:

// closure based solution -- creates 1000 anonymous functions for "onload"
for (var i=0; i<1000; i++) {
   var imageObj = new Image();
   var x = i*20;
   var y = i*10;
   imageObj.onload = function() {
       context.drawImage(imageObj, x, y);
   };
   imageObj.src = ".....";
}

与 shared-onload 函数相比,您的自定义数据隐藏在 Image 对象中:

// custom data in the object -- creates A SINGLE "onload" function
function myImageOnload () {
   context.drawImage(this, this.myCustomData.x, this.myCustomData.y);
}
for (var i=0; i<1000; i++) {
   imageObj = new Image();
   imageObj.myCustomData = {x: i*20, y: i*10};
   imageObj.onload = myImageOnload;
   imageObj.src = ".....";
}

由于您没有创建所有这些匿名函数,因此节省了很多内存并且可以更快地运行 skosh。(在这个例子中,onload 函数是一个单行函数......但我有 100 行 onload 函数,其中 1000 个肯定会被认为无缘无故地消耗大量内存。)

更新:请参阅使用 'data-*' 属性以获得标准(和“标准批准”)方式来执行此操作,而不是我的临时建议使用myCustomData.

于 2014-12-02T13:30:13.810 回答
12

创建一个私有作用域闭包来存储 x & y 值:

imageObj.onload = (function(x,y){
        return function() {
            context.drawImage(imageObj, x, y);
    };
})(x,y);
于 2013-07-10T18:34:38.727 回答
9

制作一个处理它的小函数。局部变量将保持正确的范围。

function loadImage( src, x, y) {

    var imageObj = new Image();
    imageObj.src = src;
    imageObj.onload = function() {
        context.drawImage(imageObj, x, y);
    };

}

var x = 1,
    y = 2;

loadImage("foo.png", x, y);
x = 3;
y = 4;
于 2013-07-10T18:33:31.143 回答
5

您可以使用匿名函数

x = 1;
y = 2;
(function(xValue, yValue){
    imageObj = new Image();
    imageObj.src = ".....";
    imageObj.onload = function() {
        context.drawImage(imageObj, xValue, yValue);
    };
})(x,y);
x = 3;
y = 4;  
于 2013-07-10T18:34:30.740 回答