代码之家  ›  专栏  ›  技术社区  ›  Skilldrick

使用javascript/jquery预加载图像的最终最佳方法是什么?

  •  50
  • Skilldrick  · 技术社区  · 15 年前

    我完全知道这个问题到处都有人问和回答,不管是问还是答。然而,每次似乎都有不同的答案,例如 this , this that .

    我不在乎它是否在使用jquery——重要的是它可以工作,而且是跨浏览器的。]

    那么,预加载图像的最佳方法是什么?

    8 回复  |  直到 9 年前
        1
  •  65
  •   Community Dan Abramov    7 年前

    不幸的是,这取决于你的目的。 如果你打算使用这些图片作为风格,你最好的选择是使用精灵。 http://www.alistapart.com/articles/sprites2

    但是,如果您计划使用<img>标记中的图像,则需要预先加载它们

    function preload(sources)
    {
      var images = [];
      for (i = 0, length = sources.length; i < length; ++i) {
        images[i] = new Image();
        images[i].src = sources[i];
      }
    }
    

    (修改源取自 What is the best way to preload multiple images in JavaScript? )

    使用 new Image() 不涉及使用dom方法的开销,但将为指定的映像添加一个新的请求到队列中。由于图像目前还没有添加到页面中,因此不需要重新渲染。不过,我建议您在页面的末尾添加这个脚本(因为在可能的情况下,您的所有脚本都应该这样),以防止它容纳更多的关键元素。

    编辑:编辑以反映评论,并正确指出 Image 需要对象才能正常工作。谢谢,我很遗憾没有仔细检查。

    edit2:编辑以使可重用性更加明显

    编辑3(3年后):

    由于浏览器处理不可见图像的方式发生了变化(显示:无,或者,如本答案中所述,从未附加到文档中),因此首选新的预加载方法。

    可以使用Ajax请求强制提前检索图像。使用jquery,例如:

    jQuery.get(source);
    

    或者在前面的示例中,您可以执行以下操作:

    function preload(sources)
    {
      jQuery.each(sources, function(i,source) { jQuery.get(source); });
    }
    

    请注意,这不适用于雪碧的情况,因为它很好。这仅适用于照片库或幻灯片/旋转木马等图像加载失败的情况,因为它们最初不可见。

    另外请注意,此方法不适用于IE(通常不使用Ajax来检索图像数据)。

        2
  •  14
  •   aleemb    15 年前

    斯普林汀

    正如其他人所提到的,由于各种原因,spriting工作得相当好,但是,它并没有想象的那么好。

    • 好处是,您最终只为您的图像提出一个HTTP请求。但是YMMV。
    • 在底层,您将在一个HTTP请求中加载所有内容。由于大多数当前浏览器仅限于2个并发连接,因此图像请求可以阻止其他请求。因此,ymmv和类似菜单背景的东西可能不会呈现一点。
    • 多个图像共享相同的调色板,因此有一些保存,但情况并非总是如此,甚至可以忽略不计。
    • 压缩得到了改进,因为图像之间有更多的共享数据。

    但是处理不规则形状是很困难的。把所有新的图像组合到新的图像中是另一个烦恼。

    使用<img>标签的低插孔方法

    如果你正在寻找 最权威的 解决方案,那么你应该使用我仍然喜欢的低插孔方法。创建指向文档末尾图像的链接,并设置 width height 到1x1像素,并将它们附加到隐藏的分区中。如果它们位于页面的末尾,则它们将在其他内容之后加载。

        3
  •  6
  •   Mahn    11 年前

    截至2013年1月,这里描述的所有方法都不适用于我,所以这里介绍的是对chrome 25和firefox 18的测试和使用。使用jQuery和 this plugin 要解决加载事件异常:

    function preload(sources, callback) {
        if(sources.length) {
            var preloaderDiv = $('<div style="display: none;"></div>').prependTo(document.body);
    
            $.each(sources, function(i,source) {
                $("<img/>").attr("src", source).appendTo(preloaderDiv);
    
                if(i == (sources.length-1)) {
                    $(preloaderDiv).imagesLoaded(function() {
                        $(this).remove();
                        if(callback) callback();
                    });
                }
            });
        } else {
            if(callback) callback();
        }
    }
    

    用途:

    preload(['/img/a.png', '/img/b.png', '/img/c.png'], function() { 
        console.log("done"); 
    });
    

    请注意,如果缓存被禁用,您将得到混合的结果,这在开发人员工具打开时,默认情况下是在chrome上的,因此请记住这一点。

        4
  •  3
  •   Angel    13 年前

    在我看来,在接下来的几年中,使用一些库引入的multipart xmlhttprequest将是首选的解决方案。然而,IE<V8仍然不支持data:uri(甚至IE8也有有限的支持,最多允许32kb)。下面是并行图像预加载的一个实现- http://code.google.com/p/core-framework/wiki/ImagePreloading ,它捆绑在框架中,但仍然值得一看。

        5
  •  1
  •   Scott Cleland    9 年前

    这是很久以前的事了,所以我不知道还有多少人对预加载图像感兴趣。

    我的解决方案更简单。

    我刚用了CSS。

    #hidden_preload {
        height: 1px;
        left: -20000px;
        position: absolute;
        top: -20000px;
        width: 1px;
    }
    
        6
  •  0
  •   Afonso Praça    11 年前

    下面是我的简单解决方案,在图像加载后淡入。

        function preloadImage(_imgUrl, _container){
            var image = new Image();
                image.src = _imgUrl;
                image.onload = function(){
                    $(_container).fadeTo(500, 1);
                };
            }
    
        7
  •  0
  •   DanH    10 年前

    对于我的用例,我有一个带全屏图像的旋转木马,我想预加载它。但是,由于图像按顺序显示,并且每个加载可能需要几秒钟时间,所以按顺序、顺序加载它们是很重要的。

    为此,我使用了异步库的 waterfall() 方法( https://github.com/caolan/async#waterfall )

            // Preload all images in the carousel in order.
            image_preload_array = [];
            $('div.carousel-image').each(function(){
                var url = $(this).data('image-url');
                image_preload_array.push(function(callback) {
                    var $img = $('<img/>')
                    $img.load(function() {
                        callback(null);
                    })[0].src = url;
                });
            });
            async.waterfall(image_preload_array);
    

    这是通过创建一个函数数组来实现的,每个函数都传递参数 callback() 它需要执行它才能调用数组中的下一个函数。的第一个参数 回退() 是一条错误消息,如果提供非空值,它将退出序列,因此每次传递空值。

        8
  •  -2
  •   Community Dan Abramov    7 年前