よく見る要素が画面に到達したら表示されるアニメーションの実装(みんな好きなあれ)
よくオシャンティーなサイトとかで、画面を下にスクロールしていると色んな方向から要素がふわっと表示されたりするサイトありますよね。あれめっちゃ憧れます。
一見Animationでなんとかなりそうと思っても「要素が画面に到達したら」の部分の実装が難しいわけです。結局これもjsでどうにかするしかないわけですね。色んな方向からふわっとみたいなのは適当にCSSでほげほげすればいいわけです。
本題
まずやることを細分化して「要素が画面に到達したら」の条件を書いてみることにする。
使うメソッドとプロパティがこちら
getBoundingClientRectメソッド
Viewportからの相対位置を左上を基準としてtop,right,bottom,leftのプロパティで実数値を返してくれる。
要素の内側の高さの値を実数値で返してくれる。
Viewportの高さの値を実数値で返してくれる。
この3つをなんかこう上手い事使えばいけそうな気もしなくなってきたわけである。
考え方
- まずどうすれば「要素が見えた」というのを判定すればいいのか考えなければいけない。
そこで「Viewportの高さの数値」よりも「Viewport上段から要素の上の辺までの距離の数値」が低い場合という条件式を書けば良い。 - 1を判定しただけだとcontent-boxが1pxでもViewportに表示された時点で発火してしまうため、アニメーションされてるのかわかりづらくなってしまう。そのため、「要素自身がViewportの上の辺からnpx距離を縮めたら発火する」という計算をしなくてはならない
詳しく解説
- 仮に「Viewportの高さの数値」を800pxとした場合、その数値は可変しない数値となる。
そして「Viewport上段から要素の上の辺までの距離の数値」は画面をスクロールする度に可変する数値となる。
要素がViewportに表示されていない場合、「Viewport上段から要素の上の辺までの距離の数値」は必ず800px以上の数値が返り値となっているはず。
要素が1pxでも画面上に表示された場合「Viewport上段から要素の上の辺までの距離の数値」は必ず799px以下となるため上記の考え方の式が成り立つわけである。
それをif文に起こせばいい。 - アニメーションさせる要素の高さの一部のn%が表示されたら1を発火させるという処理が必要
一応言語化して書いてるつもりだが、日本語のTierがブロンズ過ぎて非常にわかりづらいかもしれない。
実際にコードを書いてみる
const $targetElement = document.querySelectorAll('.animationtarget');
document.addEventListener('scroll', function () {
for (i = 0; i < $targetElement.length; i++) {
const $getElementDistance = $targetElement[i].getBoundingClientRect().top + $targetElement[i].clientHeight * 0.5
if (window.innerHeight > $getElementDistance) {
$targetElement[i].classList.add('show')
}
}
})
コード解説
まずはアニメーションさせたい要素を配列で取得
アニメーションさせたい要素の数分for文を回す(アニメーションさせたい要素にclass属性の.animationtargetが記述されてるものとする)
$getElementDistance変数で冒頭に記述した「要素自身がViewportの上の辺からnpx距離を縮めたら発火する」を下記の式で定義する
「Viewport上段から要素の上の辺までの距離の数値」+「要素のcontent-box」*0.5
あとは6行目の式の通り「Viewportの高さの数値」より上記の式の値のほうが小さい場合classを追加させる処理を発火させれば無事アニメーションの準備が整うわけである。
感想
汎用性が高く、ひとまずこのjsだけ用意しておけば、これから何か新規でページを作成する際アニメーションさせるような要素が必要な場合、発火させる用のclassを追加してあとは適当にほげほげCSSを書いてあげれば簡単にアニメーションさせる事が出来る。
Discussion