Javascript preloader изображений, который поддерживает события
Я пытаюсь найти сценарий preloader изображений.
Хотя я нашел несколько, ни один из них не поддерживает событие, которое запускается, когда предварительная загрузка заканчивается.
Кто-нибудь знает какой-либо скрипт или плагин jQuery, который будет делать это?
Надеюсь, что этот вопрос подходит для stackru - если нет, не стесняйтесь удалить его в одно мгновение.
4 ответа
Вот функция, которая будет предварительно загружать изображения из массива и вызывать ваш обратный вызов после завершения последнего:
function preloadImages(srcs, imgs, callback) {
var img;
var remaining = srcs.length;
for (var i = 0; i < srcs.length; i++) {
img = new Image();
img.onload = function() {
--remaining;
if (remaining <= 0) {
callback();
}
};
img.src = srcs[i];
imgs.push(img);
}
}
// then to call it, you would use this
var imageSrcs = ["src1", "src2", "src3", "src4"];
var images = [];
preloadImages(imageSrcs, images, myFunction);
И так как мы сейчас находимся в эпоху использования посылок для асинхронных операций, вот версия выше, которая использует посылы и уведомляет вызывающую сторону через стандартное обещание ES6:
function preloadImages(srcs) {
function loadImage(src) {
return new Promise(function(resolve, reject) {
var img = new Image();
img.onload = function() {
resolve(img);
};
img.onerror = img.onabort = function() {
reject(src);
};
img.src = src;
});
}
var promises = [];
for (var i = 0; i < srcs.length; i++) {
promises.push(loadImage(srcs[i]));
}
return Promise.all(promises);
}
preloadImages(["src1", "src2", "src3", "src4"]).then(function(imgs) {
// all images are loaded now and in the array imgs
}, function(errImg) {
// at least one image failed to load
});
А вот версия с обещаниями jQuery 2015 года:
function preloadImages(srcs) {
function loadImage(src) {
return new $.Deferred(function(def) {
var img = new Image();
img.onload = function() {
def.resolve(img);
};
img.onerror = img.onabort = function() {
def.reject(src);
};
img.src = src;
}).promise();
}
var promises = [];
for (var i = 0; i < srcs.length; i++) {
promises.push(loadImage(srcs[i]));
}
return $.when.apply($, promises).then(function() {
// return results as a simple array rather than as separate arguments
return Array.prototype.slice.call(arguments);
});
}
preloadImages(["src1", "src2", "src3", "src4"]).then(function(imgs) {
// all images are loaded now and in the array imgs
}, function(errImg) {
// at least one image failed to load
});
Для более надежного решения, рассмотрите это PRELOADER
Функция с парой обратных вызовов ( jsFiddle).
Сохраняя это простым:
В этом примере я передаю обратные вызовы и хэш изображения внутри Object
буквальный PRELOADER_OBJECT
, а затем переопределить обратные вызовы внутри PRELOADER
:
// preloder object stores image hash
// and event handler callbacks
var PRELOADER_OBJECT = {
imgArray:"http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg http://torwars.com/wp-content/uploads/2012/02/chewbacca-w-han-solo-anh.jpg".split(" "),
progressCallback : function( percent )
{
$( '#preloader_progress' ).html( 'preload progress complete : ' + percent + '%' );
console.log( 'preload progress complete : ', percent );
},
completeCallback : function( scope )
{
// hide preload indicator, do something when finished
console.log( 'preload complete!' );
$( '#preloader_modal' ).delay( 1000 ).animate( { opacity : 0 }, function( )
{
$( '.preload_class' ).each( function( index )
{
$( this ).delay( index * 100 ).animate( { opacity : 0 } );
} );
} );
}
/*Localize params and create PRELOADER object.
Needs to loadImages( ); iterate through hash and
call onPreloadProgress( ) and onPreloadComplete( )
each time until finished. If you're still within
bounds of the image hash, call progressCallback( )
recursively. When finished, fire onCompleteCallback( )*/
var PRELOADER = function( object )
{
// preloader modal overlay
this.modal = undefined;
// progress indicator container
this.progressIndicator = undefined;
// image preload progress
this.progress = undefined;
// progress callback
this.progressCallback = undefined;
// complete callback
this.completeCallback = undefined;
// hash to store key : value pairs for image paths
this.imgArray = undefined;
// store images in preloadArray
this.preloadArray = [];
// initialize and localize our data
this.initialize = function( )
{
// create preload indicator and overlay modal
this.createPreloaderModal( );
// image hash
this.imgArray = object.imgArray;
// progress callback event handler
this.progressCallback = object.progressCallback;
// complete callback event
this.completeCallback = object.completeCallback;
// load images
this.loadImages( );
};
this.progressCallback = function( ) {}; // function to override
this.completeCallback = function( ) {}; // function to override
// load images into DOM and fire callbacks
this.loadImages = function( )
{
var that = this;
// iterate through hash and place images into DOM
$.each( PRELOADER_OBJECT.imgArray, function( index, object )
{
this.image = $( "<img/>", { "src" : object, "class": "preload_class" } ).appendTo( 'body' );
// mark progress and call progressCallback( ) event handler
that.progress = Math.ceil( ( index / PRELOADER_OBJECT.imgArray.length ) * 100 );
that.progressCallback( this.progress );
that.preloadArray.push( this.image );
} );
// check for array bounds and call completeCallback( )
if ( PRELOADER_OBJECT.imgArray.length )
{
this.progressCallback( 100 );
this.completeCallback( this );
}
};
// create modal to display preload data
this.createPreloaderModal = function( )
{
this.modal = $( '<div/>', { 'id' : 'preloader_modal' } ).appendTo( 'body' );
this.progressIndicator = $( '<h1/>', { 'id' : 'preloader_progress' } ).appendTo( this.modal );
};
};
// trigger event chain when DOM loads
$( document ).ready( function( )
{
// instantiate PRELOADER instance and pass
// our JSON data model as a parameter
var preloader = new PRELOADER( PRELOADER_OBJECT );
// initialize preloader
preloader.initialize( );
} );
};
При достаточно большой загрузке сайта, для которой требуется предварительный загрузчик изображений, модальный текстовый дисплей может быть легко изменен для поддержки управляемой данными анимации jQuery.
Предварительная загрузка и загрузка - это одно и то же. Вы можете вставить изображение (либо создать новое, либо изменить атрибут "src" существующего), но скрыть элемент, используя $("element").hide()
или что-то подобное. Прежде чем сделать это, прикрепите обработчик события загрузки следующим образом:
var images = ["src1", "src2", "src3", "src4"];
var len = images.length;
for(i=0; i<len; i++){
$("parent element").html('<img id="new-img" style="display:none;" src="'+images[i]+'"/>');
$("new-img").load(function(){
//Your image is now "preloaded"
//Now you can show the image, or do other stuff
$(this).show();
});
}
Предварительная загрузка требует дополнительной работы, например, создания новых элементов изображения, отслеживания их загрузки и замены их на существующие в DOM. Однако вы можете сделать это прямо на DOM <img>
элементы бесконечно много раз без их замены.
Мы можем использовать API Fetch для доступа к изображениям, подождать, пока они все не загрузятся в течение promise.all()
а затем за один раз просто заменить src
атрибуты img
элементы в наиболее подходящее время с помощью window.requestAnimationFrame()
,
В следующем примере я обновляю src
атрибуты img
элементов 10 раз. Что касается задержки, я использую время, необходимое для загрузки 4 изображений из API. Таким образом, как только мы загрузили все изображения, я немедленно размещаю новый запрос, вызывая тот же refreshImagesNTimes
функционировать рекурсивно.
Конечно, вы можете загрузить сразу столько изображений, сколько вам нужно, и отображать их в группах с точными интервалами времени, используя простые setTimeout
механизм.
function refreshImagesNTimes(nodeList,count = -1){
var imgPromises = Array.from({length: nodeList.length})
.map(_ => fetch("https://unsplash.it/480/640/?random").then(res => res.blob()));
Promise.all(imgPromises)
.then(function(blobs){
window.requestAnimationFrame(_ => nodeList.forEach((img, i) => img.src = (window.URL || window.webkitURL).createObjectURL(blobs[i])));
--count && refreshImagesNTimes(nodeList, count);
});
}
var images = document.querySelectorAll("#container img");
refreshImagesNTimes(images,10);
#container {
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
align-items: center;
margin: auto;
width: 75vw;
height: 56.25vw;
background-color: #000;
box-sizing: border-box;
}
img {
width: 45%;
height: 45%;
background-color: thistle;
}
<div id="container">
<img>
<img>
<img>
<img>
</div>