Подтвердить что ты не робот

Как передать параметры в событие загрузки изображения?

Когда я устанавливаю src объекта изображения, он вызывает функцию onload. Как добавить к нему параметры?

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

Здесь я хочу использовать значения x и y, которые были установлены во время установки src изображения (то есть 1 и 2). В приведенном выше коде, к моменту завершения функции onload, x и y могут быть 3 и 4.

Есть ли способ передать значения в функцию onload или будет автоматически использовать 1 и 2?

Спасибо

4b9b3361

Ответ 1

Все остальные ответы являются некой версией "сделай замыкание". ОК, это работает. Я думаю, что замыкания - это круто, а языки, которые их поддерживают - это круто...

Тем не менее, есть гораздо более чистый способ сделать это, ИМО. Просто используйте объект изображения для хранения того, что вам нужно, и обращайтесь к нему в обработчике загрузки через "this":

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

Это очень общий метод, и я постоянно использую его во многих объектах в DOM. (Я особенно использую его, когда у меня есть, скажем, четыре кнопки, и я хочу, чтобы все они совместно использовали обработчик "onclick"; у меня есть обработчик, который вытаскивает немного пользовательских данных из кнопки, чтобы выполнить определенное действие кнопки THAT.)

Одно предупреждение: вы должны быть осторожны, чтобы не использовать свойство объекта, которое сам класс объекта имеет особое значение или использовать. (Например: вы не можете использовать 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 = ".....";

Еще одно преимущество этого подхода: он может сэкономить много памяти, если вы создаете много заданного объекта - потому что теперь вы можете совместно использовать один экземпляр обработчика загрузки. Учтите это, используя замыкания:

// 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:

// 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 = ".....";
}

Много памяти сохранено и может работать быстрее, так как вы не создаете все эти анонимные функции. (В этом примере функция onload является однострочной.... но у меня были функции загрузки из 100 строк, и 1000 из них, безусловно, считались бы расходующими много памяти без веской причины.)

ОБНОВЛЕНИЕ: см. использование атрибута [data- * ' для стандартного (и "одобренного стандартами") способа сделать это вместо моего специального предложения использовать myCustomData.

Ответ 2

Сделайте закрытие закрытого пространства, которое будет хранить значения x и y:

imageObj.onload = (function(x,y){
        return function() {
            context.drawImage(imageObj, x, y);
    };
})(x,y);

Ответ 3

Сделайте небольшую функцию, которая обрабатывает ее. Локальные переменные будут содержать правильную область.

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;

Ответ 4

Вы можете использовать анонимную функцию

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;