Пожар события после предварительной загрузки изображений
Это код, который я использую для предварительной загрузки изображений, я не уверен, что он лучший.
Мой вопрос в том, как я могу запустить огонь и событие, например, 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];
}
Ответы
Ответ 1
Вы можете использовать новый "$.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!");
});
Возможно, будет немного рискованно оставлять объекты Image, плавающие вокруг, но если это можно легко устранить, сдвинув замыкание. на самом деле я сам его поменю, потому что это меня забивает: -)
Ответ 2
Поскольку ваши теги включают jQuery, вот что я сделал бы в jQuery, с тяжелым вдохновением этого связанного ответа:
function preloadImages(images, callback) {
var count = images.length;
if(count === 0) {
callback();
}
var loaded = 0;
$(images).each(function() {
$('<img>').attr('src', this).load(function() {
loaded++;
if (loaded === count) {
callback();
}
});
});
};
// use whatever callback you really want as the argument
preloadImages(["a.gif", "b.gif", "c.gif"], function() {
alert("DONE");
});
Это зависит от обратного вызова функции загрузки jQuery.
Я бы не использовал связанный ответ просто потому, что мне не нравилось сбрасывать с помощью встроенных прототипов Javascript.
Ответ 3
Я видел что-то, что использовалось для исправления поведения Masonry приятный плагин jQuery (плагин, используемый для создания красивой компоновки на страницах), Этот плагин имел проблемы с блоками, содержащими изображения, и должен задерживать его работу при загрузке изображений.
Первое решение - задержать событие onLoad вместо document.ready. Но это событие может быть довольно долго ждать. Поэтому они используют jquery.imagesloaded.js, который может обнаружить, что загружаются все изображения в div; особенно этот очень короткий и красивый код может обрабатывать кешированные изображения, которые иногда не запускают событие загрузки.
Ответ 4
Отъезд: http://engineeredweb.com/blog/09/12/preloading-images-jquery-and-javascript. Он использует jQuery. В комментариях ваша прямая проблема адресуется кем-то, и там было отправлено решение. Я думаю, это будет соответствовать вашим потребностям.
Ответ 5
В качестве альтернативы вы можете использовать технику CSS для предварительной загрузки изображений, как показано здесь:
http://perishablepress.com/press/2008/06/14/a-way-to-preload-images-without-javascript-that-is-so-much-better/
а затем используйте глобальное событие onLoad, которое запускается, когда все загружено
Ответ 6
//Вот метод pre-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;
}
Ответ 7
Я ищу методы, которые работают для этого в течение всего дня, и наконец нашел решение всех моих проблем: https://github.com/htmlhero/jQuery.preload
Он может даже предварительно загружаться последовательно для вас в партиях любого размера (по два за раз, например) и запускать обратный вызов каждый раз, когда пакет завершается.
Ответ 8
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);
});
}
Например:
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
});
Ответ 9
Основываясь на ответе Ben Clayton выше.
Может быть случай, когда загрузка изображений заканчивается неудачно, и все еще можно получить обратный вызов.
Вот мой пересмотренный ответ.
Один из них легко обнаруживает, что многие изображения загружены с успехом, и сколько оказалось в ошибке. 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/
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);
});
};
Ответ 10
Сегодня мне нужно было предварительно загрузить изображения и выполнить код только после загрузки всех изображений, но без jQuery и с помощью Ionic2/Typcript2. Здесь мое решение:
// 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>) {
...
}
...
}
Вы можете использовать это. Проблематичный url возвращает "null".
loadImages(['https://cdn2.iconfinder.com/data/icons/nodejs-1/512/nodejs-512.png', 'http://foo_url'])
.then(function(arr) {
console.log('[???]', arr);
})