JavaScriptのLazyLoadのプログラム (画像の遅延読み込み)

2021年3月3日JavaScript

LazyLoad (画像の遅延読み込み)は、パフォーマンスに大きく貢献するエフェクトです。

lazy-loadのJavaScriptプログラムの書き方を紹介します。

JavaScriptのLazyLoadのプログラム

HTMLでデフォルトで低解像度の軽い画像をCSSでブラーなどをかけて表示させておきます。
そして、スクロールされたらdata-src属性で設定した高解像度の画像を表示させます。

HTML
        <img
          src="img/lazyimg1.jpg"
          data-src="img/goodimg1.jpg"
          alt="img1"
          class="features__img lazy-img"
        />
        <img
          src="img/lazyimg2.jpg"
          data-src="img/goodimg2.jpg"
          alt="img2"
          class="features__img lazy-img"
        />
        <img
          src="img/lazyimg3.jpg"
          data-src="img/goodimg3.jpg"
          alt="img3"
          class="features__img lazy-img"
        />

HTMLでは、src属性では低解像度の画像を設定します。
そして、データ属性を設定し、そこに高解像度の画像を設定します。
スクロールしたら、低解像度の画像を高解像度の画像に置き換えるということをします。

CSS
.lazy-img {
  filter: blur(18px);
}

filterを使うと、とても簡単にブラーをかけてぼやけさせることが可能です。

JavaScript


//targetとなる要素のすべてのデータ属性を取得
const imgTargets = document.querySelectorAll('img[data-src]');
console.log(imgTargets);
//NodeList(3) [...lazy-img, ...lazy-img, ...lazy-img]

//コールバック関数を設定
const LoadImg = function (entries, observer) {
  const [entry] = entries;
  console.log(entry);

  //Guard clause(Guard Clause ガード節,ガード条件)
  if(!entry.target) return;
  // srcとdata-srcを入れ替える
  entry.target.src = entry.target.dataset.src;

  //filterのblurを取り除く(loadを使う)
  entry.target.addEventListener('load', function () {
    entry.target.classList.remove('lazy-img');
  });

  //ovserveを止める。
  observer.unobserve(entry.target);
};

//IntersectionObserverを設定
const imgObserver = new IntersectionObserver(LoadImg, {
  root: null,
  threshold: 0,
  rootMargin: '200px', //早めに表示させるため。
});

//forEachでそれぞれのデータ属性を観測するように設定して、呼び出す
imgTargets.forEach(img => imgObserver.observe(img));

targetとなる要素のすべてのカスタムデータ属性を取得

targetとなる要素のすべてのカスタムデータ属性を取得します。
今回の場合、カスタムデータ属性はdata-srcなので、img[data-src]とすることで、カスタムデータ属性を選択することができます。

forEachでそれぞれのデータ属性を観測するように設定して、呼び出す

次に、forEachを使って、それぞれの画像でobserverに画像を観測させます。

IntersectionObserverを設定

IntersectionObserverを設定します。
rootはビューポートで観測するためにnullをセットします。
thresholdは0とします。
今回の場合、lazy-loadは基本的にはバックグランドの処理を高速化させたいだけで、見せたいものではありません。
少し早めに表示させるために、rootMarginを設定します。
プラスの数字をセットすることで、Y軸で上の方向に反応をずらすことができます。

コールバック関数を設定

entryを定義

entriesは1つでも配列のため、分割代入でentryを取り出します。
entry.targetが画像を意味します。

Guard Clause(ガード節)を設定

Guard Clause(ガード節)を設定して、無関係の場合は即returnを返させます。
そして、ターゲットを観測したら、srcとdata-srcを入れ替えることで低解像度の画像と高解像度の画像を入れ替えることができます。

loadを使ってblurを削除

さらに、ブラーがかかっているので、addEventListenerのloadを使って、filterのblurを取り除きます。

unobserveで観測をとめる

そして、最後に一度実行するだけでいいので、実行が終わったらovserveを止めます。