我在下面写的函数是否足以在大多数(如果不是全部的话)当前常用的浏览器中预加载图像?

function preloadImage(url)
{
    var img=new Image();
    img.src=url;
}

我有一个图像URL数组,我循环遍历并为每个URL调用preloadImage函数。


当前回答

截至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"
);

预览:

注:

尽量不要同时预加载太多的图像(这可能会导致主要的性能问题)-我通过隐藏图像来解决这个问题,我知道在某些事件中不可见。当然,当我需要的时候,再给他们看一遍。

其他回答

试试这个,我觉得这个更好。

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/

您可以将此代码移动到index.html,以便从任何url预加载图像

<link rel="preload" href="https://via.placeholder.com/160" as="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;
}

在这里试试,我也添加了一些评论

ECMAScript 2017兼容浏览器的解决方案

注意:如果你使用的是像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。所有这些都是并行加载的。

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);
}

更多关于承诺。

更多关于“异步”函数。

更多关于解构赋值的内容。

更多关于ECMAScript 2015。

更多关于ECMAScript 2017。

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岭坝)

.preload-images {
  display: none; 
  width: 0;
  height: 0;
  background: url(img01.jpg),
              url(img02.jpg),
              url(img03.jpg);
}

注意:带有display:none的容器中的图像可能无法预加载。 也许可视性:隐藏会更好,但我还没有测试过。感谢Marco Del Valle指出这一点