画面内に要素が表示されたらDOM操作してくれるやつ

背中が透けるほどにこすられまくった仕組みの実装で利用する。
あらかじめhtml側の動かしたい要素にclass=”inview”をつけておき、要素がviewport内に表示されたらclass=”inview is-inview”となる。
また要素がviewportから外れたらclass=”inview”となり、is-inviewがtoggleする簡単な仕組み。

これをscrollイベントで実行すると、スクロールが発生するたびに頻繁にトリガーされてしまいます。
しかしながらintersectionObserverを使うと非同期に処理を最適化してくれるため、リソースの節約に繋がります。

 

ソースコード確認

// ターゲット要素をすべて取得
const targets = document.querySelectorAll('.inview');

// IntersectionObserverを設定
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      // ビューポート内に表示されたらクラスを追加
      entry.target.classList.add('is-inview');
    } else {
      // ビューポート外に出たらクラスを削除
      entry.target.classList.remove('is-inview');
    }
  });
}, {
  threshold: 0.1 // 要素が10%表示されたら反応
});

// 各ターゲット要素をオブザーバーに監視させる
targets.forEach(target => observer.observe(target));

 

IntersectionObserver

指定した要素が画面に表示されたら~のような処理を行う場合、スクロールのたびに毎回実行されるscrollイベントではパフォーマンスが悪いので、非同期で監視してくれる。

MDN:IntersectionObserver
https://developer.mozilla.org/ja/docs/Web/API/IntersectionObserver

CSSの例

.inview {
    opacity: .5;
    transition: opacity .5s ease-in-out;
    &.is-inview {
        opacity: 1;
    }
}

class=”inview”状態では半透明であったものが、class=”inview is-inview”となるときっちり見える仕組み。
このjsではis-inviewがtoggleするので、ease-in-outとしている。

 

toggleしなくてもいいよ。1回だけでいいよっていう場合

document.querySelectorAll('.inview').forEach(el => {
  new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        entry.target.classList.add('is-inview');
        observer.unobserve(entry.target);
      }
    });
  }).observe(el);
});

この場合、intersectionObserverをすぐ作成して観測を開始するので、何回も動かしたくない場合は、これが簡単かもしれない。