2009-05-04 1 views
54

Trong IE, bạn có thể onreadystatechange. Có tải, nhưng tôi đọc scary things. jQuery kết thúc tốt đẹp sự kiện tải của DOM khá độc đáo với "sẵn sàng". Có vẻ như tôi không biết gì về việc thực hiện tải hình ảnh của một thư viện khác.Cách độc lập với trình duyệt để phát hiện khi hình ảnh đã được tải

Ngữ cảnh là tôi tạo hình ảnh động (thông qua cuộc gọi lại máy chủ) có thể mất một chút thời gian tải xuống. Trong mã chỉ có IE của tôi, tôi đặt src của phần tử img, sau đó khi sự kiện onreadystatechange kích hoạt với trạng thái "hoàn tất", tôi thêm nó vào DOM để người dùng nhìn thấy nó.

Tôi rất hài lòng với giải pháp JavaScript "gốc" hoặc một con trỏ đến thư viện thực hiện công việc. Có rất nhiều thư viện ở đó và tôi chắc rằng đây là trường hợp của tôi mà không biết về một thư viện phù hợp. Điều đó nói rằng, chúng tôi đã là người dùng jQuery, vì vậy tôi không mong muốn thêm một thư viện rất lớn chỉ để có được chức năng này.

+0

Tôi hoàn toàn không hiểu - bạn có muốn một giải pháp JS thuần túy duy nhất để phát hiện khi một hình ảnh đã được tải hay bạn đang tìm kiếm một thư viện thay thế cho jQuery để phát hiện khi một hình ảnh được tải? –

+0

Tôi cũng rất vui. Tôi sẽ không lừa jQuery khi tôi sử dụng nó ở nơi khác; chỉ thể hiện sự nghi ngờ của tôi rằng đây là một vấn đề được giải quyết tốt trong một thư viện mà tôi không quen thuộc. –

+0

Đừng quên cho chúng tôi biết bạn sẽ làm gì! –

Trả lời

46

LƯU Ý: Tôi đã viết điều này trong năm 2010, các trình duyệt trong tự nhiên là IE 8/9 beta, Firefox 3.x và Chrome 4.x. Xin vui lòng sử dụng này cho mục đích nghiên cứu, tôi nghi ngờ bạn có thể sao chép/dán này vào một trình duyệt hiện đại và có nó làm việc mà không có vấn đề.

CẢNH BÁO: Bây giờ là năm 2017 tôi vẫn nhận được điểm này ngay bây giờ và sau đó, vui lòng chỉ sử dụng thông tin này cho mục đích nghiên cứu. Tôi hiện không có ý tưởng làm thế nào để phát hiện tình trạng tải hình ảnh, nhưng có lẽ nhiều cách duyên dáng hơn để làm điều đó hơn này ... ít nhất tôi nghiêm túc hy vọng có. Tôi khuyên bạn KHÔNG nên sử dụng mã của mình trong môi trường sản xuất mà không cần nghiên cứu thêm.


tôi là một chút muộn để bên này, có lẽ câu trả lời này sẽ giúp người khác ...

Nếu bạn đang sử dụng jQuery không bận tâm với các xử lý sự kiện chứng khoán (onclick/onmouseover/etc), thực sự chỉ ngừng sử dụng chúng hoàn toàn. Sử dụng các phương thức sự kiện mà họ đã cung cấp trong số API của họ.


Điều này sẽ cảnh báo trước khi hình ảnh được thêm vào nội dung vì sự kiện tải được kích hoạt khi hình ảnh được tải vào bộ nhớ. Nó đang làm chính xác những gì bạn nói với nó: tạo một hình ảnh với src của test.jpg, khi test.jpg tải một cảnh báo, sau đó gắn nó vào cơ thể.

var img = $('<img src="test.jpg" />'); 
img.load(function() { 
    alert('Image Loaded'); 
}); 
$('body').append(img); 

này sẽ cảnh báo, sau khi hình ảnh được đưa vào cơ thể, một lần nữa, làm những gì bạn nói với nó để: tạo một hình ảnh, thiết lập một sự kiện (không có bộ src, vì vậy nó có không tải), gắn hình ảnh vào phần thân (vẫn không có src), bây giờ đặt src ... bây giờ hình ảnh được nạp để sự kiện được kích hoạt.

var img = $('<img />'); 
img.load(function() { 
    alert('Image Loaded'); 
}); 
$('body').append(img); 
$img.attr('src','test.jpg'); 

Bạn có thể dĩ nhiên cũng thêm một xử lý lỗi và hợp nhất một loạt các sự kiện sử dụng bind().

var img = $('<img />'); 
img.bind({ 
    load: function() { 
     alert('Image loaded.'); 
    }, 
    error: function() { 
     alert('Error thrown, image didn\'t load, probably a 404.'); 
    } 
}); 
$('body').append(img); 
img.attr('src','test.jpg'); 

mỗi yêu cầu của @ChrisKempen ...

Dưới đây là một cách điều khiển phi trường hợp xác định nếu những hình ảnh được chia sau khi DOM được nạp. Mã này là một dẫn xuất của mã từ một bài viết của StereoChrome sử dụng các thuộc tính naturalWidth, naturalHeight và hoàn chỉnh để xác định xem hình ảnh có tồn tại hay không.

$('img').each(function() { 
    if (this.naturalWidth === 0 || this.naturalHeight === 0 || this.complete === false) { 
     alert('broken image'); 
    } 
}); 
+12

CẢNH BÁO: Từ tài liệu jquery: Hãy cẩn thận khi tải hình ảnh khi sử dụng với hình ảnh: Một nhà phát triển thử thách phổ biến cố gắng giải quyết bằng phím tắt .load() là thực hiện chức năng khi hình ảnh (hoặc bộ sưu tập hình ảnh) hoàn toàn nạp vào. Có một số cảnh báo được biết đến với điều này cần lưu ý. Đây là: Nó không hoạt động nhất quán cũng không đáng tin cậy qua trình duyệt Nó không kích hoạt chính xác trong WebKit nếu hình ảnh src được đặt thành cùng src như trước Nó không chính xác bong bóng lên cây DOM Có thể ngừng bắn các hình ảnh đã tồn tại trong bộ nhớ cache của trình duyệt – Ben

+0

Điểm tuyệt vời @Ben. – paulj

+1

Tôi thậm chí còn sau bữa tiệc, nhưng nếu hình ảnh đã được thêm vào và bạn cần phải kiểm tra xem chúng đã được tải chưa? Cảm ơn bạn cho bất kỳ suy nghĩ/gợi ý! :) –

1

Nếu im không nhầm trong javascript thẻ hình ảnh có sự kiện onload và onerror

đây là một chút intersting mã tôi đã làm để ẩn hình ảnh bị hỏng

trong một thẻ phong cách

img.failed{ 
    display:none; 
} 

bằng cách sử dụng img onerror tôi đã có một đoạn javascript đã làm điều này.className = không thành công và nó sẽ ẩn hình ảnh nếu nó bị lỗi

tuy nhiên tôi có thể đã hiểu lầm những gì mục tiêu của bạn

+1

Mặc dù một vài trình duyệt hỗ trợ nó, sự kiện "onload" không được hỗ trợ bởi W3C tiêu chuẩn, và do đó không phải tất cả các trình duyệt cần phải hoặc phải hỗ trợ này. –

5

Cách duy nhất đáng tin cậy tôi đã tìm thấy là để làm điều đó tất cả trên client-side như thế này ...

var img = new Image(); 
img.onload = function() { 
    alert('Done!'); 
} 
img.src = '/images/myImage.jpg'; 
+1

Mặc dù một vài trình duyệt hỗ trợ nó, sự kiện "onload" không được hỗ trợ bởi tiêu chuẩn W3C, và do đó không phải tất cả các trình duyệt đều cần hoặc phải hỗ trợ điều này. –

3

Tôi nghĩ onload nên hoạt động tốt. Bạn có phải tạo đánh dấu cho các hình ảnh hoặc bạn có thể thêm chúng một cách tĩnh không? Nếu sau này, tôi muốn đề nghị như sau:

<img src="foo.png" class="classNeededToHideImage" onload="makeVisible(this)"> 

Ngoài ra, bạn có thể sử dụng window.onload để làm cho tất cả hình ảnh có thể nhìn thấy cùng một lúc - window.onload cháy sau khi tất cả ressources bên ngoài đã tải xong.

Nếu bạn muốn thêm hình ảnh động, trước tiên bạn phải đợi DOM sẵn sàng sửa đổi, tức là sử dụng jQuery hoặc triển khai hack DOMContentLoaded của riêng bạn cho các trình duyệt không hỗ trợ nguyên bản.

Sau đó, bạn tạo đối tượng hình ảnh của mình, chỉ định onload người nghe để hiển thị chúng và/hoặc thêm chúng vào tài liệu.

Thậm chí tốt hơn (nhưng hơi phức tạp hơn) sẽ là tạo và bắt đầu tải hình ảnh ngay lập tức khi tập lệnh thực thi. Trên DOMContentLoaded, bạn sẽ phải kiểm tra từng ảnh cho complete để quyết định có thêm chúng ngay lập tức vào tài liệu hoặc chờ cho trình nghe của onload kích hoạt để kích hoạt hay không.

+1

Mặc dù một vài trình duyệt hỗ trợ nó, sự kiện "onload" không được hỗ trợ bởi tiêu chuẩn W3C, và do đó không phải tất cả các trình duyệt đều cần hoặc phải hỗ trợ điều này. –

+0

Vâng, khi 'một vài trình duyệt' có vẻ là mọi trình duyệt chính thống sinde NN4, nó là hợp lý an toàn để giả định rằng các tính năng sẽ không biến mất bất cứ lúc nào sớm. Đáng buồn là có thể, thông số W3C hiếm khi phản ánh thực tế của các nhà phát triển web ... – Christoph

+0

Một lần nữa, tôi biết điều này, nhưng luôn luôn là điều tốt để lưu ý những thông số kỹ thuật nói, nếu không có lý do khác để hiểu chính xác những gì bạn chỉ ra rằng họ không liên lạc được với thực tế và cần được cập nhật. Nhân tiện, "js-hacks" là gì và tại sao cần thiết? Tôi nhận thấy từ hồ sơ của bạn rằng bạn đã tạo ra nó, nhưng thật khó để khám phá nó là gì vì trang web của bạn thiếu thông tin và tôi không có thời gian để đọc qua tất cả các tệp chỉ tìm kiếm. –

10

According to the W3C spec, chỉ phần tử BODY và ​​FRAMESET cung cấp sự kiện "onload" để đính kèm. Một số trình duyệt hỗ trợ nó bất kể, nhưng chỉ cần lưu ý rằng nó không được yêu cầu để thực hiện spec W3C.

Cái gì đó có thể là thích hợp để thảo luận này, mặc dù không nhất thiết phải là câu trả lời bạn đang cần, là cuộc thảo luận này:

Image.onload event does not fire on Internet Explorer when image is in cache


Cái gì khác mà có thể liên quan đến theo nhu cầu của bạn, mặc dù có thể không, là thông tin này về hỗ trợ sự kiện "onload" tổng hợp cho bất kỳ sự kiện nào được tải động DOM yếu tố:

How can I determine if a dynamically-created DOM element has been added to the DOM?

+0

có thể đúng, nhưng tải lên cho hình ảnh là một tiêu chuẩn thực tế (nó đã sẵn sàng từ Netscape Navigator 4) – Christoph

+0

Chắc chắn, tôi không bao giờ nói rằng đó không phải là điều mà ông ta có thể tin cậy, chỉ cần đảm bảo rằng spec - bỏ qua các thông số kỹ thuật theo nguy hiểm của riêng bạn. –

+0

sự cố với Image.onload mà bạn đề cập cụ thể là GWT - xem http://code.google.com/p/google-web-toolkit/issues/detail?id=863#c5; Image.onload phải được thiết lập trước Image.src để tránh điều này, mà đã được đề cập ngầm định bởi Josh – Christoph

1

Nó sẽ xuất hiện câu trả lời là sử dụng onreadystatechange trong IE, và onLoad trong các trình duyệt khác. Nếu không có ai, hãy làm một cái gì đó khác. onLoad sẽ thích hợp hơn, nhưng IE không kích hoạt nó khi tải một hình ảnh từ bộ nhớ đệm, như đã lưu ý trong một trong các câu trả lời dưới đây.

+0

IE kích hoạt khi tải từ bộ nhớ cache - bạn chỉ cần đảm bảo đặt 'onload' trước khi đặt' src'; vấn đề Jason đề cập cụ thể là GWT, được đề cập trên trang được liên kết – Christoph

+0

Có vẻ như bạn đã đúng - cảm ơn vì đã lặn sâu hơn vào cuối chuỗi nhận xét. Bây giờ tôi cần kiểm tra nó ... –

3

Được rồi, tôi sẽ cố gắng tóm tắt các câu trả lời một phần khác nhau tại đây (bao gồm cả tôi).

Có vẻ như câu trả lời là sử dụng onload, được "hỗ trợ rộng rãi" mặc dù không chính thức được yêu cầu theo tiêu chuẩn. Lưu ý rằng đối với IE nói riêng, bạn phải đặt onLoad trước khi thiết lập thuộc tính src hoặc nó có thể không kích hoạt tải khi tải một hình ảnh từ bộ nhớ cache. Điều này có vẻ như thực tiễn tốt nhất trong mọi trường hợp: thiết lập trình xử lý sự kiện của bạn trước khi bạn bắt đầu kích hoạt sự kiện. Trường hợp onload không được hỗ trợ, bạn nên giả định rằng chức năng này không có sẵn.

1

HTML

<img id="myimage" src="http://farm4.static.flickr.com/3106/2819995451_23db3f25fe_t.jpg"/>​ 

SCRIPT

setTimeout(function(){ 
    $('#myimage').attr('src','http://cdn.redmondpie.com/wp-content/uploads/2011/05/canarylogo.png').load(function(){ 
     alert('Main Image Loaded'); 

     $('#myimage').attr('src','image.jpg').bind({ 
      load: function(){ 
       alert('Image loaded.'); 
      }, 
      error: function(){ 
       alert('Image not loaded.'); 
      } 
     }); 
    }); 
},1000); 

JS Fiddle

http://jsfiddle.net/gerst20051/sLge3/

0

Sử dụng URI dữ liệu là cách để thực hiện. Tuy nhiên, việc sử dụng SVG thay vì GIF cung cấp sự linh hoạt hơn. Bạn có thể nhanh chóng thay đổi kích thước. Chỉ cần chạy này trong bảng điều khiển JavaScript:

var width = 1; 
var height = 1; 
'data:image/svg+xml;base64,' + 
btoa(`<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}"/>`); 

Ví dụ đầu ra:

data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxIiBoZWlnaHQ9IjEiLz4= 

Tôi ném cùng a quick CodePen utility to create transparent SVGs with arbitrary dimensions. Nó khá cơ bản, vì vậy bạn sẽ cần phải sửa đổi nó nếu bạn muốn thêm màu sắc hoặc các tính năng khác cho hình ảnh.

Lợi thế lớn nhất so với hình ảnh một pixel là cho phép tỷ lệ khung hình được giữ nguyên. Điều này rất quan trọng đối với hình ảnh có kích thước động, vì bố cục thường được thực hiện trước các thay đổi src thành hình ảnh thực (nếu đó là mục đích dự định). Cho đến khi src thay đổi, hình ảnh sẽ là hình vuông, có thể không mong muốn.