脱jQuery|スクロールインアニメーションの実装

スクロールにあわせて要素にアニメーションを加える実装を「jQuery」を使用しないで実装していきます。
それにあわせてスクロールイベントのパフォーマンス向上のためにスクロールイベントの間引きとスクロールジャック(カクツキ)対策も同時に実装していきます。
目次
実装物
今回実装したものをコードペンで確認してみましょう!
HTML記述
ポイントはふわっとしたアニメーションをあてたい要素に「js-scroll」というクラスを付与することです。
<div class="wrap">
<div class="item js-scroll">
<img src="https://i.postimg.cc/65MQ4nt6/rose-1.jpg" alt="">
</div>
<!-- 以下ループ -->
</div>
CSS(Scss)記述
今回のふわっとしたアニメーションはcssアニメーションで実装しています。
「opacity」と「transform」でふわっとさせています。
ポイントはアニメーションさせたい要素に発火クラス「-cue」を付与した際にアニメーションがあたるように記述してあるところです。
.wrap{
padding: 24vw 0;
width: 100vw;
}
.item{
width: 80vw;
height: 80vw;
min-height: 280px;
min-width: 280px;
max-height: 500px;
max-width: 500px;
margin: 12vw auto;
overflow: hidden;
opacity: 0;
transform: translate3d(0,80px,0);
transition: 1s opacity ease, 1s transform ease;
img{
height: 100%;
width: 100%;
object-fit: cover;
}
&.-cue{
opacity: 1;
transform: translate3d(0,0,0);
}
}
JavaScript記述
コード全体
window.addEventListener("DOMContentLoaded", () => {
const items = document.querySelectorAll(".js-scroll");
let isScroll = true;
let fromBtm = 200;
function onScroll() {
isScroll = true;
items.forEach(item => {
let rect = item.getBoundingClientRect();
if (rect.top < window.innerHeight - fromBtm) {
item.classList.add("-cue");
};
});
};
onScroll();
window.addEventListener("scroll", e => {
if (isScroll) {
requestAnimationFrame(onScroll);
isScroll = false;
};
}, {passive: true});
});
アニメーション対象要素を全取得し、スクロールイベントが走るたびに発火クラス「-cue」を付与しています。
「fromBtm」で画面の下からどれくらいで発火させるかの距離をとっています。
クラス構文
window.addEventListener("DOMContentLoaded", () => {
class ScrollInAnime {
constructor(){
this.items = [...document.querySelectorAll(".js-scroll")];
this.isScroll = true;
this.fromBtm = 200;
console.log(this.items)
this.onScroll = this.onScroll.bind(this);
this.init();
}
onScroll(){
this.isScroll = true;
this.items.forEach(item => {
let rect = item.getBoundingClientRect();
if (rect.top < window.innerHeight - this.fromBtm)
item.classList.add("-cue");
});
}
init(){
this.onScroll();
window.addEventListener("resize", e => {
this.onScroll();
});
window.addEventListener("scroll", e => {
if (this.isScroll) {
requestAnimationFrame(this.onScroll);
this.isScroll = false;
};
}, {passive: true});
}
}
new ScrollInAnime();
});
スクロールイベントの間引き
スクロールイベントは高い頻出で呼び出させれるイベントです。
そのため無駄に呼び出してしまい、サイトの処理を重くさせたりパフォーマンス低下へとつながっていきます。
そのためフレームレートにあった最適な回数だけ呼び出せるように「requestAnimationFrame」を使用して記述をしていきます。
極端に間引いていく際は「setTimeout」などを使用していくそうです。
window.addEventListener("scroll", e => {
if (isScroll) {
requestAnimationFrame( () => {
isScroll = true;
//・・・ 処理 ・・・
});
isScroll = false;
};
});
このように記述し「requestAnimationFrame」内で処理の記述をすることで、アニメーションフレームと同じ頻度でイベントを呼び出し最適化してくれます。
クロールジャック(カクツキ)対策
スクロールイベントのアニメーションのカクツキは「event.preventDefault()」を探しにいっている間にスクロールアニメーション内の他の処理の待ち時間が発生しているため、カクツキが生じたりします。
window.addEventListener("scroll", e => {
//・・・ 処理 ・・・
}, {passive: true});
そのため上記のように「passive: true」を最後に記述することで、ブラウザ側が「event.preventDefault()」を使用していないことを非同期に処理してくれるようになるため、スムーズにアニメーションが実行してくれるようになります。
まとめ
最近はリッチなアニメーションを使用するサイトが増えてきていますので、パフォーマンス向上のためにもしっかりと対策をしていきたいところです。
・参考サイト
Related Article
