How to pass parameters into image load event?

后端 未结 4 1635
一向
一向 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:23

    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);
    
    0 讨论(0)
  • 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.

    0 讨论(0)
  • 2020-12-08 20:33

    Make a small function that handles it. Local variables will hold the correct scope.

    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;
    
    0 讨论(0)
  • 2020-12-08 20:46

    You could use an anonymous function

    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;  
    
    0 讨论(0)
提交回复
热议问题