使用jQuery预加载图片

699

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


11
$.each(arguments,function(){(new Image).src=this}); 意思是遍历arguments中的每个元素,对于每个元素都创建一个Image对象,并将该元素作为Image对象的src属性值。 - David Hellsing
20个回答

7

谢谢这个!我想在J-P的答案上加一点小音符 - 我不知道这是否会帮助任何人,但是如果您正确命名缩略图,则无需创建图像数组,即可预加载所有大型图像。这非常方便,因为我有一个人在用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。缩略图到大型图像只需将_th.jpg替换为_lg.jpg,然后预加载所有大型图像。
希望这能帮助某些人。

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*/
        }
    )

7
欢迎来到 Stack Overflow!请不要仅仅贴上一大段代码,还需要解释这段代码是如何解决问题的。如果没有解释,那这并不算是一个答案。 - Martijn Pieters

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

先绑定到加载事件,然后设置src。 - Kevin B

1

我会使用一个 Manifest 文件,告诉(现代)web浏览器也要加载所有相关的图像并将它们缓存起来。使用 Grunt 和 grunt-manifest 自动完成这个过程,永远不必担心预加载脚本、缓存失效、CDN等问题。

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


0

这对我来说甚至在IE9中也有效:

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

1
由于缓存的原因,这将最终失败,请在设置src属性之前始终绑定load事件。 - Kevin B

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

});

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

.attr('src',value) 而不是 .attr('src',this)

只是想指出一下 :)


传递给$.each的回调函数内部的this作用域被分配为正在迭代的值。 - Oybek
? $(['img1.jpg','img2.jpg','img3.jpg']).each(function (index,value) { console.log(value);//img1.jpg console.log(this);//String { 0="i", 1="m", 2="g", more...} $('<img />').attr('src',this).appendTo('body').css('display','none'); }); - Whisher
嗯,我想你在这里是正确的。例如 $("div").each(function(i, el){ console.log(el == this);}); 会生成所有的 true;但是对数组进行迭代似乎表现不同。 - Oybek

0
我想使用 Google Maps API 自定义覆盖来实现这个。他们的示例代码只是使用 JS 插入 IMG 元素,并显示图像占位框,直到图像加载完为止。我在这里找到了一个对我有用的答案:https://dev59.com/2Wgv5IYBdhLWcg3wFsyl#10863680
$('<img src="'+ imgPaht +'">').load(function() {
$(this).width(some).height(some).appendTo('#some_target');
});

如前所述,这将预加载图像,然后使用处理程序在加载img URL后附加img对象。jQuery的文档警告说,缓存的图像与此事件/处理程序代码不兼容,但在FireFox和Chrome中它对我有效,并且我不必担心IE。


这个方法在缓存图片上表现不佳,如你所发现的那样。解决方法是先绑定加载事件,然后再设置src属性。 - Kevin B

-2

5行CoffeeScript代码

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

2
你能详细说明一下解决问题的方案是如何实现的吗?并且可能添加注释,以便其他人更容易理解代码吗? - Ro Yo Mi

-4

对于那些了解一点ActionScript的人,您可以轻松检查Flash播放器并制作Flash预加载器,还可以将其导出到HTML5 / JavaScript / JQuery。 如果未检测到Flash播放器,请查看如何使用YouTube回滚到HTML5播放器的示例,并创建自己的预加载器。 我目前没有详细信息,因为我还没有开始,如果我没有忘记,我会稍后发布并尝试一些标准JQuery代码。


这不是一个解决方案。浏览器默认不支持Flash播放器。但可以轻松使用JavaScript实现,因为它是浏览器的本地语言。 - Usman Ahmed
我记得2012年那些对Flash充满仇恨的人... 那是不正常的... 无论我走到哪里,只要一提到Flash这个词我就会受到攻击。 - Peter Gruppelaar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接