使用jQuery预加载图像

时间:2009-01-24 21:25:55

标签: javascript jquery

我正在寻找一种使用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插件可以做到这一点,但它们看起来都有点大(大小);我只需要一种快速,简单和简短的预加载图像的方法!

21 个答案:

答案 0 :(得分:960)

快速简单:

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

答案 1 :(得分:99)

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

function preload(arrayOfImages) {
    $(arrayOfImages).each(function () {
        $('<img />').attr('src',this).appendTo('body').css('display','none');
    });
}

答案 2 :(得分:50)

使用JavaScript Image object

此功能允许您在加载所有照片时触发回调。但请注意,如果未加载至少一个资源,它将永远不会触发回调。通过实施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');
});

答案 3 :(得分:35)

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

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

// 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调用上预加载图像的解决方案。

答案 4 :(得分:24)

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

$('<img src="img/1.jpg"/>');

答案 5 :(得分:22)

$.fn.preload = function (callback) {
  var length = this.length;
  var iterator = 0;

  return this.each(function () {
    var self = this;
    var tmp = new Image();

    if (callback) tmp.onload = function () {
      callback.call(self, 100 * ++iterator / length, iterator === length);
    };

    tmp.src = this.src;
  });
};

用法非常简单:

$('img').preload(function(perc, done) {
  console.log(this, perc, done);
});

http://jsfiddle.net/yckart/ACbTK/

答案 6 :(得分:19)

我有一个处理此问题的小插件。

它被称为waitForImages,它可以处理img元素或任何引用CSS中图像的元素,例如div { background: url(img.png) }

如果您只是想加载所有图像,包括CSS中引用的图像,请按以下步骤操作:)

$('body').waitForImages({
    waitForAll: true,
    finished: function() {
       // All images have loaded.
    }  
});

答案 7 :(得分:13)

这个jquery imageLoader插件只有1.39kb

用法:

$({}).imageLoader({
    images: [src1,src2,src3...],
    allcomplete:function(e,ui){
        //images are ready here
        //your code - site.fadeIn() or something like that
    }
});

还有其他选项,例如您是要同步还是异步加载图像以及每个单独图像的完整事件。

答案 8 :(得分:13)

你可以使用css display:none;规则在你的html中加载图像,然后用js或jquery显示它们

不要使用js或jquery函数来预加载只是一个css规则Vs要执行多行js

示例:Html

<img src="someimg.png" class="hide" alt=""/>

的CSS:

.hide{
display:none;
}

jQuery的:

//if want to show img 
$('.hide').show();
//if want to hide
$('.hide').hide();

通过jquery / javascript预加载图像并不好,因为图像在页面加载需要几毫秒才能解析和执行脚本,特别是如果它们是大图像,那么将它们隐藏在hml中也更好对于性能,原因图像实际上是预装的,根本没有显示,直到你显示出来!

答案 9 :(得分:9)

在jQuery中预加载图像并获得回调函数的快速,无插件方法是一次创建多个img标记并计算响应,例如

function preload(files, cb) {
    var len = files.length;
    $(files.map(function(f) {
        return '<img src="'+f+'" />';
    }).join('')).load(function () {
        if(--len===0) {
            cb();
        }
    });
}

preload(["one.jpg", "two.png", "three.png"], function() {
    /* Code here is called once all files are loaded. */
});
​    ​

请注意,如果你想支持IE7,你需要使用这个稍微不那么漂亮的版本(这也适用于其他浏览器):

function preload(files, cb) {
    var len = files.length;
    $($.map(files, function(f) {
        return '<img src="'+f+'" />';
    }).join('')).load(function () {
        if(--len===0) {
            cb();
        }
    });
}

答案 10 :(得分:7)

谢谢!我会在JP的答案上添加一点点riff - 我不知道这是否会对任何人有所帮助,但是这样你就不必创建一个图像数组了,你可以预先加载你所有的大图像如果你正确地命名你的拇指。这很方便,因为我有一个人正在用html编写所有页面,它确保他们没有更少的步骤 - 消除了创建图像数组的需要,以及另一个可能搞砸的步骤。

$("img").each(function(){
    var imgsrc = $(this).attr('src');
    if(imgsrc.match('_th.jpg') || imgsrc.match('_home.jpg')){
      imgsrc = thumbToLarge(imgsrc);
      (new Image()).src = imgsrc;   
    }
});

基本上,对于页面上的每个图像,它会抓取每个图像的src,如果它符合某些条件(是拇指或主页图像),它会更改名称(图像src中的基本字符串替换),然后加载图像。

在我的情况下,页面上充满了所有像image_th.jpg一样的拇指图像,所有相应的大图像都被命名​​为image_lg.jpg。拇指向大只用_lg.jpg替换_th.jpg然后预加载所有大图像。

希望这有助于某人。

答案 11 :(得分:3)

    jQuery.preloadImage=function(src,onSuccess,onError)
    {
        var img = new Image()
        img.src=src;
        var error=false;
        img.onerror=function(){
            error=true;
            if(onError)onError.call(img);
        }
        if(error==false)    
        setTimeout(function(){
            if(img.height>0&&img.width>0){ 
                if(onSuccess)onSuccess.call(img);
                return img;
            }   else {
                setTimeout(arguments.callee,5);
            }   
        },0);
        return img; 
    }

    jQuery.preloadImages=function(arrayOfImages){
        jQuery.each(arrayOfImages,function(){
            jQuery.preloadImage(this);
        })
    }
 // example   
    jQuery.preloadImage(
        'img/someimage.jpg',
        function(){
            /*complete
            this.width!=0 == true
            */
        },
        function(){
            /*error*/
        }
    )

答案 12 :(得分:3)

我使用以下代码:

$("#myImage").attr("src","img/spinner.gif");

var img = new Image();
$(img).load(function() {
    $("#myImage").attr("src",img.src);
});
img.src = "http://example.com/imageToPreload.jpg";

答案 13 :(得分:1)

我会使用Manifest文件告诉(现代)Web浏览器还加载所有相关图像并缓存它们。使用Grunt和grunt-manifest自动执行此操作,再也不用担心预加载脚本,缓存失效器,CDN等。

https://github.com/gunta/grunt-manifest

答案 14 :(得分:0)

即使在IE9中,这对我也有用:

$('<img src="' + imgURL + '"/>').on('load', function(){ doOnLoadStuff(); });

答案 15 :(得分:0)

我希望使用Google Maps API自定义叠加层执行此操作。他们的示例代码只使用JS插入IMG元素,并显示图像占位符框,直到加载图像。我在这里找到了一个对我有用的答案:https://stackoverflow.com/a/10863680/2095698

$('<img src="'+ imgPaht +'">').load(function() {
$(this).width(some).height(some).appendTo('#some_target');
});

这会预先加载前面建议的图像,然后在加载img URL后使用处理程序附加img对象。 jQuery的文档警告缓存的图像不能很好地处理这个事件/处理程序代码,但它在FireFox和Chrome中对我有用,我不必担心IE。

答案 16 :(得分:0)

我通常在项目中使用此代码段在页面中加载图像。 您可以在这里https://jsfiddle.net/ftor34ey/

查看结果
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

<img src="https://live.staticflickr.com/65535/50020763321_d61d49e505_k_d.jpg" width="100" />
<img src="https://live.staticflickr.com/65535/50021019427_692a8167e9_k_d.jpg" width="100" />
<img src="https://live.staticflickr.com/65535/50020228418_d730efe386_k_d.jpg" width="100" />
<img src="https://live.staticflickr.com/65535/50020230828_7ef175d07c_k_d.jpg" width="100" />

<div style="background-image: url(https://live.staticflickr.com/65535/50020765826_e8da0aacca_k_d.jpg);"></div>
<style>
    .bg {
        background-image: url("https://live.staticflickr.com/65535/50020765651_af0962c22e_k_d.jpg");
    }
</style>
<div class="bg"></div>

<div id="loadingProgress"></div>

该脚本将页面的所有srcbackground-image保存在数组中,并全部加载。

您可以通过变量loadCount查看/阅读/显示加载进度。

let backgroundImageArray = [];

function backgroundLoading(i) {

    let loadCount = 0;

    let img = new Image();
    $(img).on('load', function () {

        if (i < backgroundImageArray.length) {

            loadCount = parseInt(((100 / backgroundImageArray.length) * i));
            backgroundLoading(i + 1);

        } else {

            loadCount = 100;
            // do something when the page finished to load all the images
            console.log('loading completed!!!');
            $('#loadingProgress').append('<div>loading completed!!!</div>');

        }

        console.log(loadCount + '%');
        $('#loadingProgress').append('<div>' + loadCount + '%</div>');

    }).attr('src', backgroundImageArray[i - 1]);

}

$(document).ready(function () {

    $('*').each(function () {

        var backgroundImage = $(this).css('background-image');
        var putInArray = false;

        var check = backgroundImage.substr(0, 3);

        if (check == 'url') {

            backgroundImage = backgroundImage.split('url(').join('').split(')').join('');
            backgroundImage = backgroundImage.replace('"', '');
            backgroundImage = backgroundImage.replace('"', '');

            if (backgroundImage.substr(0, 4) == 'http') {
                backgroundImage = backgroundImage;
            }
            putInArray = true;

        } else if ($(this).get(0).tagName == 'IMG') {

            backgroundImage = $(this).attr('src');
            putInArray = true;

        }

        if (putInArray) {
            backgroundImageArray[backgroundImageArray.length] = backgroundImage;
        }

    });

    backgroundLoading(1);

});

答案 17 :(得分:-1)

function preload(imgs) {
    $(imgs).each(function(index, value) {
        $('<img />').attr('src', value).appendTo('body').css('display', 'none');
    });
}

.attr('src',value).attr('src',this)

只是指出来:))

答案 18 :(得分:-2)

coffeescript中的5行

array = ['/img/movie1.png','/img/movie2.png','/img/movie3.png']

$(document).ready ->
  for index, image of array
    img[index] = new Image()
    img[index].src = image

答案 19 :(得分:-4)

对于那些了解一点动作的人,你可以轻松地检查flash播放器,并制作一个flash预加载器,你也可以导出到html5 / Javascript / Jquery。 要在未检测到Flash播放器的情况下使用,请使用youtube角色检查如何执行此操作的示例返回html5播放器:) 并创建自己的。 我没有详细信息,因为我还没有开始,如果我不忘记,我会稍后发布它,并会尝试使用一些标准的Jquery代码。

答案 20 :(得分:-7)

所有时髦人士都写自己的版本,所以这是我的。它为身体添加了一个隐藏的div,并用所需的图像填充它。我在Coffee Script中写了它。这是咖啡,普通的js和压缩的js。

咖啡:

$.fn.preload = () ->
    domHolder = $( '<div/>' ).hide()
    $( 'body' ).append domHolder
    this.each ( i, e) =>
        domHolder.append( $('<img/>').attr('src', e) )

正常:

(function() {

  $.fn.preload = function() {
    var domHolder,
      _this = this;
    domHolder = $('<div></div>').css('display', 'none');
    $('body').append(domHolder);
    return this.each(function(i, e) {
      return domHolder.append($('<img/>').attr('src', e));
    });
  };

}).call(this);

压缩:

function(){$.fn.preload=function(){var a,b=this;return a=$("<div></div>").css("display","none"),$("body").append(a),this.each(function(b,c){return a.append($("<img/>").attr("src",c))})}}.call(this);