javascript 预加载图像后触发事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5623639/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 17:48:14  来源:igfitidea点击:

Fire an event after preloading images

javascriptjquery

提问by Badr Hari

This is the code I use to preload images, I'm not sure if it's the best one. My question is, how can I fire and event, for an example alert(); dialog after is has finished loading all the images?

这是我用来预加载图像的代码,我不确定它是否是最好的。我的问题是,我如何触发和事件,例如 alert(); 完成加载所有图像后的对话框?

var preload = ["a.gif", "b.gif", "c.gif"];
    var images = [];
    for (i = 0; i < preload.length; i++) {
        images[i] = new Image();
        images[i].src = preload[i];
    }

回答by Pointy

You can use the new "$.Deferred" if you like:

如果您愿意,可以使用新的“$.Deferred”:

var preload = ["a.gif", "b.gif", "c.gif"];
var promises = [];
for (var i = 0; i < preload.length; i++) {
    (function(url, promise) {
        var img = new Image();
        img.onload = function() {
          promise.resolve();
        };
        img.src = url;
    })(preload[i], promises[i] = $.Deferred());
}
$.when.apply($, promises).done(function() {
  alert("All images ready sir!");
});

Might be a little risky to leave the Image objects floating around, but if so that could be fixed easily by shifting the closure. editin fact I'll change it myself because it's bugging me :-)

让 Image 对象四处漂浮可能有点冒险,但如果这样的话,可以通过移动闭包轻松解决这个问题。编辑实际上我会自己改变它,因为它困扰着我:-)

回答by justkt

Since your tags include jQuery, here's what I would do in jQuery, with heavy inspiration from this related answer:

由于您的标签包含 jQuery,以下是我将在 jQuery 中执行的操作,并从这个相关答案中获得了大量灵感:

function preloadImages(images, callback) {
    var count = images.length;
    if(count === 0) {
        callback();
    }
    var loaded = 0;
    $.each(images, function(index, image) {
        $('<img>').attr('src', image).on('load', function() { // the first argument could also be 'load error abort' if you wanted to *always* execute the callback
            loaded++;
            if (loaded === count) {
                callback();
            }
        });
    });
};

// use whatever callback you really want as the argument
preloadImages(["a.gif", "b.gif", "c.gif"], function() {
    alert("DONE");
});

This relies on the callback to jQuery's load function.

这依赖于对 jQuery 加载函数的回调。

I wouldn't use the related answer simply because I don't like mucking around with Javascript's built-in prototypes.

我不会仅仅因为我不喜欢使用 Javascript 的内置原型而使用相关答案。

回答by regilero

I've seen something used to correct behavior on Masonrynice jQuery plugin (a plugin used to make nice layout composition on pages). This plugin had problems with blocks containing images and should delay his work when the images are loaded.

我见过一些用于纠正Masonrynice jQuery 插件(一个用于在页面上制作漂亮布局组合的插件)上的行为的东西。这个插件在包含图像的块上有问题,应该在加载图像时延迟他的工作。

First solution is to delay on the onLoad event instead of document.ready. But this event can be quite long to wait for. So they use jquery.imagesloaded.jswhich can detect that all images in a div are loaded; especially this very short and nice code can handle cached images which does not fire the load event sometimes.

第一个解决方案是延迟 onLoad 事件而不是 document.ready。但是这个事件可能需要等待很长时间。所以他们使用jquery.imagesloaded.js,它可以检测到 div 中的所有图像都已加载;尤其是这个非常简短而漂亮的代码可以处理有时不会触发加载事件的缓存图像。

回答by fiatjaf

I'm searching for techniques that work for doing this all day now, and I finally found the solution to all my problems: https://github.com/htmlhero/jQuery.preload

我现在正在寻找可以一整天都在做这件事的技术,我终于找到了解决所有问题的方法:https: //github.com/htmlhero/jQuery.preload

It can even preload sequentially for you, in batches of any size (two at a time, for example), and fire a callback each time a batch completes.

它甚至可以为您按顺序预加载任何大小的批次(例如,一次两个),并在每次批次完成时触发回调。

回答by Gilad Babin

jquery preloading multiple images serially can be done with a callback.

jquery 串行预加载多个图像可以通过回调来完成。

function preload_images(images_arr, f, id){
    id = typeof id !== 'undefined' ? id : 0;
    if (id == images_arr.length)
        return;
    $('<img>').attr('src', images_arr[id]).load(function(){
        console.log(id);
        f(images_arr[id], id);
        preload_images(images_arr, f, id+1);
    });
}

For example:

例如:

preload_images(["img1.jpg", "img2.jpg"], function(img_url, i){
    // i is the index of the img in the original array
    // can make some img.src = img_url
});

回答by django

Based on answer from Ben Claytonabove.

基于上面Ben Clayton 的回答。

There can be case where images load fail all together and one must still be able to get callback.

可能存在图像加载全部失败并且仍然必须能够获得回调的情况。

Here is my revised answer. One ca easily find out hom many images loaded with success and how many ended up in error. thisin callback will have that info

这是我修改后的答案。一个人可以很容易地找出许多成功加载的图像以及最终出错的图像。this在回调中将有该信息

preloadImages(_arrOfImages, function() {
  var response = this;
  var hasError = response.errored.length + response.aborted.length;
  if (hasError > 0) {
    console.log('failed ' + hasError);
  } else {
    console.log('all loaded');
  }
});

// JSFIDDLE:https://jsfiddle.net/bababalcksheep/ds85yfww/2/

// JSFIDDLE: https://jsfiddle.net/bababalcksheep/ds85yfww/2/

var preloadImages = function(preload, callBack) {
  var promises = [];
  var response = {
    'loaded': [],
    'errored': [],
    'aborted': []
  };
  for (var i = 0; i < preload.length; i++) {
    (function(url, promise) {
      var img = new Image();
      img.onload = function() {
        response.loaded.push(this.src);
        promise.resolve();
      };
      // Use the following callback methods to debug
      // in case of an unexpected behavior.
      img.onerror = function() {
        response.errored.push(this.src);
        promise.resolve();
      };
      img.onabort = function() {
        response.aborted.push(this.src);
        promise.resolve();
      };
      //
      img.src = url;
    })(preload[i], promises[i] = $.Deferred());
  }
  $.when.apply($, promises).done(function() {
    callBack.call(response);
  });
};

回答by Roque

Today I needed to preload images and execute some code onlyafter all images are loaded, but without jQueryand using Ionic2/Typescript2. Here's my solution:

今天,我需要预先载入图像,并执行一些代码,只有所有的图像加载后,却没有jQuery的使用Ionic2 / Typescript2。这是我的解决方案:

// Pure Javascript Version
function loadImages(arrImagesSrc) {
    return new Promise(function (resolve, reject) {
        var arrImages = [];
        function _loadImage(src, arr) {
            var img = new Image();
            img.onload = function () { arr.push([src, img]); };
            img.onerror = function () { arr.push([src, null]); };

            img.src = src;
        }
        arrImagesSrc.forEach(function (src) {
            _loadImage(src, arrImages);
        });
        var interval_id = setInterval(function () {
            if (arrImages.length == arrImagesSrc.length) {
                clearInterval(interval_id);
                resolve(arrImages);
            }
        }, 100);
    });
}

// Ionic2 version
private loadImages(arrImagesSrc: Array<string>): Promise<Array<any>> {
    return new Promise((resolve, reject) => {
      ...
      function _loadImage(src: string, arr: Array<any>) {
        ...
      }
      ...
 }

You can use like this. Problematic url returns 'null'.

你可以这样使用。有问题的 url 返回“null”。

loadImages(['https://cdn2.iconfinder.com/data/icons/nodejs-1/512/nodejs-512.png', 'http://foo_url'])
.then(function(arr) {
   console.log('[???]', arr); 
})

回答by Code Maverick

Check out: http://engineeredweb.com/blog/09/12/preloading-images-jquery-and-javascript. It uses jQuery. In the comments, your direct issue is addressed by someone and a solution was posted there. I think it'll fit your needs.

查看:http: //engineeredweb.com/blog/09/12/preloading-images-jquery-and-javascript。它使用jQuery。在评论中,有人解决了您的直接问题,并在那里发布了解决方案。我认为它会满足您的需求。

回答by Miquel

As an alternative you could use a CSS technique to pre-load the images as shown here:

作为替代方案,您可以使用 CSS 技术来预加载图像,如下所示:

http://perishablepress.com/press/2008/06/14/a-way-to-preload-images-without-javascript-that-is-so-much-better/

http://perishablepress.com/press/2008/06/14/a-way-to-preload-images-without-javascript-that-is-so-much-better/

and then use the global onLoad event which is fired when everything has been loaded

然后使用全局 onLoad 事件,该事件在加载完所有内容后触发

回答by kennebec

//Here is a pre-jquery method, but jquery is bound to be simpler to write.

//这里是jquery前的方法,不过jquery肯定写起来更简单。

function loadAlbum(A, cb, err, limit){
    // A is an array of image urls;
    //cb is a callback function (optional);
    //err is an error handler (optional);
    // limit is an (optional) integer time limit in milliseconds

    if(limit) limit= new Date().getTime()+limit;
    var album= [], L= A.length, tem, url;

    while(A.length){
        tem= new Image;
        url= A.shift();
        tem.onload= function(){
            album.push(this.src);
        }
        tem.onerror= function(){
            if(typeof er== 'function') album.push(er(this.src));
            else album.push('');
        }
        tem.src= url;

        // attend to images in cache (may not fire an onload in some browsers):
        if(tem.complete && tem.width> 0){
            album.push(tem.src);
            tem.onload= '';
        }
    }
    // check the length of the loaded array of images at intervals:
    if(typeof cb== 'function'){
        window.tryAlbum= setInterval(function(){
            if(limit && limit-new Date().getTime()<0) L= album.length;
            if(L== album.length){
                clearInterval(tryAlbum);
                tryAlbum= null;
                return cb(album);
            }
        },
        100);
    }
    return album;
}