Лучший способ предварительно загрузить изображения с помощью JavaScript / jQuery? - PullRequest
50 голосов
/ 23 мая 2009

Я полностью осознаю, что на этот вопрос задавали и отвечали везде, как на SO, так и выключено. Однако каждый раз, когда кажется, что есть разные ответы, например, это , это и то .

Мне все равно, использует ли он jQuery или нет - важно то, что он работает и работает в разных браузерах.]

Итак, каков наилучший способ предварительной загрузки изображений?

Ответы [ 8 ]

65 голосов
/ 23 мая 2009

К сожалению, это зависит от вашей цели. Если вы планируете использовать изображения в целях стиля, лучше всего использовать спрайты. http://www.alistapart.com/articles/sprites2

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

function preload(sources)
{
  var images = [];
  for (i = 0, length = sources.length; i < length; ++i) {
    images[i] = new Image();
    images[i].src = sources[i];
  }
}

(измененный источник взят из Каков наилучший способ предварительной загрузки нескольких изображений в JavaScript? )

Использование new Image() не требует затрат на использование методов DOM, но новый запрос на указанное изображение будет добавлен в очередь. Поскольку изображение на данный момент фактически не добавляется на страницу, повторного рендеринга не происходит. Однако я бы порекомендовал добавить это в конец вашей страницы (как и все ваши сценарии, когда это возможно), чтобы предотвратить удержание более важных элементов.

Редактировать: отредактировано, чтобы правильно отразить комментарий, указывая, что отдельные Image объекты необходимы для правильной работы. Спасибо, и мой плохой за то, что не проверил это более внимательно.

Edit2: отредактировано, чтобы сделать повторное использование более очевидным

Изменить 3 (3 года спустя):

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

Вы можете использовать Ajax-запрос для принудительного раннего извлечения изображений. Используя jQuery, например:

jQuery.get(source);

Или в контексте нашего предыдущего примера вы можете сделать:

function preload(sources)
{
  jQuery.each(sources, function(i,source) { jQuery.get(source); });
}

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

Также обратите внимание, что этот метод не работает для IE (ajax обычно не используется для получения данных изображения).

14 голосов
/ 24 мая 2009

спрайтов

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

  • С другой стороны, вы делаете только один HTTP-запрос для ваших изображений. YMMV хотя.
  • С другой стороны, вы загружаете все в одном HTTP-запросе. Поскольку большинство современных браузеров ограничены двумя одновременными подключениями, запрос изображения может блокировать другие запросы. Следовательно, YMMV и что-то похожее на фон меню могут немного не отображаться.
  • Несколько изображений имеют одну и ту же цветовую палитру, поэтому есть некоторая экономия, но это не всегда так, и даже если это незначительно.
  • Сжатие улучшено, поскольку между изображениями больше общих данных.

Работать с неправильными формами сложно. Объединение всех новых изображений в новое - еще одно раздражение.

Подход с низким гнездом с использованием imageметок

Если вы ищете наиболее определенное решение, тогда вам следует придерживаться подхода с низким валетом, который я все еще предпочитаю. Создайте imageссылки на изображения в конце документа, установите для width и height значение 1x1 пикселя и дополнительно поместите их в скрытый элемент div. Если они находятся в конце страницы, они будут загружены после другого содержимого.

6 голосов
/ 26 января 2013

По состоянию на январь 2013 года ни один из методов, описанных здесь, не работал для меня, так что вот что вместо этого, протестировал и работал с Chrome 25 и Firefox 18. Использует jQuery и этот плагин для обхода события загрузки причуды:

function preload(sources, callback) {
    if(sources.length) {
        var preloaderDiv = $('<div style="display: none;"></div>').prependTo(document.body);

        $.each(sources, function(i,source) {
            $("<img/>").attr("src", source).appendTo(preloaderDiv);

            if(i == (sources.length-1)) {
                $(preloaderDiv).imagesLoaded(function() {
                    $(this).remove();
                    if(callback) callback();
                });
            }
        });
    } else {
        if(callback) callback();
    }
}

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

preload(['/img/a.png', '/img/b.png', '/img/c.png'], function() { 
    console.log("done"); 
});

Обратите внимание, что вы получите смешанные результаты, если кеш отключен, что по умолчанию в Chrome, когда инструменты разработчика открыты, так что имейте это в виду.

3 голосов
/ 30 апреля 2011

По моему мнению, использование Multipart XMLHttpRequest, представленное некоторыми библиотеками, будет предпочтительным решением в последующие годы. Однако IE http://code.google.com/p/core-framework/wiki/ImagePreloading, она встроена в каркас, но все же стоит взглянуть.

1 голос
/ 12 апреля 2015

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

Мое решение было еще проще.

Я только что использовал CSS.

#hidden_preload {
    height: 1px;
    left: -20000px;
    position: absolute;
    top: -20000px;
    width: 1px;
}
0 голосов
/ 23 сентября 2014

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

Для этого я использовал метод waterfall() асинхронной библиотеки (https://github.com/caolan/async#waterfall)

        // Preload all images in the carousel in order.
        image_preload_array = [];
        $('div.carousel-image').each(function(){
            var url = $(this).data('image-url');
            image_preload_array.push(function(callback) {
                var $img = $('<img/>')
                $img.load(function() {
                    callback(null);
                })[0].src = url;
            });
        });
        async.waterfall(image_preload_array);

Это работает путем создания массива функций, каждой функции передается параметр callback(), который необходимо выполнить для вызова следующей функции в массиве. Первый параметр callback() - это сообщение об ошибке, которое завершит последовательность, если указано ненулевое значение, поэтому мы передаем null каждый раз.

0 голосов
/ 29 января 2013

Вот мое простое решение с появлением изображения после его загрузки.

    function preloadImage(_imgUrl, _container){
        var image = new Image();
            image.src = _imgUrl;
            image.onload = function(){
                $(_container).fadeTo(500, 1);
            };
        }
0 голосов
/ 23 мая 2009
...