バニラJavaSqriptを使ってスクロールアニメーションを作ってみよう!
jqueryでは簡単に実装できるスクロールアニメーションですが、バニラJSでどう実装するのかやってみました。
See the Pen スクロールアニメーション javascript by shimashima (@chaytee) on CodePen.
Intersection Observerの基本
まずは、簡単な要素の作成をし、その要素がブラウザ画面に入ったり出たりする時を確認。
ここではclassをつけたり外したり。※codepenでは少し見にくいかもしれません。
See the Pen Untitled by shimashima (@chaytee) on CodePen.
コード記述の流れ
①DOMの取得
②動かしたい内容
③オプションがあれば
④インスタンスされたオブジェクトの生成。引数にコールバック関数を取る。第二引数はあればオプションを渡す。
⑤observeメソッドの発動。
const child = document.querySelector('.child');
//動きの詳細を決める
const cb = function(entries, observer){
entries.forEach(entry => {
//渡ってきた要素が画面内に入ってきた場合
if(entry.isIntersecting) {
//console.log('入った');
entry.target.classList.add('inview');
//監視解除について記述もできる
//observer.unobserve(entry.target);
} else {
//画面外へ出た場合
//console.log('出た');
entry.target.classList.remove('inview');
}
});
}
//オプション
const option = {
//詳細な交差設定
root: null,
//要素の交差のオプションをmarginでつける(0もpxがいる)
rootMargin: "-50% 0px -300px 0px",
//進行方向の交差のオプション(進行方向と要素の先頭が0,後ろが1)
threhold: 0
}
//ioはインスタンスされたオブジェクト。コールバック関数を渡されている。
const io = new IntersectionObserver(cb, option);
//監視したい対象のDOM
io.observe(child);
スライドアニメーションの詳細の説明
//addEventListener() メソッド
//optionsは省略可能
target.addEventListener(type, listener [, options]);
DOMContentLoaded・・・HTML の初期文書が完全に読み込まれ解釈された時点で発生し、スタイルシート、画像、サブフレームの読み込みが完了するのを待ちません。
document.addEventListener('DOMContentLoaded', function () {
const cb = function (el, isIntersecting) {
if (isIntersecting) {
el.classList.add('inview');
}
//要素が画面を外れたらクラスを外す
else {
el.classList.remove('inview');
}
}
const so = new ScrollObserver('.cover-slide', cb);
});
//クラス化したもの
class ScrollObserver {
constructor(els, cb, options) {
this.els = document.querySelectorAll(els);
//デフォルトオプションの設定
const defaultOptions = {
root: null, //交差点の設定
rootMargin: "0px", //交差点の位置を設定
threshold: 0, //交差点の進行方向の上部を選択
once: true
};
this.cb = cb;
//デフォルトオプションとoptionsのmarge
this.options = Object.assign(defaultOptions, options);
//this.once = this.options.once;
this._init();
}
_init() {
const callback = function (entries, observer) {
//entriesの配列--entry/entries
entries.forEach(entry => {
//entryに要素があれば処理を行う
if (entry.isIntersecting) {
this.cb(entry.target, true);
//一度だけ読み込む場合
//if(this.once) {
//observer.unobserve(entry.target);
//}
} else {
this.cb(entry.target, false);
}
});
};
//監視している対象が交差した時に起動する
this.io = new IntersectionObserver(callback.bind(this), this.options);
//複数から一つづつ取り出して監視対象
this.els.forEach(el => this.io.observe(el));
}
//不用になったら解除する
//destory() {
//this.io.disconnect();
//}
}