簡體   English   中英

使用Javascript動態添加HTML <img> 標簽。 如何判斷圖像的加載時間

[英]Dynamically adding HTML with Javascript which has <img> tags. How do I tell when the images are loaded

假設我有一個div,並希望向該div注入一些HTML。 HTML將包含一個或多個圖像。

是否有任何方法使用純JavaScript或jQuery來確定圖像何時加載?

因此,如果我執行以下操作,您是否可以將事件偵聽器放在單個元素上以告知包含圖像的內容何時准備好?:

var html = "<p>Some text <img src='image.jpg' /></p><p>Some more text <img src='image2.jpg' /></p>";
$("div.output").html(html);

每次圖像都不同,所以我無法使用JavaScript圖像對象進行預加載。

我正在考慮的一種方法是使用正則表達式或jQuery運行HTML,查找所有圖像URL,循環遍歷它們並使用圖像對象預加載每個URL。 當所有都已預加載時,然后將HTML注入輸出div。

除非你在加載並計算它們之前將onload事件連接到每個圖像,否則沒有簡單的方法來判斷它們何時被加載。

這是一個相對防彈的方法演示 ),使用Deferred ,在IE 6-9,Chrome 19和Firefox 3.6-10,Opera 10.10-11.52,Android 4和iOS 5中測試和工作。

首先,我們將編寫一個小的jQuery插件,為jQuery集合中的每個元素返回一個Deferred s數組。 每個Deferred將在元素加載時解析; 如果元素加載失敗或(可選)花費的時間超過timeout秒數,則拒絕或拒絕。

$.fn.loaded = function(opts) {
    var o = $.extend({timeout:10000}, opts) // Merge default options with supplied options
        , r = []; // Return value

    this.each(function() {
        var dfd = new $.Deferred(), el = $(this), to;
        if (o.timeout) to = setTimeout(function() {
            done();
            dfd.reject();
        }, o.timeout);
        el.bind('load.dfdl', function() {
            done();
            dfd.resolve();
        }).bind('error.dfdl', function() {
            done();
            dfd.reject();
        });

        function done() { // internal clean-up
            clearTimeout(to);
            el.unbind('.dfdl');
        }
        r.push(dfd.promise());
    });
    return r;
};

超時將防止瀏覽器從未實際觸發任何事件的情況。 我在這里將默認超時設置為10秒; 在現實世界中,你可能希望減少它。

現在我們將生成10個隨機大小的placekittens ,用作示例中的圖像。

var imgs=[];
for (var i = 0; i < 10; i++) imgs.push('<img src="http://placekitten.com/' + rnd() + '/' + rnd() + '"> ');
$('#imgs').html(imgs.join());

最后,我們將把所有東西放在一起,帶來一些魔力:

$.when.apply($, $('#imgs img').loaded({timeout:10000}) ).done(function() {
    alert('loaded successfully');
}).fail(function() {
    alert('load failed or timed out');
});

$.when創建一個主Deferred ,只有當所有子Deferred s解析時才會解析,或者在子拒絕時拒絕。 它通常希望您將每個Deferred作為參數傳遞(它不支持傳遞Deferred數組),因此我們必須apply我們的數組。 (我可能會執行$.whenall = function(dfds) { $.when.apply($,dfds); };這樣你的應用程序代碼就有了一個更清晰的$.whenall( $('#imgs img').loaded() )...

嘗試這個:

$("#preload_div").html(
    '<img src="image.png" alt="preload" class="preload" width="0" height="0">'
);

事件處理程序可以綁定到圖像:

$('preload').load(function () {
    var html = "<p>Some text <img src='image.jpg' /></p><p>Some more text <img src='image2.jpg' /></p>";
    $("div.output").html(html);
});

當然,您必須為每個圖像合並一個.each()以循環遍歷所有圖像。

編輯:在我的一個AJAX網站上,我預加載了我需要的下一個圖像,因此當用戶點擊“下一步”按鈕時,新內容所需的圖像已經被緩存。 http://funl.es/p/1

我認為你應該在將圖像插入html后綁定加載處理程序。

DEMO

    //Add image
    $('#result').append('<img src= "<Your_Image_URL>" width="300" height="300"/>');

    //Bind handler also add condition to not bind images that was not added before.
    $('#result').find('img').not('.loaded').on('load', function () {
        alert('Image Loaded');
        //Add code that you want to do after the image is added
    }).addClass('loaded');

當與圖像一起使用時,請注意加載事件的警告

開發人員嘗試使用.load()快捷方式解決的常見挑戰是在圖像(或圖像集合)完全加載時執行函數。 應該注意有幾個已知的警告。 這些是:

  1. 它不能一致地工作,也不能可靠地跨瀏覽器
  2. 如果圖像src設置為與之前相同的src,則它在WebKit中無法正確觸發
  3. 它沒有正確地冒泡DOM樹
  4. 可以停止為已經存在於瀏覽器緩存中的圖像觸發

參考: http //api.jquery.com/load-event/

我正在考慮的一種方法是使用正則表達式或jQuery運行HTML,查找所有圖像URL,循環遍歷它們並使用圖像對象預加載每個URL。 當所有都已預加載時,然后將HTML注入輸出div。

var imagesLoaded = [];
var imagesErrored = [];

$('img').each(function() {
     $(this).load(function() {
         imagesLoaded.push($(this).attr("src"));
         if( (imagesLoaded.length + imagesErrored.length) == $('img').length ) {
             displayResults(imagesLoaded, imagesErrored);

         } 
     });
     $(this).error(function() {
         imagesErrored.push($(this).attr("src"));
         if( (imagesLoaded.length + imagesErrored.length) == $('img').length ) {
             displayResults(imagesLoaded, imagesErrored);
         } 

});

function displayResults(imagesLoaded, imagesErrored) {
    for(var i = 0; i < imagesLoaded.length; i++) {
        alert(imagesLoaded[i] + " has loaded successfully.");
        $('#myDiv').append("<img src='" + imagesLoaded[i] + "' />");
    }
    for(var i = 0; i < imagesErrored.length; i++) {
        alert(imagesLoaded[i] + " did NOT load successfully.");
    }
}

上面循環遍歷所有圖像並使用load事件檢查它們是否已加載。 使用錯誤事件,我們還獲得了由於任何原因未正確加載的所有圖像的集合。 在預加載所有圖像之后,我們可以將它們注入“displayResults”函數中的頁面。 這基於你問題的最后一段。

但是,它不使用正則表達式,因為它們不是操作DOM的正確工具。 幸運的是,JavaScript和jQuery為我們提供了執行DOM操作和解析活動所需的工具。

最后,根據您的問題,聽起來您可能對了解成功加載的圖像感興趣。 根據加載和錯誤事件構建的上述集合將在您需要時為您提供這些詳細信息。

您是否考慮過使用jQuery'on'事件機制? 使用'on'應該允許您在動態添加到容器和DOM時自動將'load'處理程序綁定到每個圖像。

鏈接: jQuery docs for'on'功能

如果您使用的是1.7之前的jQuery,則需要使用“實時”功能,因為在1.7版本中添加了“on”。

鏈接: 'live'函數的jQuery文檔(不建議使用)

我認為沒有簡單的方法可以做到這一點。 您可以做的是將所有圖像加載到隱藏的div上(顯示:無)。

當您想要顯示圖片時,您可以執行以下操作:

$("#myDiv").show();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM