使用 jQuery 预加载图像

IT技术 javascript jquery
2021-01-13 19:46:41

我正在寻找一种快速简便的方法来使用 JavaScript 预加载图像。如果这很重要,我正在使用 jQuery。

我在这里看到了这个(http://nettuts.com...):

function complexLoad(config, fileNames) {
  for (var x = 0; x < fileNames.length; x++) {
    $("<img>").attr({
      id: fileNames[x],
      src: config.imgDir + fileNames[x] + config.imgFormat,
      title: "The " + fileNames[x] + " nebula"
    }).appendTo("#" + config.imgContainer).css({ display: "none" });
  }
};

但是,对于我想要的东西,它看起来有点过分!

我知道有 jQuery 插件可以做到这一点,但它们看起来都有些大(大小);我只需要一种快速、简单和简短的方式来预加载图像!

6个回答

快速简单的:

function preload(arrayOfImages) {
    $(arrayOfImages).each(function(){
        $('<img/>')[0].src = this;
        // Alternatively you could use:
        // (new Image()).src = this;
    });
}

// Usage:

preload([
    'img/imageName.jpg',
    'img/anotherOne.jpg',
    'img/blahblahblah.jpg'
]);

或者,如果你想要一个 jQuery 插件:

$.fn.preload = function() {
    this.each(function(){
        $('<img/>')[0].src = this;
    });
}

// Usage:

$(['img1.jpg','img2.jpg','img3.jpg']).preload();
我相信$('<img />')只是在内存中创建一个图像元素(见链接)。看起来'$('<img src="' + this + '" />')实际上会在隐藏的 DIV 中创建元素,因为它更“复杂”。但是,我认为大多数浏览器不需要这样做。
2021-03-13 19:46:41
确保在内部调用它,$(window).load(function(){/*preload here*/});因为这样会首先加载文档中的所有图像,很可能首先需要它们。
2021-03-13 19:46:41
这是编写 jQuery 插件的一种奇怪的方式。为什么不$.preload(['img1.jpg', 'img2.jpg'])呢?
2021-03-31 19:46:41
不需要将图像元素插入到 DOM 中以确保浏览器缓存它吗?
2021-04-02 19:46:41
@RegionalC -load在设置事件之前设置事件可能更安全src,以防图像在设置加载事件之前完成加载?$('<img/>').load(function() { /* it's loaded! */ }).attr('src', this);
2021-04-05 19:46:41

这是第一个响应的调整版本,它实际上将图像加载到 DOM 中并默认隐藏它。

function preload(arrayOfImages) {
    $(arrayOfImages).each(function () {
        $('<img />').attr('src',this).appendTo('body').css('display','none');
    });
}
将它们插入 DOM 有什么好处?
2021-03-15 19:46:41
我也想知道将它们插入 DOM 的好处。
2021-03-18 19:46:41
丹尼斯·朗戈。将图像附加到 DOM 修复了 Chrome 上的随机重新加载。谢谢!
2021-03-23 19:46:41
根据我的经验,将图像预加载到 DOM 会使浏览器知道它的存在并正确缓存它。否则,图像仅存在于仅适用于单页应用程序的内存中。
2021-03-24 19:46:41
hide()比 更简洁css('display', 'none')
2021-04-04 19:46:41

使用 JavaScript Image 对象

此功能允许您在加载所有图片时触发回调。但是,请注意,如果至少没有加载一个资源,它将永远不会触发回调。这可以通过实现onerror回调和增加loaded值或处理错误来轻松解决

var preloadPictures = function(pictureUrls, callback) {
    var i,
        j,
        loaded = 0;

    for (i = 0, j = pictureUrls.length; i < j; i++) {
        (function (img, src) {
            img.onload = function () {                               
                if (++loaded == pictureUrls.length && callback) {
                    callback();
                }
            };

            // Use the following callback methods to debug
            // in case of an unexpected behavior.
            img.onerror = function () {};
            img.onabort = function () {};

            img.src = src;
        } (new Image(), pictureUrls[i]));
    }
};

preloadPictures(['http://foo/picture.bar', 'http://foo/picture.bar', 'http://foo/picture.bar', 'http://foo/picture.bar'], function(){
    console.log('a');
});

preloadPictures(['http://foo/picture.bar', 'http://foo/picture.bar', 'http://foo/picture.bar', 'http://foo/picture.bar'], function(){
    console.log('b');
});
精彩的代码。我认为onload即使图像被缓存也会触发事件是否正确(因为img.onload是先声明的)。这是我的测试所显示的。
2021-03-09 19:46:41
@Gazillion 提供更多细节。你如何定义“不工作”?什么是FF版本?
2021-03-11 19:46:41
做正确的事,使用 JavaScript Image 对象。您是否观察到人们在这些答案中做错了事?
2021-03-14 19:46:41
我喜欢这个解决方案,但我刚刚发现它在我的 Firefox 中不起作用。是只有我还是其他人有同样的问题?
2021-03-16 19:46:41
@alex 可能,是的。如果目标是预加载(这表明性能顺序),那么我更愿意看到原始 JS 选项而不是 jQuery 相关选项。
2021-04-06 19:46:41

JP,在检查您的解决方案后,我仍然在 Firefox 中遇到问题,在加载页面之前它不会预加载图像。我通过sleep(5)在我的服务器端脚本中放入一些发现这一点我根据您的解决方案实施了以下解决方案,这似乎解决了这个问题。

基本上,我向您的 jQuery 预加载插件添加了一个回调,以便在所有图像正确加载后调用它。

// Helper function, used below.
// Usage: ['img1.jpg','img2.jpg'].remove('img1.jpg');
Array.prototype.remove = function(element) {
  for (var i = 0; i < this.length; i++) {
    if (this[i] == element) { this.splice(i,1); }
  }
};

// Usage: $(['img1.jpg','img2.jpg']).preloadImages(function(){ ... });
// Callback function gets called after all images are preloaded
$.fn.preloadImages = function(callback) {
  checklist = this.toArray();
  this.each(function() {
    $('<img>').attr({ src: this }).load(function() {
      checklist.remove($(this).attr('src'));
      if (checklist.length == 0) { callback(); }
    });
  });
};

出于兴趣,在我的上下文中,我使用它如下:

$.post('/submit_stuff', { id: 123 }, function(response) {
  $([response.imgsrc1, response.imgsrc2]).preloadImages(function(){
    // Update page with response data
  });
});

希望这可以帮助从 Google 访问此页面的人(就像我一样)寻找在 Ajax 调用中预加载图像的解决方案。

对于那些对搞乱 Array.prototype 不感兴趣的人,您可以这样做:checklist = this.length在 onload 函数中:checklist--然后:if (checklist == 0) callback();
2021-03-11 19:46:41
.attr({ src: this }).load(function() {...})应该是,.load(function() {...}).attr({ src: this })否则你会遇到缓存问题。
2021-03-15 19:46:41
很好而且很快,但是如果其中一个图像损坏或无法加载,此代码将永远不会触发回调。
2021-03-20 19:46:41
一切都会好起来的,但是向不拥有的对象添加新方法或删除现有方法是 JavaScript 中最糟糕的做法之一。
2021-03-30 19:46:41

这一行 jQuery 代码创建(并加载)了一个 DOM 元素 img 而不显示它:

$('<img src="img/1.jpg"/>');
@huzzah - 你最好只使用精灵。减少 http 请求。:)
2021-03-17 19:46:41