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 の多くのオブジェクトで常に使用しています。(特に、たとえば 4 つのボタンがあり、すべてのボタンで "onclick" ハンドラーを共有する場合に使用します。そのボタンの特定のアクションを実行するために、ハンドラーにボタンからカスタム データを少し引き出してもらいます。)

1 つの警告: オブジェクト クラス自体が特別な意味または使用を持っているオブジェクトのプロパティを使用しないように注意する必要があります。(たとえばimageObj.src、古いカスタム用途には使用できません。ソース URL のためにそのままにしておく必要があります。) しかし、一般的なケースでは、特定のオブジェクトがそのすべてのプロパティをどのように使用しているかを知るにはどうすればよいでしょうか? 厳密に言えば、できません。したがって、このアプローチを可能な限り安全にするために:

  • すべてのカスタム データを 1 つのオブジェクトにまとめる
  • そのオブジェクトを、オブジェクト自体によって使用される可能性が低い/ありそうにないプロパティに割り当てます。

その点で、"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 = ".....";

このアプローチのもう 1 つの利点は、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 = ".....";
}

カスタム データを Image オブジェクトに格納した shared-onload 関数と比較します。

// 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 関数は 1 行です....しかし、私は 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 に答える