Загрузка видимых изображений (Lazy Load) на JavaScript


Загрузка видимых изображений (Lazy Load) на JavaScript

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

Готовых скриптов Lazy Load для разных популярных JavaScript-фреймворков написано уже немало. Мне же, как всегда, захотелось реализовать свой вариант. Да и вам, наверное, будет интересно узнать как это все работает.

Сперва сделаем заготовку HTML-страницы. Это будет контейнер галереи, в котором будут размещены несколько картинок. Ничего сложного, самая обычная верстка:
<div id="gallery">
  <img src="/images/image01.jpg" width="600" height="450" alt="Фото 1">
  <img src="/images/image02.jpg" width="600" height="450" alt="Фото 2">
  <img src="/images/image03.jpg" width="600" height="450" alt="Фото 3">
  <img src="/images/image04.jpg" width="600" height="450" alt="Фото 4">
  <img src="/images/image05.jpg" width="600" height="450" alt="Фото 5">
  <img src="/images/image06.jpg" width="600" height="450" alt="Фото 6">
  <img src="/images/image07.jpg" width="600" height="450" alt="Фото 7">
  <img src="/images/image08.jpg" width="600" height="450" alt="Фото 8">
  <img src="/images/image09.jpg" width="600" height="450" alt="Фото 9">
  <img src="/images/image10.jpg" width="600" height="450" alt="Фото 10">
  <img src="/images/image11.jpg" width="600" height="450" alt="Фото 11">
  <img src="/images/image12.jpg" width="600" height="450" alt="Фото 12">
</div>

Теперь перейдем к теоретической выкладке. Как работает Lazy Load? После загрузки HTML-содержимого страницы, но до момента ее полной загрузки (все скрипты и изображения), запускается скрипт, который заменяет все изображения в отслеживаемой области на "заглушку" - однопиксельный прозрачный GIF-файл. Чтобы верстка страницы при этом не поплыла, размеры всех оригинальных картинок обязательно должны быть указаны. Данные о ссылках на исходные картинки удобнее всего сохранять прямо в элементе img, добавляя ему наш собственный атрибут lazy. После этого устанавливается обработчик событий на прокрутку окна и изменение размеров. На каждое срабатывание события (пользователь прокручивает страницу), скрипт пробегает по всем картинкам в контейнере, высчитывает их положение относительно верхнего края страницы, и, если они попадают в видимую область, то заменяет атрибут src на сохраненный атрибут lazy. В этом случае картинка будет загружаться с сервера или будет взята из кеша браузера, если он была ранее туда загружена. Для ускорения проверки у отображаемых картинок атрибут lazy можно удалять. Осталось оформить это все в виде скрипта. Нам понадобится вспомогательная функция, которая будет возвращать координаты местоположения элемента на странице относительно верха страницы.
// Вспомогательная функция для определения координат элемента
function lazy_get_position(element) {
    var offsetLeft=0;
    var offsetTop=0;
    do {
        offsetLeft+=element.offsetLeft;
        offsetTop+=element.offsetTop;
    }
    while (element=element.offsetParent);
    return {x:offsetLeft, y:offsetTop};
}

Теперь напишем функцию инициализации. Для повышения быстродействия мы будем обрабатывать не все картинки на странице, а только те, которые находятся в нужном нам контейнере-галерее. Он задается через ID родительского элемента, в нашем случае это "gallery":
// ID родительского элемента
var lazy_parent_id='gallery';
 
function lazy_load() {
 
    // Картинка-заместитель
    var lazy_replacer='dot.gif';
    var container=document.getElementById(lazy_parent_id);
    if (container) {
        var im=container.getElementsByTagName('img');
        // Сохранить адрес исходной картинки и заменить его на прозрачный GIF
        for (var i=0; i<im.length; i++) {
            var el=im[i];
            if (el.src) {
                el.setAttribute('lazy',el.src);
                el.lazy=el.src;
                el.src=lazy_replacer;
            }    
        }    
    }
 
    // Установить обработчики событий окна
    window.onscroll = lazy_load_proc;
    window.onresize = lazy_load_proc;
    // Сразу же показать картинки в видимой области
    lazy_load_proc();
}

Осталось написать обработчик, который будет показывать картинки в видимой области. Я его подробно прокомментировал, непонятностей быть не должно.
// Обработчик событий прокрутки
function lazy_load_proc() {
    var doc = document.documentElement;
    var body = document.body;
 
    // Получить размеры видимой области страницы (кроссбраузерно)
    if (typeof(window.innerWidth) == 'number') {
        my_width = window.innerWidth;
        my_height = window.innerHeight;
    }
    else if (doc && (doc.clientWidth || doc.clientHeight)) {
        my_width = doc.clientWidth;
        my_height = doc.clientHeight;
    }
    else if (body && (body.clientWidth || body.clientHeight)) {
        my_width = body.clientWidth;
        my_height = body.clientHeight;
    }
 
    // Получить смещение страницы относительно ее верха
    if (doc.scrollTop) { dy=doc.scrollTop; } else { dy=body.scrollTop; }
 
    // Обработка всех картинок в контейнере
    var container=document.getElementById(lazy_parent_id);
    if (container) {
        var im=container.getElementsByTagName('img');
        for (var i=0; i<im.length; i++) {
            var el=im[i];
            // Если атрибут lazy есть, то обработать картинку
            if (el.lazy) {
                // Получить координаты картинки от верха страницы
                var coord=lazy_get_position(el);
                // Если картинка попала в видимую область, то показать ее.
                // Плюс берется запас в 100 пикселов для более плавной подгрузки
                if (coord.y>(dy-my_height-100) && coord.y<(dy+my_height+100)) {
                    // Прописать адрес исходной картинки и убрать атрибут lazy
                    el.src=el.lazy;
                    el.setAttribute('src',el.lazy);
                    el.lazy='';
                    el.removeAttribute('lazy');                
                }    
            }
        }
    }
}

Последний шаг. Осталось все это поместить на нашу страницу. Текст функций для краткости я дублировать не стал, они все описаны выше. Должно получиться примерно следующее:
<script type="text/javascript">
// ID родительского элемента
var lazy_parent_id='gallery';
function lazy_load() { ... }
function lazy_load_proc() { ... }
function lazy_get_position(element) { ... }
</script>
 
<div id="gallery">
  <img src="/images/image01.jpg" width="600" height="450" alt="Фото 1">
  <img src="/images/image02.jpg" width="600" height="450" alt="Фото 2">
  <img src="/images/image03.jpg" width="600" height="450" alt="Фото 3">
  <img src="/images/image04.jpg" width="600" height="450" alt="Фото 4">
  <img src="/images/image05.jpg" width="600" height="450" alt="Фото 5">
  <img src="/images/image06.jpg" width="600" height="450" alt="Фото 6">
  <img src="/images/image07.jpg" width="600" height="450" alt="Фото 7">
  <img src="/images/image08.jpg" width="600" height="450" alt="Фото 8">
  <img src="/images/image09.jpg" width="600" height="450" alt="Фото 9">
  <img src="/images/image10.jpg" width="600" height="450" alt="Фото 10">
  <img src="/images/image11.jpg" width="600" height="450" alt="Фото 11">
  <img src="/images/image12.jpg" width="600" height="450" alt="Фото 12">
</div>
 
<script type="text/javascript">
// Инициализировать скрипт
lazy_load();
</script>

Если используются какие-то посторонние фреймворки, то запуск lazy_load() надо забиндить на событие "ondocumentready", то есть когда уже произошла полная загрузка HTML и скриптов, но еще не загружены все картинки. Вешать запуск Lazy Load на событие "onload" бессмысленно, так как при его наступлении все картинки уже загружены, и никакой пользы от использования этой технологии не будет. На индексацию поисковыми системами она также не влияет, ведь в HTML-коде, который "видит" робот-поисковик, прописаны ссылки на оригинальные картинки. Также этот метод будет работать при отключенных скриптах, пользователь просто будет вынужден загрузить сразу все картинки.

Вот такая интересная, а главное полезная технология "отложенной загрузки" изображений. Демонстрационный пример можете посмотреть у меня на сайте. В FireBug наглядно видно, как меняется содержимое страницы по мере ее прокрутки.


Изменение содержимого страницы в FireBug
Теги:
Lazy Load
Добавлено: 15 Сентября 2013 02:33:11 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...