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

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

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


当前回答

我可以确认,在这个问题的方法是足以触发图像下载和缓存(除非你已经禁止浏览器这样做通过你的响应头),至少:

铬74 Safari 12 火狐66 边缘17

为了测试这一点,我做了一个小的网络应用程序,它有几个端点,每个端点都休眠10秒钟,然后提供一张小猫的照片。然后我添加了两个网页,其中一个包含<script>标记,其中每个小猫都是使用来自问题的preloadImage函数预加载的,另一个包含页面上使用<img>标记的所有小猫。

在上面所有的浏览器中,我发现如果我先访问预加载器页面,等待一段时间,然后转到带有<img>标记的页面,我的小猫会立即呈现。这表明预加载器在所有测试的浏览器中成功地将小猫加载到缓存中。

您可以在https://github.com/ExplodingCabbage/preloadImage-test上查看或试用我用于测试的应用程序。

特别要注意的是,即使循环图像的数量超过浏览器一次愿意发出的并行请求的数量,这种技术也可以在上述浏览器中工作,这与Robin的回答所建议的相反。图像预加载的速率当然会受到浏览器愿意发送多少并行请求的限制,但它最终会请求您调用preloadImage()的每个图像URL。

其他回答

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

我建议你使用try/catch来防止一些可能的问题:

OOP:

    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时遇到问题,所以恕我直言,与freedev的贡献相反,完全避免使用DOM。Image()在旧的垃圾浏览器中有更好的支持。

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指出这一点

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

预览:

注:

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

对于感兴趣的人,这里有一些OP提供的代码的替代方案。

预加载图像()

函数现在返回

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

v1:通过将图像作为参数传递给preloadImages()来预加载

返回函数返回的Image类型对象数组。有助于检查预紧状态。

js小提琴

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

function preloadImages() {
  const images = []
  for (var i = 0; i < arguments.length; i++) {
    images[i] = preloadImage(arguments[i])
  }
  return images
}

  //-- usage --//
const images = preloadImages(
  "http://domain.tld/gallery/image-001.jpg",
  "http://domain.tld/gallery/image-002.jpg",
  "http://domain.tld/gallery/image-003.jpg"
)

v2:通过将图像作为数组传递给preloadImages()来预加载

不类型安全 用Image类型对象覆盖提供的数组。返回函数返回的Image类型对象数组。有助于检查预紧状态。

js小提琴

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

function preloadImages(images) {
  for (var i = 0; i < images.length; i++) {
    images[i] = preloadImage(images[i])
  }
  return images
}

//-- usage --//
let arr = [
  "http://domain.tld/gallery/image-001.jpg",
  "http://domain.tld/gallery/image-002.jpg",
  "http://domain.tld/gallery/image-003.jpg"
]

const images = preloadImages(arr)
console.dir(images)

v3:通过传递数组和/或参数来预加载preloadImages()

类型安全。返回函数返回的Image类型对象数组。有助于检查预紧状态。

js小提琴

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

function preloadImages() {
  const images = []
  let c = 0
  for (var i = 0; i < arguments.length; i++) {
    if (Array.isArray(arguments[i])) {
      for(var arr = 0; arr < arguments[i].length; arr++) {
        if(typeof arguments[i][arr] == 'string') {
            images[c] = preloadImage(arguments[i][arr])
            c++
        }
      }
    }
    else if(typeof arguments[i] == 'string') {
      images[c] = preloadImage(arguments[i])
      c++
    }
  }
  return images
}

  //-- usage --//
var arr = [
  "http://domain.tld/gallery/image-001.jpg",
  "http://domain.tld/gallery/image-002.jpg"
]

const images = preloadImages(
  arr,
  "http://domain.tld/gallery/image-003.jpg",
  "http://domain.tld/gallery/image-004.jpg",
  [
      "http://domain.tld/gallery/image-005.jpg", 
      "http://domain.tld/gallery/image-006.jpg"
  ]
)

console.dir(images)

灵感来源于:http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/