Cách chính thức để yêu cầu jQuery đợi tất cả các hình ảnh được tải trước khi thực hiện một cái gì đó


641

Trong jQuery khi bạn làm điều này:

$(function() {
   alert("DOM is loaded, but images not necessarily all loaded");
});

Nó chờ DOM tải và thực thi mã của bạn. Nếu tất cả các hình ảnh không được tải thì nó vẫn thực thi mã. Đây rõ ràng là những gì chúng tôi muốn nếu chúng tôi đang khởi tạo bất kỳ nội dung DOM nào như hiển thị hoặc ẩn các phần tử hoặc đính kèm các sự kiện.

Giả sử tôi muốn một số hình ảnh động và tôi không muốn nó chạy cho đến khi tất cả các hình ảnh được tải. Có một cách chính thức trong jQuery để làm điều này?

Cách tốt nhất tôi có là sử dụng <body onload="finished()">, nhưng tôi không thực sự muốn làm điều đó trừ khi tôi phải làm vậy.

Lưu ý: Có một lỗi trong jQuery 1.3.1 trong Internet Explorer thực sự chờ tất cả các hình ảnh được tải trước khi thực thi mã bên trong $function() { }. Vì vậy, nếu bạn đang sử dụng nền tảng đó, bạn sẽ nhận được hành vi tôi đang tìm thay vì hành vi đúng được mô tả ở trên.


3
không $("img").load()làm việc
Lucas

1
Tôi nghĩ có thể đáng đề cập rằng nếu bạn đặt các thuộc tính kích thước, bạn nên thực thi một số mã trong chức năng sẵn sàng dựa trên các kích thước đó một cách an toàn. Với php, bạn có thể lấy chúng bằng php.net/manual/en/feft.getimagesize.php khi tải lên để lưu trữ chúng trong db hoặc trước khi xuất ra trình duyệt.
Alqin

nếu bạn muốn một cái gì đó làm một công việc đáng kinh ngạc, thì hãy xem thư viện javascript được tải hình ảnh cực kỳ tốt và phổ biến được đề cập trong câu trả lời này bên dưới stackoverflow.com/a/26458347/759452
Adrien Be

"Ở đây tôi đến để tìm bất cứ điều gì ngoại trừ một cách chính thức."
Léon Pelletier

Câu trả lời:


1035

Với jQuery, bạn sử dụng $(document).ready()để thực thi một cái gì đó khi DOM được tải và $(window).on("load", handler)để thực thi một cái gì đó khi tất cả những thứ khác cũng được tải, chẳng hạn như hình ảnh.

Có thể thấy sự khác biệt trong tệp HTML hoàn chỉnh sau đây, miễn là bạn có jollyrogertệp JPEG (hoặc các tệp phù hợp khác):

<html>
    <head>
        <script src="jquery-1.7.1.js"></script>
        <script type="text/javascript">
            $(document).ready(function() {
                alert ("done");
            });
        </script>
    </head><body>
        Hello
        <img src="jollyroger00.jpg">
        <img src="jollyroger01.jpg">
        // : 100 copies of this
        <img src="jollyroger99.jpg">
    </body>
</html>

Cùng với đó, hộp cảnh báo xuất hiện trước khi hình ảnh được tải, vì DOM đã sẵn sàng tại thời điểm đó. Nếu bạn sau đó thay đổi:

$(document).ready(function() {

vào:

$(window).on("load", function() {

sau đó hộp cảnh báo không xuất hiện cho đến khi hình ảnh được tải.

Do đó, để đợi cho đến khi toàn bộ trang sẵn sàng, bạn có thể sử dụng một cái gì đó như:

$(window).on("load", function() {
    // weave your magic here.
});

32
đánh vào trán +1 hoàn toàn quên mất điều đó. $ (window) .load () sẽ không kích hoạt cho đến khi hình ảnh được hoàn thành.
Paolo Bergantino

10
Tôi cũng đã làm như vậy. Thậm chí, đọc qua một câu trả lời không biết đó là tôi và vẫn không hiểu nó.
Rimian

24
Chỉ là một lưu ý - điều này dường như không hoạt động trong Chromium (và tôi đoán Chrome). Sự kiện $ (window). Yet dường như kích hoạt giống như $ (tài liệu). Đã sẵn sàng - trước khi hình ảnh được hoàn thành.
Nathan Crause

24
nhưng đó là $ (cửa sổ) .load (function ())
TJ-

3
@KyorCode Bạn có chắc không chỉ vì hình ảnh trong IE được lưu trữ? Nếu điều đó xảy ra, họ sẽ không thực hiện một sự kiện "tải" nào cả. Bài viết này giúp khắc phục vấn đề này.
Jamie Barker

157

Tôi đã viết một plugin có thể kích hoạt các cuộc gọi lại khi hình ảnh đã được tải trong các phần tử hoặc kích hoạt một lần cho mỗi hình ảnh được tải.

Nó tương tự như $(window).load(function() { .. }), ngoại trừ nó cho phép bạn xác định bất kỳ bộ chọn nào để kiểm tra. Nếu bạn chỉ muốn biết khi tất cả hình ảnh trong #content(ví dụ) đã được tải, thì đây là plugin dành cho bạn.

Nó cũng hỗ trợ tải hình ảnh tham chiếu trong CSS, chẳng hạn như background-image, list-style-imagevv

plugin WaitForImages jQuery

Cách sử dụng ví dụ

$('selector').waitForImages(function() {
    alert('All images are loaded.');
});

Ví dụ trên jsFiddle .

Thêm tài liệu có sẵn trên trang GitHub.


1
Cảm ơn bạn!! $ .load () không hoạt động với tôi, nhưng điều này thực sự là mánh khóe.
Fraxtil

Tôi sử dụng Chrome Phiên bản 22.0.1229.94 và plugin này và tôi đã cố gắng đọc phần bù từ các hình ảnh được tải trong WaitFormImages: ('img selector').each(function(index) { var offset = $(this).offset(); ...});tuy nhiên, offset.top vẫn bằng không. Tại sao?
basZero

1
@basZero Khó nói mà không có thêm ngữ cảnh. Vui lòng đưa ra một vấn đề trên trang Các vấn đề .
alex

Nó không hoạt động đối với tôi khi các hình ảnh bị hủy bỏ. Có any1 hav một cách giải quyết cho điều này?
Mandeep Jain

2
Về cơ bản, nó tương tự như hình ảnh được tải nhưng nó cũng hoạt động với srcsets. Chính xác những gì tôi đang tìm kiếm! Plugin tuyệt vời!
Fabian Schöner

48

$(window).load()sẽ chỉ hoạt động khi lần đầu tiên trang được tải. Nếu bạn đang làm công cụ động (ví dụ: nút bấm, hãy đợi một số hình ảnh mới được tải), điều này sẽ không hoạt động. Để đạt được điều đó, bạn có thể sử dụng plugin của tôi:

Bản giới thiệu

Tải xuống

/**
 *  Plugin which is applied on a list of img objects and calls
 *  the specified callback function, only when all of them are loaded (or errored).
 *  @author:  H. Yankov (hristo.yankov at gmail dot com)
 *  @version: 1.0.0 (Feb/22/2010)
 *  http://yankov.us
 */

(function($) {
$.fn.batchImageLoad = function(options) {
    var images = $(this);
    var originalTotalImagesCount = images.size();
    var totalImagesCount = originalTotalImagesCount;
    var elementsLoaded = 0;

    // Init
    $.fn.batchImageLoad.defaults = {
        loadingCompleteCallback: null, 
        imageLoadedCallback: null
    }
    var opts = $.extend({}, $.fn.batchImageLoad.defaults, options);

    // Start
    images.each(function() {
        // The image has already been loaded (cached)
        if ($(this)[0].complete) {
            totalImagesCount--;
            if (opts.imageLoadedCallback) opts.imageLoadedCallback(elementsLoaded, originalTotalImagesCount);
        // The image is loading, so attach the listener
        } else {
            $(this).load(function() {
                elementsLoaded++;

                if (opts.imageLoadedCallback) opts.imageLoadedCallback(elementsLoaded, originalTotalImagesCount);

                // An image has been loaded
                if (elementsLoaded >= totalImagesCount)
                    if (opts.loadingCompleteCallback) opts.loadingCompleteCallback();
            });
            $(this).error(function() {
                elementsLoaded++;

                if (opts.imageLoadedCallback) opts.imageLoadedCallback(elementsLoaded, originalTotalImagesCount);

                // The image has errored
                if (elementsLoaded >= totalImagesCount)
                    if (opts.loadingCompleteCallback) opts.loadingCompleteCallback();
            });
        }
    });

    // There are no unloaded images
    if (totalImagesCount <= 0)
        if (opts.loadingCompleteCallback) opts.loadingCompleteCallback();
};
})(jQuery);

chỉ trong trường hợp bất kỳ ai cũng cần một ví dụ sử dụng cho plugin BatchImagesLoad
Jonathan Marzullo

1
Ý tôi là không thiếu tôn trọng nhưng người ta không thể tin vào "chỉ" từ của bạn về độ tin cậy của plugin. Như đã đề cập trong Yevgeniy Afanasyevcâu trả lời , hình ảnh được tải thực hiện công việc này tốt hơn nhiều và bao gồm trường hợp sử dụng mà bạn đã đề cập cùng với nhiều trường hợp góc khác (xem các vấn đề về github đã giải quyết) .
Adrien Be

19

Đối với những người muốn được thông báo về việc hoàn thành tải xuống một hình ảnh được yêu cầu sau khi $(window).loadcháy, bạn có thể sử dụng loadsự kiện của thành phần hình ảnh .

ví dụ:

// create a dialog box with an embedded image
var $dialog = $("<div><img src='" + img_url + "' /></div>");

// get the image element (as a jQuery object)
var $imgElement = $dialog.find("img");

// wait for the image to load 
$imgElement.load(function() {
    alert("The image has loaded; width: " + $imgElement.width() + "px");
});

13

Không có câu trả lời nào cho đến nay đã đưa ra những gì dường như là giải pháp đơn giản nhất.

$('#image_id').load(
  function () {
    //code here
});

Điều tuyệt vời ở đây là bạn có thể kích hoạt nó cho từng ảnh ngay khi chúng tải.
Top Cat

6

Tôi khuyên bạn nên sử dụng imagesLoaded.jsthư viện javascript.

Tại sao không sử dụng jQuery $(window).load()?

Như đã trả lời trên /programming/26927575/why-use-imagesloaded-javascript-l Library-versus-jquerys-window-load/26929951

Đó là một vấn đề phạm vi. imageLoaded cho phép bạn nhắm mục tiêu một tập hợp hình ảnh, trong khi $(window).load()nhắm mục tiêu tất cả các tài sản - bao gồm tất cả các hình ảnh, đối tượng, tệp .js và .css và thậm chí cả iframe. Nhiều khả năng, hình ảnh được tải sẽ kích hoạt sớm hơn $(window).load()vì nó đang nhắm mục tiêu một nhóm tài sản nhỏ hơn.

Các lý do tốt khác để sử dụng tải hình ảnh

  • được hỗ trợ chính thức bởi IE8 +
  • giấy phép: Giấy phép MIT
  • phụ thuộc: không
  • trọng lượng (rút gọn & gzipped): 7kb rút gọn (nhẹ!)
  • download builder (giúp giảm trọng lượng): không cần, đã nhỏ xíu
  • trên Github: CÓ
  • cộng đồng & cộng tác viên: khá lớn, hơn 4000 thành viên, mặc dù chỉ có 13 người đóng góp
  • lịch sử & đóng góp: ổn định như tương đối cũ (từ năm 2010) nhưng dự án vẫn hoạt động

Tài nguyên


4

Với jQuery tôi đi kèm với ...

$(function() {
    var $img = $('img'),
        totalImg = $img.length;

    var waitImgDone = function() {
        totalImg--;
        if (!totalImg) alert("Images loaded!");
    };

    $('img').each(function() {
        $(this)
            .load(waitImgDone)
            .error(waitImgDone);
    });
});

Bản trình diễn: http://jsfiddle.net/molokoloco/NWjDb/


Tôi phát hiện ra rằng điều này sẽ không hoạt động đúng nếu trình duyệt trả về 304 Phản hồi không được xác thực cho hình ảnh có nghĩa là hình ảnh được lưu trữ.
JohnyFree

1

Sử dụng hình ảnh Đã tải GÓI v3.1.8 (6.8 Kb khi thu nhỏ). Nó tương đối cũ (từ năm 2010) nhưng vẫn hoạt động dự án.

Bạn có thể tìm thấy nó trên github: https://github.com/desandro/imagesloaded

Trang web chính thức của họ: http://imagesloaded.desandro.com/

Tại sao nó tốt hơn sử dụng:

$(window).load() 

Bởi vì bạn có thể muốn tải hình ảnh động, như thế này: jsfiddle

$('#button').click(function(){
    $('#image').attr('src', '...');
});

1
Trên thực tế, hình ảnh được tải không hỗ trợ thay đổi trình duyệt chéo giá trị thuộc tính src. Bạn phải tạo một yếu tố hình ảnh mới mỗi lần. Hãy thử nó trên Firefox và bạn sẽ thấy vấn đề xuất hiện.
Adrien Be

Điểm hay, tôi chỉ thử nghiệm trên Google chrome và IE-11. Nó đã hoạt động. Cảm ơn.
Yevgeniy Afanasyev

Tôi đã thêm vấn đề trình duyệt chéo này vào câu hỏi stackoverflow.com/q/26927575 của tôi trong điểm "Những gì bạn không thể làm với hình ảnh được tải", xem hình ảnh Vấn đề liên quan được tải trên Github github.com/desandro/imagesloaded/issues/121
Adrien Trở thành

1

Bằng cách này, bạn có thể thực hiện một hành động khi tất cả các hình ảnh bên trong cơ thể hoặc bất kỳ vùng chứa nào khác (tùy thuộc vào lựa chọn của bạn) được tải. YÊU CẦU PURE, không cần pluggins.

var counter = 0;
var size = $('img').length;

$("img").load(function() { // many or just one image(w) inside body or any other container
    counter += 1;
    counter === size && $('body').css('background-color', '#fffaaa'); // any action
}).each(function() {
  this.complete && $(this).load();        
});

0

Giải pháp của tôi tương tự như molokoloco . Được viết dưới dạng hàm jQuery:

$.fn.waitForImages = function (callback) {
    var $img = $('img', this),
        totalImg = $img.length;

    var waitImgLoad = function () {
        totalImg--;
        if (!totalImg) {
            callback();
        }
    };

    $img.each(function () {
        if (this.complete) { 
            waitImgLoad();
        }
    })

    $img.load(waitImgLoad)
        .error(waitImgLoad);
};

thí dụ:

<div>
    <img src="img1.png"/>
    <img src="img2.png"/>
</div>
<script>
    $('div').waitForImages(function () {
        console.log('img loaded');
    });
</script>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.