使用 JavaScript/jQuery 预加载图像的最佳方式?

IT技术 javascript jquery image-preloader
2021-01-21 09:10:36

我完全意识到这个问题已经在任何地方被问到和回答,无论是在 SO 上还是在外面。但是,每次似乎都有不同的答案,例如thisthisthat

我不在乎它是否使用 jQuery - 重要的是它可以工作,并且是跨浏览器的。]

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

6个回答

不幸的是,这取决于您的目的。如果您打算将图像用于风格目的,最好的办法是使用精灵。 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];
  }
}

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

usingnew Image()不涉及使用 DOM 方法的费用,但是对指定图像的新请求将被添加到队列中。由于图像此时并未实际添加到页面中,因此不涉及重新渲染。但是,我建议将其添加到页面的末尾(如果可能,所有脚本都应该如此)以防止它包含更多关键元素。

编辑:编辑以正确反映评论,指出Image需要单独的对象才能正常工作。谢谢,我很遗憾没有更仔细地检查它。

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

编辑 3(3 年后):

由于浏览器处理不可见图像的方式发生了变化(display:none 或者,在这个答案中,从不附加到文档)一种新的预加载方法是首选。

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

jQuery.get(source);

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

function preload(sources)
{
  jQuery.each(sources, function(i,source) { jQuery.get(source); });
}

请注意,这不适用于原样很好的精灵的情况。这仅适用于照片画廊或带有图像的滑块/旋转木马之类的东西,其中图像未加载,因为它们最初不可见。

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

这些图像在 DOM 中吗?导致内存使用,或者他们只是坐在缓存中等待被拉出?
2021-03-22 09:10:36
猜猜您实际上并没有阅读您链接到的问题的答案。该方法仅预加载数组中的最后一项。
2021-03-23 09:10:36
由于 CORS,您不能将 jQuery.get 用于另一台服务器上的图像。
2021-03-24 09:10:36
感谢 +1,很高兴我在发布之前没有尝试使语法完美:)
2021-04-01 09:10:36
+1 用于编写我将要提交的所有内容。打败我 25 秒。:-)
2021-04-06 09:10:36

精灵

正如其他人所提到的,由于各种原因,精灵效果很好,但是,它并不像它想象的那么好。

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

处理不规则形状虽然很棘手。将所有新图像组合成新图像是另一个烦恼。

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

如果您正在寻找最明确的解决方案,那么您应该采用我仍然喜欢的低插孔方法。在文档的末尾创建的图像<IMG>链接,并设置widthheight对1x1像素,另外把它们放在一个隐藏的股利。如果它们在页面的末尾,它们将在其他内容之后加载。

这不是“漂亮”,但低插孔方法是让它跨浏览器和设备工作的最一致的方法。需要注意的一点,特别是在 Firefox 上,它更适合做可见性:隐藏而不是显示:包装器 div 没有,并且只处理您需要的间距。
2021-03-22 09:10:36
我从没想过“低插孔方法”……好主意,而且很简单!
2021-04-03 09:10:36

截至 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();
    }
}

用法:

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

请注意,如果缓存被禁用,您会得到不同的结果,当开发者工具打开时,Chrome 上默认是这样,所以请记住这一点。

对于那些害怕添加新插件的人 - 我很惊喜地看到它可以通过 npm 轻松获得。我在 5 分钟内将上述解决方案落实到位,这非常简单。其他解决方案也不适用于我(即使在 chrome 中)。
2021-04-07 09:10:36

在我看来,使用一些库引入的 Multipart XMLHttpRequest 将是未来几年的首选方案。但是 IE < v8,仍然不支持 data:uri(即使 IE8 支持有限,最多允许 32kb)。这是并行图像预加载的实现 - http://code.google.com/p/core-framework/wiki/ImagePreloading,它捆绑在框架中,但仍然值得一看。

这是很久以前的事了,所以我不知道还有多少人对预加载图像感兴趣。

我的解决方案更简单。

我刚刚使用了 CSS。

#hidden_preload {
    height: 1px;
    left: -20000px;
    position: absolute;
    top: -20000px;
    width: 1px;
}