使用 JavaScript/jQuery 预加载图像的最佳方式?
不幸的是,这取决于您的目的。如果您打算将图像用于风格目的,最好的办法是使用精灵。 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 检索图像数据)。
精灵
正如其他人所提到的,由于各种原因,精灵效果很好,但是,它并不像它想象的那么好。
- 从好的方面来说,您最终只会为您的图像发出一个 HTTP 请求。虽然是 YMMV。
- 不利的一面是,您在一个 HTTP 请求中加载所有内容。由于大多数当前浏览器仅限于 2 个并发连接,因此图像请求可以阻止其他请求。因此 YMMV 和菜单背景之类的东西可能不会呈现一点。
- 多个图像共享相同的调色板,因此可以节省一些费用,但情况并非总是如此,即使如此也可以忽略不计。
- 压缩得到改进,因为图像之间有更多的共享数据。
处理不规则形状虽然很棘手。将所有新图像组合成新图像是另一个烦恼。
使用 <img> 标签的低插孔方法
如果您正在寻找最明确的解决方案,那么您应该采用我仍然喜欢的低插孔方法。在文档的末尾创建的图像<IMG>链接,并设置width
和height
对1x1像素,另外把它们放在一个隐藏的股利。如果它们在页面的末尾,它们将在其他内容之后加载。
截至 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 上默认是这样,所以请记住这一点。
在我看来,使用一些库引入的 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;
}