使用JavaScript/jQuery预加载图像的权威最佳方法?

Ski*_*ick 50 javascript jquery image-preloader

我完全清楚这个问题已经在所有地方得到了回答,无论是在SO还是在关闭.然而,每一次似乎有不同的答案,比如这个,这个那个.

我不关心它是否使用jQuery - 重要的是它是有效的,并且是跨浏览器.

那么,预加载图像的最佳方法是什么?

Jon*_*and 65

不幸的是,这取决于你的目的.如果您打算将图像用于风格,最好的办法是使用精灵. http://www.alistapart.com/articles/sprites2

但是,如果您打算使用<img>标签中的图像,那么您需要预先加载它们

function preload(sources)
{
  var images = [];
  for (i = 0, length = sources.length; i < length; ++i) {
    images[i] = new Image();
    images[i].src = sources[i];
  }
}
Run Code Online (Sandbox Code Playgroud)

(修改后的源代码来源于在JavaScript中预加载多个图像的最佳方法是什么?)

using new Image()不涉及使用DOM方法的费用,但是对指定图像的新请求将被添加到队列中.由于图像在此时未实际添加到页面中,因此不会涉及重新呈现.但是,我建议将其添加到页面的末尾(因为所有脚本应尽可能),以防止它占用更多关键元素.

编辑:编辑以反映评论非常正确地指出Image需要单独的对象才能正常工作.谢谢,我不能更仔细地检查它.

Edit2:编辑以使可重用性更加明显

编辑3(3年后):

由于浏览器处理不可见图像的方式发生了变化(显示:无,或者在本答复中,从未附加到文档中),因此首选新的预加载方法.

您可以使用Ajax请求强制提前检索图像.使用jQuery,例如:

jQuery.get(source);
Run Code Online (Sandbox Code Playgroud)

或者在我们上一个示例的上下文中,您可以执行以下操作:

function preload(sources)
{
  jQuery.each(sources, function(i,source) { jQuery.get(source); });
}
Run Code Online (Sandbox Code Playgroud)

请注意,这不适用于精细的精灵情况.这仅适用于照片画廊或滑块/旋转木马等带图像的图像未加载的图像,因为它们最初不可见.

另请注意,此方法不适用于IE(ajax通常不用于检索图像数据).

  • 由于CORS,您无法在另一台服务器上使用jQuery.get. (6认同)
  • 写下我要提交的所有内容的+1.打败我25秒.:-) (4认同)

ale*_*emb 14

拼合

正如其他人所提到的那样,由于各种原因,精神作用非常好,然而,它并没有像它的那样好.

  • 从好的方面来说,您最终只能为图像发出一个HTTP请求.但YMMV.
  • 在不利方面,您将在一个HTTP请求中加载所有内容.由于大多数当前浏览器限于2个并发连接,因此图像请求可以阻止其他请求.因此,YMMV和菜单背景之类的东西可能不会渲染一点.
  • 多个图像共享相同的调色板,因此有一些保存,但情况并非总是如此,即使如此,它也可以忽略不计.
  • 由于图像之间存在更多共享数据,因此压缩得到改善.

然而,处理不规则形状是棘手的.将所有新图像组合成新图像是另一个烦恼.

使用<img>标签的低插孔方法

如果您正在寻找最明确的解决方案,那么您应该采用我更喜欢的低插孔方法.创建<img>链接到文档末尾的图像,并设置widthheight1x1像素,并另外将它们放在隐藏的div中.如果它们位于页面的末尾,则会在其他内容之后加载它们.


Mah*_*ahn 6

截至2013年1月,这里描述的方法都没有适用于我,所以这里做了相反的事情,测试并使用Chrome 25和Firefox 18.使用jQuery和这个插件来解决加载事件的怪癖:

function preload(sources, callback) {
    if(sources.length) {
        var preloaderDiv = $('<div style="display: none;"></div>').prependTo(document.body);

        $.each(sources, function(i,source) {
            $("<img/>").attr("src", source).appendTo(preloaderDiv);

            if(i == (sources.length-1)) {
                $(preloaderDiv).imagesLoaded(function() {
                    $(this).remove();
                    if(callback) callback();
                });
            }
        });
    } else {
        if(callback) callback();
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

preload(['/img/a.png', '/img/b.png', '/img/c.png'], function() { 
    console.log("done"); 
});
Run Code Online (Sandbox Code Playgroud)

请注意,如果禁用缓存,您将获得混合结果,默认情况下,当开发人员工具处于打开状态时,Chrome会默认显示,因此请记住这一点.