Ленивая загрузка изображений

Для работы с Waypoints необходимо подключить библиотеку к проекту. Чаще всего используют версию через CDN:

<script src="https://cdnjs.cloudflare.com/ajax/libs/waypoints/4.0.1/noframework.waypoints.min.js"></script>

После подключения создается объект Waypoint, который отслеживает появление выбранного элемента на экране. Основной синтаксис:

var waypoint = new Waypoint({
  element: document.getElementById('target'),
  handler: function(direction) {
    // действия при достижении элемента
  },
  offset: '75%' // точка срабатывания
});
  • element – DOM-элемент, который отслеживается.
  • handler – функция, вызываемая при пересечении линии срабатывания.
  • offset – расстояние от верхнего края окна до точки срабатывания, может быть в пикселях или процентах.

Использование Waypoints для ленивой загрузки

Ленивая загрузка (lazy loading) подразумевает подгрузку контента, например изображений, только тогда, когда они становятся видимыми пользователю. Это сокращает время первоначальной загрузки страницы и экономит трафик. С Waypoints процесс выглядит следующим образом:

  1. В HTML задаются изображения с атрибутом data-src вместо src:
<img class="lazy" data-src="image1.jpg" alt="Пример">
<img class="lazy" data-src="image2.jpg" alt="Пример">
  1. Создается Waypoint для каждого изображения:
var lazyImages = document.querySelectorAll('.lazy');

lazyImages.forEach(function(img) {
  new Waypoint({
    element: img,
    handler: function() {
      img.src = img.getAttribute('data-src');
      img.classList.remove('lazy');
      this.destroy(); // удаляем waypoint после срабатывания
    },
    offset: '100%' // срабатывание при появлении элемента в видимой области
  });
});
  • this.destroy() удаляет waypoint после загрузки, чтобы не потреблять ресурсы.
  • offset можно регулировать, чтобы изображение подгружалось заранее (например, 200px выше видимой области).

Оптимизация ленивой загрузки

Групповая обработка элементов

Чтобы уменьшить количество созданных объектов Waypoint, можно объединять изображения в контейнеры:

var containers = document.querySelectorAll('.lazy-container');

containers.forEach(function(container) {
  new Waypoint({
    element: container,
    handler: function() {
      var images = container.querySelectorAll('img.lazy');
      images.forEach(function(img) {
        img.src = img.getAttribute('data-src');
        img.classList.remove('lazy');
      });
      this.destroy();
    },
    offset: '100%'
  });
});

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

Использование дополнительных атрибутов

Для более точного контроля можно добавлять атрибут data-srcset для адаптивных изображений:

<img class="lazy" data-src="small.jpg" data-srcset="medium.jpg 600w, large.jpg 1200w" alt="Пример">

И обновлять srcset одновременно с src:

img.srcset = img.getAttribute('data-srcset');

Поддержка повторного отображения

Если элементы появляются повторно (например, при использовании infinite scroll), Waypoints можно не уничтожать полностью, а использовать enabled/disable:

var waypoint = new Waypoint({
  element: img,
  handler: function() {
    img.src = img.getAttribute('data-src');
    img.srcset = img.getAttribute('data-srcset');
    waypoint.disable();
  },
  offset: '100%'
});

disable() временно отключает waypoint, оставляя возможность включить его снова при необходимости.

Управление производительностью

  • Throttle и Debounce – Waypoints встроенно оптимизирован для прокрутки, но при большом количестве элементов лучше комбинировать с requestAnimationFrame или внешними throttle-функциями.
  • Разделение на страницы – при ленивой подгрузке больших галерей имеет смысл разбивать контент на группы и создавать waypoint только для видимой группы.
  • Удаление ненужных waypoint – после подгрузки элементов важно удалять объекты, чтобы уменьшить память и количество событий scroll.

Примеры сложных сценариев

Ленивое подгружение с эффектом анимации

var lazyImages = document.querySelectorAll('.lazy');

lazyImages.forEach(function(img) {
  new Waypoint({
    element: img,
    handler: function() {
      img.src = img.getAttribute('data-src');
      img.classList.add('fade-in'); // CSS-анимация
      this.destroy();
    },
    offset: '90%'
  });
});

CSS-анимация:

img.fade-in {
  opacity: 0;
  transition: opacity 0.5s ease-in;
}

img.fade-in.loaded {
  opacity: 1;
}

JavaScript можно дополнить добавлением класса loaded после установки src для плавного появления.

Интеграция с динамически создаваемыми элементами

Если изображения добавляются через AJAX, нужно создавать waypoint после вставки:

function addNewImages(imagesHtml) {
  var container = document.getElementById('gallery');
  container.insertAdjacentHTML('beforeend', imagesHtml);
  
  var newImages = container.querySelectorAll('img.lazy:not([data-waypoint])');
  newImages.forEach(function(img) {
    img.setAttribute('data-waypoint', 'true');
    new Waypoint({
      element: img,
      handler: function() {
        img.src = img.getAttribute('data-src');
        img.classList.remove('lazy');
        this.destroy();
      },
      offset: '100%'
    });
  });
}

Атрибут data-waypoint предотвращает повторное создание waypoint для одного и того же элемента.

Совместимость и особенности

  • Waypoints работает во всех современных браузерах и поддерживает мобильные устройства.
  • Для элементов с динамическим изменением размеров стоит учитывать, что waypoint рассчитывает позицию при инициализации; после изменения размеров можно вызвать Waypoint.refreshAll().
  • Для вертикальных и горизонтальных прокруток можно использовать horizontal: true, хотя в ленивой загрузке чаще применяют вертикальные скроллы.

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