Управление загрузкой изображений

Автор оригинала: Patrick Kunka
  • Перевод
  • Tutorial


Быстрая и плавная загрузка изображений — это одна из немаловажных составляющих хорошего веб-интерфейса. Кроме того, появляется все больше сайтов, использующие крупные фотографии в дизайне, таким проектам особенно важно следить за корректной загрузкой графики. В этой статье описано несколько техник, которые помогут контролировать загрузку изображений.

Использование контейнера для каждого изображения


Простой способ, который можно применить к любому изображению на сайте. Заключается в том, что каждая картинка оборачивается в DIV, который предотвращает построчную загрузку:

<div class="img_wrapper">
    <img src="comicbookguy.jpg" alt=""/>
</div>

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

Например, чтобы задать соотношение сторон 4:3, можно использовать следующий CSS:

.img_wrapper{
    position: relative;
    padding-top: 75%;
    overflow: hidden;
}
 
.img_wrapper img{
    position: absolute;
    top: 0;
    width: 100%;
    opacity: 0;
}

Для того, чтобы изображение отображалось в браузере только после полной подгрузки, необходимо добавить событие onload для изображения и использовать JavaScript, который будет обрабатывать событие:

<div>
    <img src="comicbookguy.jpg" alt="" onload="imgLoaded(this)"/>
</div>

function imgLoaded(img){
    var $img = $(img);
 
    $img.parent().addClass('loaded');
};

Код функции внутри тега HEAD должен быть расположен в самом конце, после любого jQuery или другого плагина. После полной подгрузки изображения его необходимо показать на странице:

.img_wrapper.loaded img{
    opacity: 1;
}

Для эффекта плавного появления картинки можно использовать CSS3 transition:

.img_wrapper img{
    position: absolute;
    top: 0;
    width: 100%;
    opacity: 0;
 
    -webkit-transition: opacity 150ms;
    -moz-transition: opacity 150ms;
    -ms-transition: opacity 150ms;
    transition: opacity 150ms;
}

Живой пример этого способа можно посмотреть на Codepen.

Использование контейнера для множества изображений


Предыдущий способ хорошо подходит для отдельных изображений, а что если на странице их много, например галерея фотографий или слайдер? Подгружать сразу все нецелесообразно — картинки могут много весить. Для решения этой проблемы можно заставить JavaScript'ом загружать только нужные в данный момент времени изображения. Пример HTML-разметки для слайдшоу:

<div id="Slideshow">
    <img src="slide_1.jpg" alt="" onload="slideLoaded(this)" />
    <img src="slide_2.jpg" alt="" onload="slideLoaded(this)" />
    <img src="slide_3.jpg" alt="" onload="slideLoaded(this)" />
</div>

Используем функцию slideLoaded(), чтобы контролировать процесс:

function slideLoaded(img){
    var $img = $(img),
        $slideWrapper = $img.parent(),
        total = $slideWrapper.find('img').length,
        percentLoaded = null;
 
    $img.addClass('loaded');
 
    var loaded = $slideWrapper.find('.loaded').length;
 
    if(loaded == total){
        percentLoaded = 100;
        // INSTANTIATE PLUGIN
        $slideWrapper.easyFader();
    } else {
        // TRACK PROGRESS
        percentLoaded = loaded/total * 100;
    };
};

Подгруженным изображениям присваивается класс loaded, а также отображается общий прогресс. И снова, JavaScript должен быть помещен в конец тега HEAD, после всего остального.

Кэширование


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

<script>
    var heroArray = [
        '/uploads/hero_about.jpg',
        '/uploads/hero_history.jpg',
        '/uploads/hero_contact.jpg',
        '/uploads/hero_services.jpg'
    ]
</script>

Когда посетитель заходит на сайт, после загрузки главной страницы, начинают загружаться изображения в кэш. Для того, чтобы кэширование не мешало отображению текущего контента, необходимо функционал JavaScript добавить в событие window load:

function preCacheHeros(){
    $.each(heroArray, function(){
        var img = new Image();
        img.src = this;
    });
};
 
$(window).load(function(){
    preCacheHeros();
});

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

Загрузка по событию


способ заключается в том, что изображения начинают подгружаться после определенного события. Это увеличивает производительность и экономит трафик пользователя. HTML-разметка:

<div class="img_wrapper lazy_load">
    <img
        src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
        data-src="comicbookguy.jpg"
        alt="Comic Book Guy"
    />
</div>

Стоит заметить, что URL изображение задано в data-src, а не в src. Это необходимо, чтобы браузер не загружал картинку сразу. Вместо этого в src загружается прозрачный пиксель в GIF, заданный в base64, что уменьшает количество обращений к серверу.

Остается только при нужном событии изменить значение src на data-src. JavaScript позволяет загружать изображения постепенно:

function lazyLoad(){
    var $images = $('.lazy_load');
 
    $images.each(function(){
        var $img = $(this),
            src = $img.attr('data-src');
 
        $img
            .on('load',imgLoaded($img[0]))
            .attr('src',src);
    });
};
 
$(window).load(function(){
    lazyLoad();
};

Заключение


Нет одного оптимального способа для того, чтобы управлять загрузкой изображений на сайте. В каждом конкретном случае необходимо выбирать подходящий метод, а также комбинировать несколько, если это целесообразно. Одними из главных моментов, на которые необходимо обратить внимание — это производительность и трафик. Проще говоря, в первую очередь стоит подумать о том, как будет удобнее пользователю сайта.
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 31

    +2
    FYI: Соoбытие onload не совсем корректно работает. Оно может вообще не проявиться, если файл битый. Как вариант — вот такой велосипед:

    var request = $.ajax({ url: snapshot, cache: true, processData: false }).always(hadler { target..attr('src') = snapshot });

    Ну, или типа того…
      +3
      К слову, если IE достаёт картинку из кэша, onload не срабатывает.
      +1
      github.com/desandro/imagesloaded

      для проверки загрузились ли изображения на странице / в контейнере.
        +13
        С помощью контейнера можно контролировать соотношение сторон картинки, а также использовать индикатор загрузки, что очень удобно, если изображения тяжелые.

        На самом деле спрятанное недогруженное изображение — это очень неудобно. Может быть уже по 40% изображения понятно, что дожидаться полной загрузки не стоит. А если изображение не прятать, то оно уже само является индикатором своей загрузки, и еще один индикатор не требуется.
          +1
          опять же, по недогруженному изображению (в случае проблем со связью) можно кликнуть правой кнопкой и запустить принудительную перезагрузку.
          0
          А кто может объяснить, почему некоторые картинки грузятся сверху вниз, некоторые снизу вверх, а некоторые черезстрочно? Притом это все бывает в одном браузере
            +1
            Для случая снизу вверх очень может оказаться, что это bmp, для черезстрочных – это изображение так сохранено было (это умеют и gif, и png, и jpg).
              +2
              Потому что это зависит от самой картинки.

              Так, формат bmp поддерживает режимы как снизу-вверх, так и сверху-вниз (зависит от знака высоты), при этом режим снизу-вверх считается предпочтительным в силу исторических причин.
                0
                Это от схемы сжатия картинки зависит wiki
                  0
                  А еще оно может грузиться слева направо, или наоборот, но тут уже обычный sequential JPEG + тег ориентации из EXIF.
                  0
                  А почему нет упоминания <link rel="prefetch" href="/url-there" />?
                    +1
                    Дык ить не во всех браузерах оно работает, кажись.
                    +10
                    Свойства -ms-transition не существует. IE9 его не поддерживает, для IE10 префикс не нужен.
                      +1
                      Многие до сих пор border-radius префиксуют :(
                        0
                        Приходится делать свойство с префиксом -moz — третья версия Файрфокса удивительно живуча на компьютерах наших пользователей :)
                          0
                          Отсутствие скруглённых уголков в их браузере, было бы хорошим поводом сменить его :)

                          Ну а если серьёзно, то деградация на то и деградация, что бы из-за одной ну уж очень старой версии, не приходилось делать какую то дополнительную работу.
                      –2
                      Чтобы загрузить картинку — подключать jQ.
                      Мсье знает толк в извращениях.

                      Не знай как многие, а у меня стоит NoScript и я с таких сайтов чаще всего ухожу сразу или довольствуюсь чтением без картинок.
                        –1
                        Специально для таких, как вы, придуманы сайты с черным текстом, черным фоном — и белой картинкой по-середине!
                          +8
                          Лопата

                          Хорошо, поясню.
                          Данная статья рассказывает, как «красиво» загрузить картинку.
                          Даже если за уши притянуть, то на одной «средней» странице картинки максимум весят 1 Мб, в каких нить фотоотчетах (про 18+ хайрез не будем говорить). В большинстве случаях, в обычных статьях, они весят 100-300 кб.

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

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

                          Ну и, как говорилось, создается много проблем, которые тут в комментах всем миром решают.
                          А также пользователь с медленным интернетом может очень долго втыкать на пустой квадрат и думать: «что же для меня там припасено?»

                          Тот же Радикал.ру внедрил подобное. Отстой!

                          Всё уже придумано. Есть способ проще — progressive
                            –2
                            Не только интернет. Вы думаете, браузер быстро отрисовывает такой объем графики? Ошибаетесь. А про мобилки вообще молчу.
                              +4
                              А Вы думаете все картинки разом отображаются на экране, особенно мобильном?

                              Я ещё строю свой негатив на встрече в интернете с «плагинами» подобными, когда при прокрутке страниц начинают мелькать картинки (подгружаться), отвлекая от чтения.

                              А чтобы браузер быстрее работал — для этого и использую NoScript, ну и AddBlock.

                              С нынешними тенденциями везде пихать jQ (сам грешен, не без этого, но я им дополняю, а не заменяю) браузер с 20-30 вкладками начинает напрягать ноутбук, если скрипты везде включены. И работа скриптов с картинками напрягает систему ещё больше.

                              Поэтому глупо всё это, только лишние проблемы.
                                –4
                                Глупо не любить библиотеку, только потому, что «нагружает ноутбук». Вес этой библиотеки где-то как размер одной картинки. Чем она вам мешает? Может быть мешает не библиотека, а криволапое программирование? Ну так и говорите про это. Может радикал тормозит не потому, что там jQ, а потому, что это уродливый косорылый вырвиглазный хостинг с миллиардом баннеров и таким же косорылым нутром?

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

                                Ну а про средний случай в статье не было сказано ни слова. Берете гугл картинки или фликр и пытаетесь сделать такое же, но без нормальной оптимизации подгрузки. Вот тогда и поговорим.
                                  +3
                                  Глупо не любить библиотеку

                                  Где я говорил, что не люблю jQ?

                                  потому, что «нагружает ноутбук»

                                  Если ноутбук нагружается, то поверьте, это не доставляет удовольствия, когда он жужжит бешено и можно на нем яичницу жарить. Я понимаю, что лично мои проблемы и моего ноутбука. Но таких не единицы. Тут равно та же ситуация, что указана тобой ниже: «т.к. последний год только и делаю, что заставляю шевелиться на мобилках списки с картинками»

                                  Вес этой библиотеки где-то как размер одной картинки. Чем она вам мешает? Может быть мешает не библиотека, а криволапое программирование?

                                  У меня отключены скрипты и она ни как не мешает, кроме пожалуй того, что я не увижу картинки, что как раз является «криволапым» программированием и версткой.
                                  И повторю, из-за одной картинки подключать либу весом с картинку глупо.

                                  Может радикал тормозит не потому

                                  И опять передергивание. Я разве говорил конкретно за радикал?
                                  Я просто туда как раз вчера попал и увидел «в тему» и поэтому упомянул.

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

                                  Я уже упоминал, что у меня AddBlock?!

                                  Оптимизация загрузки изображений это очень сложная задача.

                                  Можно с этого момента поподробнее? Мы же про веб говорим, где загрузка уже продумана в браузерах?

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

                                  Так может быть тогда вернемся к фразе «криволапое программирование»?
                                  Ну и выпад был в продолжение темы, в которую Вы, уважаемый, вклинились. Стоило бы всё же прочитать внимательнее моё сообщение. Я же написал: "(про 18+ хайрез не будем говорить)", что является исключением аналогичным гугл или фликр. И то, у первого есть рабочая версия без скриптов, про второго не знаю, не пользуюсь.

                                  Ну а про средний случай в статье не было сказано ни слова.

                                  Зная тенденцию, особенно учитывая на какого читателя рассчитана статья, можно смело предположить что каждый суслик теперь будет агрономом начинающий веб-мастер для крутизны, который увидит эту статью, захочет впихнуть к себе такое. А ведь мало кто задумывается, что та же jQ ещё плохо оптимизирована под мобильные (есть конечно отдельная ветка jQuery mobile) И многие люди просто могут не увидеть картинки. Не увидели картинки — минус продажи.

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

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

                                  Так вот к чему всё это. Попробую подытожить и высказаться ещё раз.

                                  Я не против фремворков. Я за то, чтобы их использовали по назначению.
                                  Правильная верстка должна работать:
                                  1) Без скриптов
                                  2) Без CSS
                                  3) Без картинок
                                  Когда эти пункты сделаны, можно начинать думать о всяких JS плюшках.

                                  PS Извиняюсь за много буковок, но не мог оставить без внимания притенении к словам, которых не было.
                              0
                              Главная проблема их, еще раз повторим для закрепления, медленный интернет. Так вот зачем им ждать загрузку лишних 100 кб библиотеки?

                              Учитывая то, что jQ подключен практически на каждом сайте, то практически у каждого библиотека лежит в кэше браузера.
                                0
                                Это если она подключается сразу с сервера jq, а многие ведь на своём сервере копию хранят и отдают её, так что всё не так уж радужно.
                            –1
                            Плавная подгрузка бесконечного контента — одна из самых трудных задач из всего UI программирования. Одной разметкой вы тут точно не обойдетесь. А технологические альтернативы, например явная пагинация, меня ужасно бесят как пользователя.
                            +2
                            У нас похожим образом загружается реклама. Рекламы на сайте очень много (70-80% веса страницы), загружать её вместе со всеми нет возможности.
                            Решение:
                            1. Модифицированный код загрузки баннеров создаёт вместо картинок плашки-div'ы с аттрибутом data-src. У этих div-ов системой показа баннеров проставлены верные width и height и они занимают места точь-в-точь как картинка.
                            2. div-ы обводятся тонкой серой рамкой (все блоки и баннеры с такой рамкой разных цветов), посередине блока — неброская светло-серая виньетка. Выглядит приятно и органично, лучше, чем белое пространство.
                            3. Когда загружается всё полезное содержимое, jQuery создаёт в каждом div-е с data-src картинку с соответствующим src и аттрибутом opacity: 0.
                            4. Баннеры начинают шквалом загружаться. Перерисовки не происходит, ничего не тормозит, страница отзывчива.
                            5. Через 1-2 секунды или по onload изображения (что произойдёт раньше) opacity каждой картинки меняется на 1. Она анимацией проявляется поверх серой плашки с виьеткой.


                            Особо отмечу, что картинки статей (и вообще все обычные картинки) грузятся обычным способом. Поэтому, любители NoScript видят ровно то, о чём мечтали — работоспособный сайт без рекламы. Нам не жалко (смайлик).

                            Остальные видят быстро загрузившуюся страницу, вместо части блоков которой — плашки, После того, как страница загружена, плашки одна за другой плавно превращаются в баннеры.
                              +3
                              70-80%… Это уже не реклама на сайте, а сайт на рекламе :D
                                0
                                Особенности провинциальных городских порталов (смайлик)

                                Что характерно, читателям реклама тоже нравится — она важная часть городских новостей
                              0
                              В довесок к картинке поста стоило все же рассказать о способах сжатия картинок (средствами сайта) как построчного, так и увеличивая четкость. Я лично ожидал именно этого увидев пост в rss :)
                                –8
                                Хабр здравствуй!
                                Давай как в детстве, поиграем в игру. Будто мы с тобой сидим на лавочке и по очереди описываем проходящих людей. Вот идет дяденка с кривым носом, хмурый, губы поджаты. Вот идет мальчик, дергает маму за юбку и кричит. А этот дедушка такой старый. Кое-как идет.
                                <habracut/>

                                Попробуй понаблюдать за собой. Ведь когда ты встречаешь человека, ты отмечаешь в нем только недостатки. Ищешь ошибки.
                                Этот фокус на негатив накладывает отпечаток и на твой образ мысли и на человека. Ради науки, сформулируй для себя: какую ты задачу решаешь таким подходом?
                                Читаю комментарии к статьям ребят- одни кричалки: тут не то тут не так.
                                Написал человек текст, давайте видеть в нем хорошее. Если человек что-то пишет не так и делает ошибки, это не значит что он дурак, не значит что он мало понимает. Это значит что конкретно здесь и сейчас он написал так. Больше это ничего не значит. Вы застаете человека в чрезвычайно маленький момент его жизни и судите его по этому моменту. Увидели что кто-то прыгает на одной ноге и считаете что это такой одноногий человек.

                                Вспомните себя детьми, что вас мотивировало к развитию? Постоянная ругань родителей и насмешки друзей или поддержка. Ощущение что ты не один.

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

                                Ищите недостатки и вы будете окружены недостатками и ошибками. Ищите добро и добро будет повсюду. Это фундаментальная истина, как гравитация.
                                Люди, которые может и ошибаются в чем-то и недопонимают, гораздо быстрее станут лучше и умнее если их поддерживать. Хабр станет лучше если на нем будет больше думающих добрый людей. Вы будете читать статьи на качественно другом уровне, которые будут упрощать вашу жизнь и делать ее радостнее, потому что те кто могут их писать захотят тут писать.

                                Спасибо.

                                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                Самое читаемое