我在下面编写的函数是否足以在当今大多数(如果不是全部)浏览器中预加载图像?
function preloadImage(url)
{
var img=new Image();
img.src=url;
}
我有一个图像URL数组,我遍历并preloadImage为每个URL 调用该函数。
(new Image()).src = url;
new Image().src = url;
我在下面编写的函数是否足以在当今大多数(如果不是全部)浏览器中预加载图像?
function preloadImage(url)
{
var img=new Image();
img.src=url;
}
我有一个图像URL数组,我遍历并preloadImage为每个URL 调用该函数。
(new Image()).src = url;
new Image().src = url;
Answers:
试试这个,我认为这样更好。
var images = [];
function preload() {
for (var i = 0; i < arguments.length; i++) {
images[i] = new Image();
images[i].src = preload.arguments[i];
}
}
//-- usage --//
preload(
"http://domain.tld/gallery/image-001.jpg",
"http://domain.tld/gallery/image-002.jpg",
"http://domain.tld/gallery/image-003.jpg"
)
来源:http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/
onload任何图像的处理程序
onload状态,或者只是实例化内存中的图像。
for (var i = 0.....
var
就我而言,将回调添加到onload事件的函数中非常有用:
function preloadImage(url, callback)
{
var img=new Image();
img.src=url;
img.onload = callback;
}
然后包装它,以完成要通过回调预加载的图像的URL数组的情况: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');
});
CSS2替代:http://www.thecssninja.com/css/even-better-image-preloading-with-css2
body:after {
content: url(img01.jpg) url(img02.jpg) url(img03.jpg);
display: none;
}
CSS3替代:https://perishablepress.com/preload-images-css3/ (H / T Linh大坝)
.preload-images {
display: none;
width: 0;
height: 0;
background: url(img01.jpg),
url(img02.jpg),
url(img03.jpg);
}
注意:容器中的图像display:none可能不会预加载。也许能见度:隐藏会更好,但我尚未对此进行测试。感谢Marco Del Valle指出这一点
display: none将不会预加载。
display: none(2)不使用width/height: 0,(3)放置no-repeat和位置,以使图像位于外面(-<width>px -<height>px将带您到那里,因此,如果图像全部为100px高度以下时,你可以使用0 -100px,换句话说url(...) no-repeat 0 -100px,
我建议您使用try / catch来防止某些可能的问题:
面向对象:
var preloadImage = function (url) {
try {
var _img = new Image();
_img.src = url;
} catch (e) { }
}
标准:
function preloadImage (url) {
try {
var _img = new Image();
_img.src = url;
} catch (e) { }
}
另外,虽然我喜欢DOM,但是旧的愚蠢的浏览器在使用DOM时可能会遇到问题,因此请完全避免使用IMHO,这与Freedev的贡献背道而驰。Image()在旧的垃圾桶浏览器中有更好的支持。
这种方法更加精细。在这里,您将所有预加载的图像存储在一个容器中,可能是div。然后,您可以显示图像或将其在DOM中移动到正确的位置。
function preloadImg(containerId, imgUrl, imageId) {
var i = document.createElement('img'); // or new Image()
i.id = imageId;
i.onload = function() {
var container = document.getElementById(containerId);
container.appendChild(this);
};
i.src = imgUrl;
}
在这里尝试,我还添加了一些评论
const preloadImage = src =>
new Promise(r => {
const image = new Image()
image.onload = r
image.onerror = r
image.src = src
})
// Preload an image
await preloadImage('https://picsum.photos/100/100')
// Preload a bunch of images in parallel
await Promise.all(images.map(x => preloadImage(x.src)))
是的,这将起作用,但是浏览器将限制(在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;
}
注意:如果您使用像Babel这样的编译器,这也将起作用。
'use strict';
function imageLoaded(src, alt = '') {
return new Promise(function(resolve) {
const image = document.createElement('img');
image.setAttribute('alt', alt);
image.setAttribute('src', src);
image.addEventListener('load', function() {
resolve(image);
});
});
}
async function runExample() {
console.log("Fetching my cat's image...");
const myCat = await imageLoaded('https://placekitten.com/500');
console.log("My cat's image is ready! Now is the time to load my dog's image...");
const myDog = await imageLoaded('https://placedog.net/500');
console.log('Whoa! This is now the time to enable my galery.');
document.body.appendChild(myCat);
document.body.appendChild(myDog);
}
runExample();
您可能还已经等待所有图像加载。
async function runExample() {
const [myCat, myDog] = [
await imageLoaded('https://placekitten.com/500'),
await imageLoaded('https://placedog.net/500')
];
document.body.appendChild(myCat);
document.body.appendChild(myDog);
}
或用于Promise.all并行加载它们。
async function runExample() {
const [myCat, myDog] = await Promise.all([
imageLoaded('https://placekitten.com/500'),
imageLoaded('https://placedog.net/500')
]);
document.body.appendChild(myCat);
document.body.appendChild(myDog);
}
我可以确认问题中的方法足以触发图像的下载和缓存(除非您通过响应标头禁止浏览器这样做),至少应在以下条件中进行:
为了测试这一点,我制作了一个小型Web应用程序,其中包含多个端点,每个端点睡眠10秒钟,然后再提供小猫的照片。然后,我添加了两个网页,其中一个包含一个<script>标签,其中使用问题中的preloadImage函数预加载了每只小猫,而另一个包含了使用的页面上的所有小猫<img>标签。
在上面的所有浏览器中,我发现如果我先访问预加载器页面,等待一会儿,然后转到带有<img>标签的页面,则我的小猫会立即呈现。这表明预加载器已在所有测试的浏览器中成功将小猫加载到缓存中。
您可以在https://github.com/ExplodingCabbage/preloadImage-test上查看或试用我用来测试它的应用程序。
特别要注意的是,即使循环的图像数量超过了浏览器一次愿意发出的并行请求的数量,该技术也可以在上面的浏览器中使用,这与罗宾的回答相反。图像预加载的速率当然会受到浏览器愿意发送的并行请求数量的限制,但是最终它将请求您调用的每个图像URL preloadImage()。
使用头部的link标签,浏览器将运行最佳。
export function preloadImages (imageSources: string[]): void {
imageSources
.forEach(i => {
const linkEl = document.createElement('link');
linkEl.setAttribute('rel', 'preload');
linkEl.setAttribute('href', i);
linkEl.setAttribute('as', 'image');
document.head.appendChild(linkEl);
});
}
img对象的引用,例如在父作用域的数组中。