2013-07-10 26 views
18

Khi tôi đặt src của một đối tượng hình ảnh, nó sẽ kích hoạt một hàm onload. Làm thế nào tôi có thể thêm các tham số cho nó?Làm thế nào để truyền tham số vào sự kiện tải ảnh?

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

Tại đây, tôi muốn sử dụng các giá trị x và y đã được thiết lập vào thời điểm tôi đặt src của hình ảnh (ví dụ 1 và 2). Trong đoạn mã trên, khi hàm onload kết thúc, x và y có thể là 3 và 4.

Có cách nào tôi có thể truyền giá trị vào hàm onload hay nó sẽ tự động sử dụng 1 và 2?

Cảm ơn

+2

cách khác: imageObj.coords = {x: x, y: y}; ... drawImage (imageObj, imageObj.coords.x, imageObj.coords.y); – dandavis

+1

COMP SCI TECHIE STUFF: Vấn đề ở trên là hàm onload tham chiếu đến các biến GLOBAL x và y ... và sẽ sử dụng giá trị hiện tại khi thực thi. Để sử dụng đúng cách đóng - và có các giá trị biến "được lưu" từ thời gian tạo (của đóng) và được sử dụng khi được thực hiện - bạn cần sử dụng khai báo 'var' để cung cấp cho chúng một phạm vi INSIDE đóng. (Điều này ngầm xảy ra nếu các biến là các tham số chính thức cho một hàm, đó là lý do tại sao các câu trả lời dựa trên đóng cửa ở đây "hoạt động".) –

Trả lời

7

Tạo một chức năng nhỏ để xử lý. Biến cục bộ sẽ giữ phạm vi chính xác.

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

Bạn có thể sử dụng một chức năng ẩn danh

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

Thực hiện một đóng cửa phạm vi tin rằng sẽ lưu giữ x & y giá trị:

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

Tại sao lại là downvote? – gdoron

30

Tất cả các câu trả lời khác là một số phiên bản của "làm một đóng cửa ". OK, nó hoạt động. Tôi cho rằng các bao đóng là tuyệt vời và các ngôn ngữ hỗ trợ chúng rất tuyệt ...

Tuy nhiên: có cách làm sạch hơn, IMO. Đơn giản chỉ cần sử dụng đối tượng hình ảnh để lưu trữ những gì bạn cần, và truy cập nó trong xử lý tải qua "this":

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

Đây là một kỹ thuật rất chung chung, và tôi sử dụng nó mọi lúc trong nhiều đối tượng trong DOM . (Tôi đặc biệt sử dụng nó khi tôi có, nói, bốn nút và tôi muốn tất cả họ chia sẻ một "onclick" xử lý; tôi có xử lý kéo một chút dữ liệu tùy chỉnh ra khỏi nút để làm hành động cụ thể của nút đó.)

Một cảnh báo: bạn phải cẩn thận không sử dụng thuộc tính của đối tượng mà chính lớp đối tượng đó có ý nghĩa hoặc sử dụng đặc biệt. (Ví dụ: bạn không thể sử dụng imageObj.src cho bất kỳ mục đích sử dụng tùy chỉnh nào cũ; bạn phải để nó cho URL nguồn.) Nhưng, trong trường hợp chung, làm thế nào bạn biết được một đối tượng đã cho sử dụng tất cả các thuộc tính của nó như thế nào? Nói đúng ra, bạn không thể. Vì vậy, để thực hiện phương pháp này là an toàn càng tốt:

  • Tổng kết tất cả các dữ liệu tùy chỉnh của bạn trong một đối tượng duy nhất
  • Gán rằng phản đối một tài sản đó là không bình thường/khó có khả năng được sử dụng bởi các đối tượng chính nó.

Về vấn đề đó, việc sử dụng "x" và "y" hơi rủi ro vì một số triển khai Javascript trong một số trình duyệt có thể sử dụng các thuộc tính đó khi xử lý đối tượng Hình ảnh. Nhưng điều này có lẽ là an toàn:

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

Một ưu điểm khác để tiếp cận này: nó có thể tiết kiệm rất nhiều bộ nhớ nếu bạn đang tạo rất nhiều của một đối tượng nhất định - vì bây giờ bạn có thể chia sẻ một trường hợp duy nhất của trình xử lý onload .Xem xét việc này, sử dụng đóng cửa:

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

Hãy so sánh để chia sẻ-onload chức năng, với dữ liệu tùy chỉnh của bạn giấu đi trong đối tượng hình ảnh:

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

Phần lớn bộ nhớ lưu lại và có thể chạy một skosh nhanh hơn kể từ khi bạn aren không tạo ra tất cả các chức năng ẩn danh đó. (Trong ví dụ này, hàm onload là một lớp lót .... nhưng tôi đã có các hàm tải 100 dòng, và 1000 trong số chúng chắc chắn sẽ được coi là dành nhiều bộ nhớ không có lý do chính đáng.)

+3

Wow. Thật tuyệt vời trong bao nhiêu năm tôi không nghĩ về giải pháp đối tượng. Thật đáng yêu Dan, thx –

+1

Cách tiếp cận hoàn hảo, cảm ơn. –

+0

tuyệt! thay vì 'imageObj.myCustomData', tôi đã làm' imageObj.this = this', sau đó được gọi với 'this.this'. nó đã được dễ dàng hơn so với mã hóa cứng các lĩnh vực – Jason

Các vấn đề liên quan