使用带有标签的Javascript动态添加HTML <img> 。如何判断图像何时加载



>假设我有一个div,并且想向该div注入一些HTML。HTML 将包含 1 个或多个图像。

有没有办法用普通的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事件挂接到每个图像并对其进行计数,否则没有简单的方法可以判断它们何时全部加载。

这是一个相对防弹的方法(demo(,它使用Deferred s,在IE 6-9,Chrome 19和Firefox 3.6-10,Opera 10.10-11.52,Android 4和iOS 5中测试和工作。

首先,我们将编写一个小的 jQuery 插件,它为 jQuery 集合中的每个元素返回一个 Deferred 的数组。 每个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 个随机大小的 placekit,以用作示例中的图像。

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解析时解析,或在子项拒绝时拒绝。 它通常希望您将每个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

我想做的一种方法是使用正则表达式或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 事件检查它们是否加载。使用 error 事件,我们还获得了由于某种原因未正确加载的所有图像的集合。预加载所有图像后,我们可以在"displayResults"函数中将它们注入到页面上。这大致基于您问题的最后一段。

但是,它不使用正则表达式,因为它们不是操作 DOM 的正确工具。 幸运的是,JavaScript 和 jQuery 为我们提供了执行 DOM 操作和解析活动所需的工具。

最后,从您的问题来看,听起来您可能有兴趣了解哪些图像已成功加载。如果需要,从加载和错误事件生成的上述集合将为您提供这些详细信息。

我认为您应该在将图像插入 html 后绑定加载处理程序。

演示

    //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. 工作
  3. 如果图像 src 设置为与以前相同的 src,则在 WebKit 中无法正确触发
  4. 它没有正确地冒泡 DOM 树
  5. 可以停止为浏览器缓存中已存在的图像触发

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

您是否考虑过使用 jQuery 'on' 事件机制?使用"on"应该允许您在动态添加到容器和 DOM 时自动将"load"处理程序绑定到每个映像。

链接: jQuery docs for 'on' 函数

如果您使用的是 1.7 之前的 jQuery,则需要使用"live"函数,因为 1.7 版本添加了"on"。

链接:用于"实时"函数的jQuery文档(已弃用(

我认为没有简单的方法可以做到这一点。您可以做的是将所有图像加载到隐藏的div上(显示:无(。

当您想显示图片时,您可以执行以下操作:

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

最新更新