How to pass parameters into image load event?

后端 未结 4 1665
一向
一向 2020-12-08 19:54

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         


        
4条回答
  •  情深已故
    2020-12-08 20:28

    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:

    • Wrap up all your custom data in a single object
    • Assign that object to a property that is unusual/unlikely to be used by the object itself.

    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.

提交回复
热议问题