When I set the src of an image object, it will trigger an onload function. How can I add parameters to it?
x = 1;
y = 2;
imageObj = new Image();
imageObj.src = ".....";
imageObj.onload = function() {
context.drawImage(imageObj, x, y);
};
x = 3;
y = 4;
In here, I want to use the x and y values that were set at the time I set the src of the image (i.e. 1 and 2). In the code above, by the time the onload function would finish, x and y could be 3 and 4.
Is there a way I can pass values into the onload function, or will it automatically use 1, and 2?
Thanks
All the other answers are some version of "make a closure". OK, that works. I think closures are cool, and languages that support them are cool...
However: there is a much cleaner way to do this, IMO. Simply use the image object to store what you need, and access it in the load handler via "this
":
imageObj = new Image();
imageObj.x = 1;
imageObj.y = 2;
imageObj.onload = function() {
context.drawImage(this, this.x, this.y);
};
imageObj.src = ".....";
This is a very general technique, and I use it all the time in many objects in the DOM. (I especially use it when I have, say, four buttons and I want them to all share an "onclick" handler; I have the handler pull a bit of custom data out of the button to do THAT button's particular action.)
One warning: you have to be careful not to use a property of the object that the object class itself has a special meaning or use. (For example: you can't use imageObj.src
for any old custom use; you have to leave it for the source URL.) But, in the general case, how are you to know how a given object uses all its properties? Strictly speaking, you can't. So to make this approach as safe as possible:
In that regard, using "x" and "y" are a little risky as some Javascript implementation in some browser may use those properties when dealing with the Image object. But this is probably safe:
imageObj = new Image();
imageObj.myCustomData = {x: 1, y: 2};
imageObj.onload = function() {
context.drawImage(this, this.myCustomData.x, this.myCustomData.y);
};
imageObj.src = ".....";
Another advantage to this approach: it can save a lot of memory if you are creating a lot of a given object -- because you can now share a single instance of the onload handler. Consider this, using closures:
// 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 = ".....";
}
Compare to shared-onload function, with your custom data tucked away in the Image object:
// 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 = ".....";
}
Much memory saved and may run a skosh faster since you aren't creating all those anonymous functions. (In this example, the onload function is a one-liner.... but I've had 100-line onload functions, and a 1000 of them would surely be considered spending a lot of memory for no good reason.)
UPDATE: See use of 'data-*' attribute for a standard (and "standards approved") way to do this, in lieu of my ad-hoc suggestion to use myCustomData
.
Make a private scope closure that will store x & y values:
imageObj.onload = (function(x,y){
return function() {
context.drawImage(imageObj, x, y);
};
})(x,y);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With