
スクロール判定の作成方法
一般的に特定の要素までスクロールしたらCSSのactiveクラスを付けてCSSアニメーションを実行する場合、JavaScriptのscrollイベントが使用されるが、scrollイベントを使用すると処理が重くなるという問題がある。
また、特定の要素すべてにactiveクラスを付けてCSSアニメーションを実行する要素がなくなってもscrollイベントを実行し続けているWebサイトが多く存在する。
IntersectionObserverを使用する
scrollイベントではなくIntersectionObserverを使用すると処理が軽くなる。
IntersectionObserverとはターゲットとなる要素を監視するためのAPIで詳細はMDNのWebサイトに書かれているが、内容が少し難しいので最初はターゲットとなる要素までスクロールされたか判定できるAPIだと認識できれば良いです。
IntersectionObserverを使用したコード
まずJavaScriptの前にHTMLとCSSを用意する。
以下のサンプルでは.scrollAnimeの要素までスクロールされた際に.activeが追加された場合はCSSアニメーションが動作するようにした。
<h1>IntersectionObserverによるスクロール位置取得</h1>
<h2>↓ 1000px以上スクロールして確認してみてください。</h2>
<div class="scrollAnime">scrollAnime1</div>
<hr>
<div class="scrollAnime">scrollAnime2</div>
h2, hr {
margin-bottom: 1000px;
}
.scrollAnime {
transition: all 1s linear;
transform: translateX(-20px);
opacity: 0;
}
.scrollAnime.active {
transform: translateX(0);
opacity: 1;
}
JavaScriptは以下の通り。querySelectorAllでCSSアニメーションを動作させる要素を取得する。
すべての要素に.activeが追加された場合はobserver.disconnect()で終了されるため、scrollイベントだけの処理とは違いJavaScriptが動作しつづけることがない。
const targets = [].slice.call(document.querySelectorAll('.scrollAnime'))
const targetsLen = targets.length
if (targetsLen) {
const observer = new IntersectionObserver(changes => {
for (let i in changes) {
if (changes[i].isIntersecting) {
changes[i].target.classList.add('active')
const activeLen = document.querySelectorAll('.scrollAnime.active').length
if (targetsLen === activeLen) {
observer.disconnect()
}
}
}
})
targets.forEach(target => observer.observe(target))
}
ちなみにIntersectionObserverはIE11は使用不可のため、IE11も対象のWebサイトの場合はpolyfill.min.jsを読み込んでください。
polyfill.min.jsを読み込めばIE11でも動作します。
<script src="https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"></script>
IntersectionObserverによるスクロール判定CSSアニメーションサンプル