12
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

un-T factory! XAAdvent Calendar 2019

Day 12

Intersection Observerでスクロールアニメーションをつくってみる

Last updated at Posted at 2019-12-11

#はじめに
今までスクロールに連動した処理を実装するときは、jQueryのscrollイベントを使ってきました。
しかし上記の処理だとスクロールの度に実行され、パフォーマンスに影響を及ぼすことがあります。

今回はIntersection Observer APIを使い、より効率的なスクロール連動アニメーションをつくってみました。

#Intersection Observer API (交差監視 API) とは

ターゲットとなる要素が、祖先要素もしくは文書の最上位のビューポートと交差する変更を非同期的に監視する方法を提供します。
https://developer.mozilla.org/ja/docs/Web/API/Intersection_Observer_API

つまり、これを使うとスクロールして特定の位置にきた時のみに処理を実行できます。

scrollイベントではブラウザ幅の変更で特定の位置が変わった際に、resize処理を考える必要がありました。
Intersection Observerはviewportの変更で要素の位置が変わっても自動的に反応します。
スクロールの度に処理が実行されることがないので、パフォーマンス的にも良いとされてます。

#つくってみた

See the Pen Scroll_Animation by M_H (@hitsujiball) on CodePen.

JavaScript
/**
* スクロールアニメーション
*/
const _setScrollAnime = () => {
  const sectionPos = document.querySelectorAll('.js-sec-target'); // 監視対象の要素

  // IntersectionObserverのオプション設定
  const options = {
    root: null,
    rootMargin: '-50% 0px',
    threshold: 0.5
  };

  // IntersectionObserverを呼び出す
  const observer = new IntersectionObserver(anchorSetting, options);
  
  // ターゲット(sectionPos)を監視する
  for(let p = 0; p < sectionPos.length; p++) {
    (function() {
      observer.observe(sectionPos[p]);
    })();
  }

 // 要素が交差する度(スクロール位置がターゲットに到達する度)に _setCurrent関数 を呼び出す
 function anchorSetting(entries) {
    for(let i = 0; i < entries.length; i++) {
      (function() {
        if(entries[i].isIntersecting) {
          _setCurrent(entries[i]);
        }
      })();
    }
  };
  
  // div.anime に .is-currentクラス を付与する関数
  const _setCurrent = (target) => {
    //.is-currentクラス が付与された要素を取得
    const currentIndex = document.querySelector('.js-anime.is-current');

    // currentIndex に .is-currentクラス が付いていたら削除(初期化)
    if(currentIndex !== null) {
      currentIndex.classList.remove('is-current');
    }

    // 現在地の div.anime に .is-currentクラス を付与
    const currentNew = document.querySelector(`.${target.target.children[1].classList[1]}`);
    currentNew.classList.add('is-current');
  };
};

_setScrollAnime();

##作り方

  1. section.js-sec-targetがブラウザの高さ50%までスクロールしたら、_setCurrent()を実行します。
    alt
  2. div.anime(グレーの正方形)に.is-currentクラスを付与します。(※アニメーションはCSS側で実装しました。)
    alt

##注意点
###IE11はポリフィルが必要
IE11はIntersectionObserverに対応していないので、ポリフィルを追加する必要があります。
https://github.com/w3c/IntersectionObserver/tree/master/polyfill

#感想
今回はスクロールアニメーションを作りましたが、他にも画像の遅延読み込みやグロナビのカレント表示など、様々な場面で活躍しそうだなと思いました。
パフォーマンスを考慮したコーディングができるよう、恐れず積極的に使ってみたいです。

#参考サイト
以下を参考にさせていただきました。
https://developer.mozilla.org/ja/docs/Web/API/Intersection_Observer_API
https://ics.media/entry/190902/

12
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?