Предварительная загрузка изображений с помощью jQuery

Я ищу быстрый и простой способ предварительной загрузки изображений с помощью 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, которые делают это, но все они кажутся немного большими (по размеру); Мне просто нужен быстрый, простой и короткий способ предварительной загрузки изображений!

20 ответов

Решение

Быстро и просто:

function preload(arrayOfImages) {
    $(arrayOfImages).each(function(){
        $('<img/>')[0].src = this;
        // Alternatively you could use:
        // (new Image()).src = this;
    });
}

// Usage:

preload([
    'img/imageName.jpg',
    'img/anotherOne.jpg',
    'img/blahblahblah.jpg'
]);

Или, если вы хотите плагин jQuery:

$.fn.preload = function() {
    this.each(function(){
        $('<img/>')[0].src = this;
    });
}

// Usage:

$(['img1.jpg','img2.jpg','img3.jpg']).preload();

Вот измененная версия первого ответа, которая фактически загружает изображения в DOM и скрывает его по умолчанию.

function preload(arrayOfImages) {
    $(arrayOfImages).each(function () {
        $('<img />').attr('src',this).appendTo('body').css('display','none');
    });
}

Используйте JavaScript Image объект.

Эта функция позволяет вызвать обратный вызов при загрузке всех изображений. Однако обратите внимание, что он никогда не будет вызывать обратный вызов, если хотя бы один ресурс не загружен. Это можно легко исправить, внедрив onerror обратный вызов и увеличение loaded значение или обработка ошибки.

var preloadPictures = function(pictureUrls, callback) {
    var i,
        j,
        loaded = 0;

    for (i = 0, j = pictureUrls.length; i < j; i++) {
        (function (img, src) {
            img.onload = function () {                               
                if (++loaded == pictureUrls.length && callback) {
                    callback();
                }
            };

            // Use the following callback methods to debug
            // in case of an unexpected behavior.
            img.onerror = function () {};
            img.onabort = function () {};

            img.src = src;
        } (new Image(), pictureUrls[i]));
    }
};

preloadPictures(['http://foo/picture.bar', 'http://foo/picture.bar', 'http://foo/picture.bar', 'http://foo/picture.bar'], function(){
    console.log('a');
});

preloadPictures(['http://foo/picture.bar', 'http://foo/picture.bar', 'http://foo/picture.bar', 'http://foo/picture.bar'], function(){
    console.log('b');
});

JP, После проверки вашего решения, у меня все еще были проблемы в Firefox, когда он не загружал изображения до того, как перейти к загрузке страницы. Я обнаружил это, положив некоторые sleep(5) в моем сценарии на стороне сервера. Я реализовал следующее решение на основе вашего, которое, кажется, решает эту проблему.

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

// Helper function, used below.
// Usage: ['img1.jpg','img2.jpg'].remove('img1.jpg');
Array.prototype.remove = function(element) {
  for (var i = 0; i < this.length; i++) {
    if (this[i] == element) { this.splice(i,1); }
  }
};

// Usage: $(['img1.jpg','img2.jpg']).preloadImages(function(){ ... });
// Callback function gets called after all images are preloaded
$.fn.preloadImages = function(callback) {
  checklist = this.toArray();
  this.each(function() {
    $('<img>').attr({ src: this }).load(function() {
      checklist.remove($(this).attr('src'));
      if (checklist.length == 0) { callback(); }
    });
  });
};

Из интереса, в моем контексте, я использую это следующим образом:

$.post('/submit_stuff', { id: 123 }, function(response) {
  $([response.imgsrc1, response.imgsrc2]).preloadImages(function(){
    // Update page with response data
  });
});

Надеюсь, это поможет тому, кто заходит на эту страницу из Google (как и я), в поисках решения для предварительной загрузки изображений при вызовах Ajax.

Этот однострочный код jQuery создает (и загружает) элемент DOM img, не показывая его:

$('<img src="img/1.jpg"/>');
$.fn.preload = function (callback) {
  var length = this.length;
  var iterator = 0;

  return this.each(function () {
    var self = this;
    var tmp = new Image();

    if (callback) tmp.onload = function () {
      callback.call(self, 100 * ++iterator / length, iterator === length);
    };

    tmp.src = this.src;
  });
};

Использование довольно просто:

$('img').preload(function(perc, done) {
  console.log(this, perc, done);
});

http://jsfiddle.net/yckart/ACbTK/

У меня есть небольшой плагин, который обрабатывает это.

Это называется waitForImages и может обрабатывать img элементы или любой элемент со ссылкой на изображение в CSS, например div { background: url(img.png) },

Если вы просто хотите загрузить все изображения, включая те, на которые есть ссылки в CSS, вот как вы это сделаете:)

$('body').waitForImages({
    waitForAll: true,
    finished: function() {
       // All images have loaded.
    }  
});

Вы можете загрузить изображения в ваш HTML где-нибудь с помощью CSS display:none; правило, а затем показать их, когда вы хотите с JS или JQuery

не используйте функции js или jquery для предварительной загрузки - это просто правило css против множества строк j, которые нужно выполнить

пример: HTML

<img src="someimg.png" class="hide" alt=""/>

Css:

.hide{
display:none;
}

JQuery:

//if want to show img 
$('.hide').show();
//if want to hide
$('.hide').hide();

Предварительная загрузка изображений с помощью jquery/javascript не годится, поскольку загрузка изображений на странице занимает несколько миллисекунд + у вас есть миллисекунды для синтаксического анализа и выполнения сценария, особенно если это большие изображения, поэтому скрытие их в hml лучше также для производительности, потому что изображение действительно предварительно загружено, не будучи видимым, пока вы не покажете это!

Этот плагин JQuery ImageLoader просто 1,39 КБ

использование:

$({}).imageLoader({
    images: [src1,src2,src3...],
    allcomplete:function(e,ui){
        //images are ready here
        //your code - site.fadeIn() or something like that
    }
});

Существуют также другие варианты, например, хотите ли вы загружать изображения синхронно или асинхронно, а также полное событие для каждого отдельного изображения.

Быстрый, без плагинов способ предварительно загрузить изображения в jQuery и получить функцию обратного вызова - создать несколько img пометить сразу и посчитать ответы, например

function preload(files, cb) {
    var len = files.length;
    $(files.map(function(f) {
        return '<img src="'+f+'" />';
    }).join('')).load(function () {
        if(--len===0) {
            cb();
        }
    });
}

preload(["one.jpg", "two.png", "three.png"], function() {
    /* Code here is called once all files are loaded. */
});
​    ​

Обратите внимание, что если вы хотите поддерживать IE7, вам нужно использовать эту немного менее симпатичную версию (которая также работает в других браузерах):

function preload(files, cb) {
    var len = files.length;
    $($.map(files, function(f) {
        return '<img src="'+f+'" />';
    }).join('')).load(function () {
        if(--len===0) {
            cb();
        }
    });
}

Спасибо за это! Я хотел бы добавить небольшой рифф к ответу JP - я не знаю, поможет ли это кому-нибудь, но таким образом вам не нужно создавать массив изображений, и вы можете предварительно загрузить все свои большие изображения, если вы правильно назовите свои большие пальцы. Это удобно, потому что у меня есть кто-то, кто пишет все страницы в 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, а затем предварительно загружает все большие изображения.

Надеюсь, это кому-нибудь поможет.

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

Я использую следующий код:

$("#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";

Я бы использовал файл Manifest, чтобы сообщить (современным) веб-браузерам, чтобы они также загружали все соответствующие изображения и кэшировали их. Используйте Grunt и grunt-manifest, чтобы сделать это автоматически, и больше никогда не беспокоиться о сценариях предварительной загрузки, обнулителях кэша, CDN и т. Д.

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

Обычно я использую этот фрагмент кода в своих проектах для загрузки изображений на странице. Вы можете увидеть результат здесь 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>

Скрипт сохраняет в массиве все src а также background-image страницы и загрузите их все.

Вы можете увидеть / прочитать / показать прогресс загрузки с помощью var 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);

});

Я хотел сделать это с помощью пользовательского оверлея Google Maps API. Их пример кода просто использует JS для вставки элементов IMG, и поле заполнителя изображения отображается до тех пор, пока изображение не будет загружено. Я нашел ответ, который работал для меня: /questions/25723679/zagruzite-izobrazhenie-s-pomoschyu-jquery-i-dobavte-ego-v-dom/25723692#25723692.

$('<img src="'+ imgPaht +'">').load(function() {
$(this).width(some).height(some).appendTo('#some_target');
});

Это предварительно загружает изображение, как предлагалось ранее, а затем использует обработчик для добавления объекта img после загрузки URL-адреса img. Документация jQuery предупреждает, что кэшированные изображения плохо работают с этим кодом события / обработчика, но он работает для меня в FireFox и Chrome, и мне не нужно беспокоиться об IE.

Это работает для меня даже в IE9:

$('<img src="' + imgURL + '"/>').on('load', function(){ doOnLoadStuff(); });
function preload(imgs) {
    $(imgs).each(function(index, value) {
        $('<img />').attr('src', value).appendTo('body').css('display', 'none');
    });
}

.attr('src',value)не.attr('src',this)

просто чтобы указать на это:)

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

Для тех, кто немного знает ActionScript, вы можете с минимальными усилиями проверить наличие flash player и сделать предварительный загрузчик flash, который вы также можете экспортировать в html5/Javascript/Jquery. Чтобы использовать, если flash player не обнаружен, посмотрите примеры того, как сделать это с ролью youtube обратно в html5 player:) И создайте свой собственный. У меня нет подробностей, потому что я еще не начал, если я не забыл, я опубликую его позже и попробую какой-то странный код Jquery для меня.

Все хипстеры написали там свою версию, так что вот моя. Он добавляет скрытый элемент div к телу и заполняет его необходимыми изображениями. Я написал это в Coffee Script. Вот Кофе, нормальный js и сжатый js.

Кофе:

$.fn.preload = () ->
    domHolder = $( '<div/>' ).hide()
    $( 'body' ).append domHolder
    this.each ( i, e) =>
        domHolder.append( $('<img/>').attr('src', e) )

Нормальный:

(function() {

  $.fn.preload = function() {
    var domHolder,
      _this = this;
    domHolder = $('<div></div>').css('display', 'none');
    $('body').append(domHolder);
    return this.each(function(i, e) {
      return domHolder.append($('<img/>').attr('src', e));
    });
  };

}).call(this);

Сжатый:

function(){$.fn.preload=function(){var a,b=this;return a=$("<div></div>").css("display","none"),$("body").append(a),this.each(function(b,c){return a.append($("<img/>").attr("src",c))})}}.call(this);
Другие вопросы по тегам