2013-07-10 1 views
18

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

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

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

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

Thanks

+2

другой способ: imageObj.coords = {x: x, y: y}; ... drawImage (imageObj, imageObj.coords.x, imageObj.coords.y); – dandavis

+1

COMP SCI TECHIE STUFF: Проблема выше в том, что функция onload ссылается на GLOBAL-переменные x и y ... и будет использовать значение then-current при выполнении. Чтобы правильно использовать закрытие - и иметь значения переменных «сохранены» от времени создания (закрытия) и использоваться при их исполнении - вам нужно использовать декларацию 'var', чтобы предоставить им область INSIDE для закрытия. (Это неявно происходит, если переменные являются формальными параметрами для функции, поэтому ответы на замыкание здесь «работают».) –

ответ

7

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

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; 
8

Сделайте частное замыкание области, которая будет хранить й & значения Y:

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

Почему downvote? – gdoron

30

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

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

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

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

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

Еще одно преимущество такого подхода: он может сэкономить много памяти, если вы создаете много данного объекта - потому что теперь вы можете использовать один экземпляр обработчика 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 = "....."; 
} 

Сравнить с разделяемой OnLoad функции с пользовательскими данными спрятан в объекте 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 = "....."; 
} 

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

+3

Ничего себе. Удивительно, сколько лет я не думал об объектном решении. Это прекрасный Дэн, thx –

+1

Идеальный подход, спасибо. –

+0

круто! вместо 'imageObj.myCustomData', я сделал' imageObj.this = this', а затем вызывается с 'this.this'. это было проще, чем жесткое кодирование полей – Jason

Смежные вопросы