使用JavaScript / jQuery预加载图像的最佳方法是什么?

我完全意识到,这个问题已经被问及到处都回答了,无论是在SO还是在OFF。 然而,每一次似乎有不同的答案,例如这个 , 这个和那个 。

我不在乎它是否使用jQuery – 重要的是它的工作原理,并且是跨浏览器。

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

不幸的是,这取决于你的目的。 如果你打算使用风格的图像,最好的select是使用精灵。 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中的最佳方式? )

使用new Image()不涉及使用DOM方法的开销,但是指定图像的新请求将被添加到队列中。 由于图像在这一点上并未实际添加到页面中,因此不涉及重新渲染。 但是,我build议将其添加到页面的最后(因为所有的脚本都应该尽可能),以防止它阻塞更多的关键元素。

编辑:编辑反映评论相当正确指出,单独的Image对象需要正常工作。 谢谢,我的不好,不仔细检查。

编辑2:编辑使重复使用更加明显

编辑3(3年后):

由于浏览器处理不可见图像的方式发生了变化(显示:无,或者如在此答案中,从未附加到文档中),所以预加载的新方法是优选的。

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

 jQuery.get(source); 

或者在我们之前的例子中,你可以这样做:

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

请注意,这并不适用于原样好的精灵。 这只是像照片画廊或滑块/旋转木马与图像不加载,因为它们是最初不可见的图像。

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

拼合

正如其他人所说的那样,由于种种原因,spriting运行得非常好,但是它并不像它那样好。

  • 另一方面,你最终只能为你的图像做一个HTTP请求。 YMMV虽然。
  • 在不利的方面,你正在加载一个HTTP请求的一切。 由于大多数当前浏览器被限制为2个并发连接,所以图像请求可以阻止其他请求。 因此,YMMV和你的菜单背景可能不会呈现一点点。
  • 多个图像共享相同的调色板,所以有一些节省,但这并不总是如此,即使如此,它是微不足道的。
  • 由于图像之间有更多的共享数据,所以压缩得到了改善。

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

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

如果你正在寻找最权威的解决scheme,那么你应该采用我更喜欢的低插口方法。 在文档的末尾创build<img>指向图像的链接,并将widthheight设置为1×1像素,并将其放置在隐藏的div中。 如果他们在页面的最后,他们将被加载其他内容之后。

截至2013年1月,这里描述的方法都没有为我工作,所以这里是什么,而是testing和使用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"); }); 

请注意,如果禁用了caching,那么在开发人员工具处于打开状态时,默认情况下会在Chrome上得到混合结果,因此请记住这一点。

在我看来,使用某些库引入的Multipart XMLHttpRequest将成为未来几年的首选解决scheme。 不过IE <v8,依然不支持数据:uri(即使IE8支持有限,最高可达32kb)。 这是一个并行图像预加载的实现 – http://code.google.com/p/core-framework/wiki/ImagePreloading ,它是捆绑在框架中,但仍值得一看。

这是很久以前,所以我不知道有多less人仍然有兴趣预载图像。

我的解决scheme更加简单。

我只是使用CSS。

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

这里是我的简单的解决scheme,加载后的图像淡入淡出。

  function preloadImage(_imgUrl, _container){ var image = new Image(); image.src = _imgUrl; image.onload = function(){ $(_container).fadeTo(500, 1); }; } 

对于我的使用案例,我有一个全屏图像的旋转木马,我想预先加载。 但是,由于图像按顺序显示,并且可能需要几秒钟才能加载,因此按顺序加载它们非常重要。

为此我使用了asynchronous库的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); 

这是通过创build一个函数数组,每个函数传递参数callback() ,它需要执行以调用数组中的下一个函数。 callback()的第一个参数是一个错误消息,如果提供了一个非空的值,它将退出序列,所以我们每次都传递null。

看到这个:

http://www.mattfarina.com/2007/02/01/preloading_images_with_jquery

SO的相关问题:

jquery隐藏了预加载

Interesting Posts