Javascript preloader изображений, который поддерживает события - PullRequest
7 голосов
/ 25 ноября 2011

Я пытаюсь найти скрипт предварительного загрузки изображения.

Хотя я нашел несколько из них, ни один из них не поддерживает событие, которое запускается по окончании предварительной загрузки.

Кто-нибудь знает какой-нибудь скрипт или плагин jQuery, который будет это делать?

Надеюсь, этот вопрос подходит для stackoverflow - если нет, не стесняйтесь удалить его в одно мгновение.

Ответы [ 4 ]

31 голосов
/ 25 ноября 2011

Вот функция, которая будет предварительно загружать изображения из массива и вызывать ваш обратный вызов после завершения последнего:

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
});
2 голосов
/ 15 октября 2012

Для более надежного решения рассмотрим эту 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.

0 голосов
/ 10 сентября 2017

Предварительная загрузка требует дополнительной работы, такой как создание новых элементов изображения, отслеживание загрузки всех элементов и их замена на существующие в DOM. Однако вы можете делать это непосредственно с элементами DOM <img> неограниченное количество раз, не заменяя их.

Мы можем использовать Fetch API для доступа к изображениям, подождать, пока все они будут загружены в 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>
0 голосов
/ 25 ноября 2011

Предварительная загрузка и загрузка - это одно и то же.Вы можете вставить изображение (либо создать новое, либо изменить атрибут «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();
    });
}
...