要求jQuery在执行某些操作之前等待所有图像加载的官方方式


640

在jQuery中,当您执行以下操作时:

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

它等待DOM加载并执行您的代码。如果未加载所有映像,则仍将执行代码。如果我们要初始化任何DOM东西(例如显示或隐藏元素或附加事件),显然这就是我们想要的。

假设我想要一些动画,并且在加载所有图像之前不希望它运行。jQuery中有正式的方法吗?

我最好的方法是使用<body onload="finished()">,但是除非需要,否则我真的不想这样做。

注意:Internet Explorer的jQuery 1.3.1中存在一个错误,错误实际上会等待所有图像加载之后才执行内部代码$function() { }。因此,如果您使用该平台,则会得到我正在寻找的行为,而不是上面描述的正确行为。


3
不起作用$("img").load()
卢卡斯

1
我认为值得一提的是,如果设置了维度属性,则可以安全地在依赖这些维度的就绪函数中执行一些代码。使用php时,您可以在上传时使用php.net/manual/en/function.getimagesize.php抓取它们,以将它们存储在db中或输出到浏览器之前。
Alqin

如果您想做一些令人难以置信的工作,那么请查看下面这个答案中提到的非常好和最受欢迎的imageloaded javascript库stackoverflow.com/a/26458347/759452
Adrien是

“在这里,我找到了除官方途径以外的任何东西。”
莱昂佩尔蒂埃

Answers:


1034

使用jQuery,您可以$(document).ready()在加载DOM时执行某些操作,并在加载$(window).on("load", handler)所有其他内容(如图像)时执行某些操作。

如果您有jollyrogerJPEG文件(或其他合适的文件),则可以在下面的完整HTML文件中看到区别:

<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>

这样,在加载图像之前会出现警告框,因为此时DOM已准备就绪。如果您随后更改:

$(document).ready(function() {

变成:

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

则直到加载图像才会出现警报框。

因此,要等到整个页面准备就绪,可以使用类似以下的命令:

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

32
打ack的额头 +1完全忘记了这一点。$(window).load()在图像完成之前不会触发。
Paolo Bergantino,

10
我也一样 甚至,通读一个答案,不知道那是我,仍然不理解。
Rimian

24
请注意-在Chromium(我认为是Chrome)下,这似乎不起作用。$(window).ready事件似乎与$(document).ready触发事件相同-在完成图像之前。
内森·克劳斯

24
但这是$(window).load(function())
TJ-

3
@KyorCode您确定不只是因为IE中的图像被缓存了吗?如果发生这种情况,他们将根本不会触发“加载”事件。本文有助于解决此问题。
Jamie Barker

157

我写了一个插件,可以在图像加载到元素中时触发回调,或者在每个图像加载时触发一次。

与相似$(window).load(function() { .. }),不同之处在于,它允许您定义要检查的选择器。如果您只想知道何时所有图像#content(例如)中的加载,这就是您的插件。

它还支持加载CSS中引用的图像,例如background-imagelist-style-image等等。

waitForImages jQuery插件

用法示例

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

jsFiddle上的示例

GitHub页面上提供了更多文档。


1
谢谢!!$ .load()不适用于我,但这可以完美地解决问题。
Fraxtil 2011年

我使用的是Chrome版本22.0.1229.94和该插件,并且尝试从waitFormImages中读取已加载图像的偏移量('img selector').each(function(index) { var offset = $(this).offset(); ...});,但是offset.top仍为零。为什么?
basZero 2012年

1
@basZero很难在没有更多上下文的情况下讲述。请在问题上提出问题页面。
alex 2012年

缓存图像后,它对我不起作用。有任何解决方法吗?
Mandeep Jain

2
它基本上类似于imagesLoaded,但也可以与srcsets一起使用。正是我想要的!很棒的插件!
FabianSchöner,2016年

48

$(window).load()仅在第一次加载页面时有效。如果您要进行动态处理(例如:单击按钮,等待一些新图像加载),则此操作将无效。为此,您可以使用我的插件:

演示版

下载

/**
 *  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);

以防万一有人需要BatchImagesLoad插件的用法示例:yankov.us/batchImageLoad
Jonathan Marzullo

1
我的意思是不尊重他人,但您不能仅仅依靠您关于插件可靠性的说法。正如在Yevgeniy Afanasyev答案中提到,imagesLoaded在这方面做得更好,并且涵盖了您提到的用例以及许多其他极端情况(请参阅已解决的github问题)
Adrien Be

19

对于那些希望在$(window).load发生火灾后收到请求的单个图像的下载完成通知的人,可以使用图像元素的load事件。

例如:

// 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

到目前为止,没有一个答案给出了最简单的解决方案。

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

这样做的好处是,您可以在加载单个图像后立即触发它。
顶级猫

6

我建议使用imagesLoaded.jsjavascript库。

为什么不使用jQuery $(window).load()

/programming/26927575/why-use-imagesloaded-javascript-library-versus-jquerys-window-load/26929951所述

这是范围的问题。imagesLoaded允许您定位一组图像,而$(window).load()定位所有资产 -包括所有图像,对象,.js和.css文件,甚至是iframe。最有可能的是,imagesLoaded的触发时间要早于$(window).load()因为它以较小的资产为目标。

使用图像加载的其他良好理由

  • IE8 +正式支持
  • 许可证:MIT许可证
  • 依赖项:无
  • 重量(最小并压缩):最小7kb(轻!)
  • 下载构建器(有助于减轻体重):不需要,已经很小了
  • 在Github上:是
  • 社区和贡献者:很大,有4000多个成员,尽管只有13个贡献者
  • 历史和贡献:相对稳定(自2010年起),但仍处于活跃状态

资源资源


4

有了jQuery我就附带了这个...

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

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

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

演示:http : //jsfiddle.net/molokoloco/NWjDb/


我发现,如果浏览器针对图像返回304 Not Mofified响应,则意味着此图像已缓存,因此无法正常工作。
JohnyFree

1

使用imagesLoaded PACKAGED v3.1.8(最小化时为6.8 Kb)。它相对较旧(自2010年起),但仍处于活跃状态。

您可以在github上找到它:https : //github.com/desandro/imagesloaded

他们的官方网站:http : //imagesloaded.desandro.com/

为什么比使用更好:

$(window).load() 

因为您可能想动态加载图像,所以像这样:jsfiddle

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

1
实际上,加载的图像不支持跨浏览器更改src属性值。您每次必须创建一个新的图像元素。在Firefox上尝试,您将看到问题出现。
Adrien Be

好点,我只在Google chrome和IE-11上进行过测试。它正在工作。谢谢。
Yevgeniy Afanasyev 2014年

我确实在我的问题stackoverflow.com/q/26927575中添加了跨浏览器问题,指向“您无法使用图像加载做什么”,请参见Github上的imagesLoaded相关问题github.com/desandro/imagesloaded/issues/121
Adrien是

1

这样,当加载了体内或任何其他容器(取决于您的选择)中的所有图像时,您可以执行操作。纯JQUERY,无需插件。

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

我的解决方案类似于molokoloco。编写为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);
};

例:

<div>
    <img src="img1.png"/>
    <img src="img2.png"/>
</div>
<script>
    $('div').waitForImages(function () {
        console.log('img loaded');
    });
</script>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.