我完全清楚这个问题已经在所有地方被询问和回答,无论是在SO还是关闭。但是,每次似乎有不同的答案,例如this,this和that。
我不关心它是否使用jQuery - 重要的是它是有效的,并且是跨浏览器。]
那么,预加载图像的最佳方法是什么?
答案 0 :(得分: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];
}
}
(修改后的来源于What is the best way to preload multiple images in JavaScript?)
使用new Image()
不涉及使用DOM方法的费用,但是对指定图像的新请求将添加到队列中。由于图像在此时未实际添加到页面中,因此不会涉及重新呈现。但是,我建议将其添加到页面的末尾(因为所有脚本应尽可能),以防止它占用更多关键元素。
编辑:编辑以反映评论非常正确地指出需要单独的Image
个对象才能正常工作。谢谢,我不能更仔细地检查它。
Edit2:编辑以使可重用性更加明显
编辑3(3年后):
由于浏览器处理不可见图像的方式发生了变化(显示:无,或者在本答复中,从未附加到文档中),因此首选新的预加载方法。
您可以使用Ajax请求强制提前检索图像。使用jQuery,例如:
jQuery.get(source);
或者在上一个示例的上下文中,您可以这样做:
function preload(sources)
{
jQuery.each(sources, function(i,source) { jQuery.get(source); });
}
请注意,这不适用于精细的精灵情况。这仅适用于照片画廊或滑块/旋转木马等带图像的图像未加载的图像,因为它们最初不可见。
另请注意,此方法不适用于IE(ajax通常不用于检索图像数据)。
答案 1 :(得分:14)
<强>拼合强>
正如其他人所说的那样,出于各种原因,精灵作品效果很好,但是它并不像它的那样好。
处理不规则形状虽然很棘手。将所有新图像合并到新图像中是另一个烦恼。
使用&lt; img&gt;的低插孔方法代码
如果您正在寻找最明确的解决方案,那么您应该采用我更喜欢的低插孔方法。创建&lt; img&gt;链接到文档末尾的图像,并将width
和height
设置为1x1像素,并将它们另外放入隐藏的div中。如果它们位于页面的末尾,则会在其他内容之后加载它们。
答案 2 :(得分:6)
截至2013年1月,这里描述的方法都没有为我工作,所以这里是做了什么,测试和使用Chrome 25和Firefox 18.使用jQuery和this plugin来解决加载事件的怪癖:< / p>
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会默认显示,因此请记住这一点。
答案 3 :(得分:3)
在我看来,使用一些库引入的Multipart XMLHttpRequest将是接下来几年的首选解决方案。然而,IE&lt; v8,仍然不支持数据:uri(即使IE8支持有限,允许最多32kb)。这是一个并行图像预加载的实现 - http://code.google.com/p/core-framework/wiki/ImagePreloading,它在框架中捆绑但仍值得一看。
答案 4 :(得分:1)
这是很久以前的事情,所以我不知道还有多少人对预装图像感兴趣。
我的解决方案更简单。
我刚刚使用CSS。
#hidden_preload {
height: 1px;
left: -20000px;
position: absolute;
top: -20000px;
width: 1px;
}
答案 5 :(得分:0)
这是我的简单解决方案,在加载后淡入图像。
function preloadImage(_imgUrl, _container){
var image = new Image();
image.src = _imgUrl;
image.onload = function(){
$(_container).fadeTo(500, 1);
};
}
答案 6 :(得分:0)
对于我的用例,我有一个带有全屏图像的旋转木马,我想要预装。然而,由于图像按顺序显示,并且每个图像可能需要几秒钟才能加载,因此按顺序加载它们非常重要。
为此,我使用了异步库的waterfall()
方法(https://github.com/caolan/async#waterfall)
// Preload all images in the carousel in order.
image_preload_array = [];
$('div.carousel-image').each(function(){
var url = $(this).data('image-url');
image_preload_array.push(function(callback) {
var $img = $('<img/>')
$img.load(function() {
callback(null);
})[0].src = url;
});
});
async.waterfall(image_preload_array);
这通过创建一个函数数组来工作,每个函数都传递参数callback()
,它需要执行它才能调用数组中的下一个函数。 callback()
的第一个参数是一条错误消息,如果提供了非空值,它将退出序列,因此我们每次都传递null。
答案 7 :(得分:-2)