我在下面写的函数是否足以在大多数(如果不是全部的话)当前常用的浏览器中预加载图像?
function preloadImage(url)
{
var img=new Image();
img.src=url;
}
我有一个图像URL数组,我循环遍历并为每个URL调用preloadImage函数。
我在下面写的函数是否足以在大多数(如果不是全部的话)当前常用的浏览器中预加载图像?
function preloadImage(url)
{
var img=new Image();
img.src=url;
}
我有一个图像URL数组,我循环遍历并为每个URL调用preloadImage函数。
当前回答
是的,这是可行的,但是浏览器会限制(4-8之间)实际的调用,因此不会缓存/预加载所有想要的图像。
更好的方法是在使用图像之前调用onload,如下所示:
function (imageUrls, index) {
var img = new Image();
img.onload = function () {
console.log('isCached: ' + isCached(imageUrls[index]));
*DoSomething..*
img.src = imageUrls[index]
}
function isCached(imgUrl) {
var img = new Image();
img.src = imgUrl;
return img.complete || (img .width + img .height) > 0;
}
其他回答
截至2020年的工作解决方案
这篇文章中的大多数答案不再有效-(至少在Firefox上)
以下是我的解决方案:
var cache = document.createElement("CACHE");
cache.style = "position:absolute;z-index:-1000;opacity:0;";
document.body.appendChild(cache);
function preloadImage(url) {
var img = new Image();
img.src = url;
img.style = "position:absolute";
cache.appendChild(img);
}
用法:
preloadImage("example.com/yourimage.png");
显然<cache>不是一个“已定义”的元素,所以如果你愿意,你可以使用<div>。
在你的CSS中使用它,而不是应用style属性:
cache {
position: absolute;
z-index: -1000;
opacity: 0;
}
cache image {
position: absolute;
}
如果你测试过这个,请留下评论。
注:
不应用display: none;缓存-这将不会加载 的形象。 不要调整图像元素的大小,因为这也会影响 加载图像的质量,当你来使用它。 设置位置:绝对于图像是必要的,因为图像元素最终会在视口之外——导致它们无法加载,并影响性能。
更新
虽然上面的解决方案是有效的,但这里有一个小更新,我做了一个很好的结构:
(这现在也接受多个图像在一个函数)
var cache = document.createElement("CACHE");
document.body.appendChild(cache);
function preloadImage() {
for (var i=0; i<arguments.length; i++) {
var img = new Image();
img.src = arguments[i];
var parent = arguments[i].split("/")[1]; // Set to index of folder name
if ($(`cache #${parent}`).length == 0) {
var ele = document.createElement("DIV");
ele.id = parent;
cache.appendChild(ele);
}
$(`cache #${parent}`)[0].appendChild(img);
console.log(parent);
}
}
preloadImage(
"assets/office/58.png",
"assets/leftbutton/124.png",
"assets/leftbutton/125.png",
"assets/leftbutton/130.png",
"assets/leftbutton/122.png",
"assets/leftbutton/124.png"
);
预览:
注:
尽量不要同时预加载太多的图像(这可能会导致主要的性能问题)-我通过隐藏图像来解决这个问题,我知道在某些事件中不可见。当然,当我需要的时候,再给他们看一遍。
HTML生活标准现在支持“预加载”
根据W3C HTML规范,你现在可以像这样使用JavaScript预加载:
var link = document.createElement("link");
link.rel = "preload";
link.as = "image";
link.href = "https://example.com/image.png";
document.head.appendChild(link);
您可以将此代码移动到index.html,以便从任何url预加载图像
<link rel="preload" href="https://via.placeholder.com/160" as="image">
在我的例子中,为onload事件添加一个回调函数是有用的:
function preloadImage(url, callback)
{
var img=new Image();
img.src=url;
img.onload = callback;
}
然后包装它的情况下,一个url数组的图像被预加载回调对all是完成的: https://jsfiddle.net/4r0Luoy7/
function preloadImages(urls, allImagesLoadedCallback){
var loadedCounter = 0;
var toBeLoadedNumber = urls.length;
urls.forEach(function(url){
preloadImage(url, function(){
loadedCounter++;
console.log('Number of loaded images: ' + loadedCounter);
if(loadedCounter == toBeLoadedNumber){
allImagesLoadedCallback();
}
});
});
function preloadImage(url, anImageLoadedCallback){
var img = new Image();
img.onload = anImageLoadedCallback;
img.src = url;
}
}
// Let's call it:
preloadImages([
'//upload.wikimedia.org/wikipedia/commons/d/da/Internet2.jpg',
'//www.csee.umbc.edu/wp-content/uploads/2011/08/www.jpg'
], function(){
console.log('All images were loaded');
});
我可以确认,在这个问题的方法是足以触发图像下载和缓存(除非你已经禁止浏览器这样做通过你的响应头),至少:
铬74 Safari 12 火狐66 边缘17
为了测试这一点,我做了一个小的网络应用程序,它有几个端点,每个端点都休眠10秒钟,然后提供一张小猫的照片。然后我添加了两个网页,其中一个包含<script>标记,其中每个小猫都是使用来自问题的preloadImage函数预加载的,另一个包含页面上使用<img>标记的所有小猫。
在上面所有的浏览器中,我发现如果我先访问预加载器页面,等待一段时间,然后转到带有<img>标记的页面,我的小猫会立即呈现。这表明预加载器在所有测试的浏览器中成功地将小猫加载到缓存中。
您可以在https://github.com/ExplodingCabbage/preloadImage-test上查看或试用我用于测试的应用程序。
特别要注意的是,即使循环图像的数量超过浏览器一次愿意发出的并行请求的数量,这种技术也可以在上述浏览器中工作,这与Robin的回答所建议的相反。图像预加载的速率当然会受到浏览器愿意发送多少并行请求的限制,但它最终会请求您调用preloadImage()的每个图像URL。