【更新日 : 】
【JavaScript】Intersection Observer + scrollイベントでパララックスを実装する
Category: JavaScript
Tags: JavaScript, transition, Vanilla JS, アニメーション, パララックス, レイアウト, 脱Jquery, 自作関数
Intersection Observer + scrollイベントでパララックスを実装したサンプルです。
画面に入った要素のみscrollイベントを発火させるので、scrollイベントのみの実装よりは低負荷になっていると思います。
※以前実装した以下のコードをベースにしています。
【脱Jquery】Vanilla JSでシンプルなパララックスを実装する
動作サンプル
表示エリアからはみ出している量だけ画像が動きます。
動く量はウィンドウの高さに応じて算出しているので、スクロール中に要素がエリアから飛び出したりもしません。
See the Pen
Intersection Observer + Scroll Event Parallax Vanilla JS by web_nak (@web_walking_nak)
on CodePen.
HTML
<div class="js-parallax-elm-box">
<div class="js-parallax-elm">
<img src="画像パス" alt="">
</div>
</div>
表示エリア(.js-parallax-elm-box)の中に、動かす要素(.js-parallax-elm)を内包してください。
上記は画像を格納していますが、何が入っていても動きます。
CSS
.js-parallax-elm-box {
overflow: hidden;
}
.js-parallax-elm-box img {
display: block;
}
表示エリアからはみ出している要素を隠すため、最低限overflow: hidden;を設定してください。
※表示エリアのheightは実装するデザインに応じて適宜設定してください。
パララックス関数
//Intersection Observer + Scroll Event Parallax Vanilla JS
function parallax() {
'use strict';
//class設定
//表示エリア class
const targetClass = '.js-parallax-elm-box';
//動かす要素 class
const childClass = '.js-parallax-elm';
//表示エリア取得
const targets = Array.prototype.slice.call(document.querySelectorAll(targetClass),0);
//表示エリアが存在するかチェック
if(targets.length === 0) {
return;
}
//observer設定
let observer = new IntersectionObserver(observerFunc, {
root: null,
rootMargin: '0px',
threshold: 0
});
//ウィンドウの高さ取得
let winH = window.innerHeight;
//スクロール量(ウィンドウの上端)取得
let scrollTop = window.pageYOffset || document.documentElement.scrollTop;
//スクロール量(ウィンドウの下端)取得
let scrollBottom = scrollTop + winH;
//初期設定
let setListener = [];
let settings = [];
targets.forEach((target,index) => {
//Listener設定取得用の判別番号をセット
target.setAttribute('data-index',index);
//動かす要素を取得
const child = target.querySelector(childClass);
//動かす要素が存在するかチェック
if(!child) {
return;
}
//処理用の設定を追加
settings.push({
child: child,
//比率取得:スクロールできる最大量 / (ウィンドウの高さ + 表示エリアの高さ)
scrollRatio: (child.clientHeight - target.clientHeight) / (winH + target.clientHeight)
});
//scrollイベントへ渡すlistener設定
setListener.push(
{
target: target,
handleEvent: function handleEvent () {
requestAnimationFrame(parallaxFunk.bind(target));
}
}
);
//初期表示の位置調整
requestAnimationFrame(parallaxFunk.bind(target));
//observer監視開始
observer.observe(target);
});
//高さ更新
let resizeID;
window.addEventListener('resize', function() {
clearTimeout(resizeID);
resizeID = setTimeout(() => {
//ウィンドウの高さ取得
winH = window.innerHeight;
//各要素の高さ更新
targets.forEach((target,index) => {
//動かす要素が存在するかチェック
if(!settings[index].child) {
return;
}
//比率取得:スクロールできる最大量 / (ウィンドウの高さ + 表示エリアの高さ)
settings[index].scrollRatio = (settings[index].child.clientHeight - target.clientHeight) / (winH + target.clientHeight);
});
}, 200);
});
//スクロール量更新
window.addEventListener('scroll', function() {
//スクロール量(ウィンドウの上端)取得
scrollTop = window.pageYOffset || document.documentElement.scrollTop;
//スクロール量(ウィンドウの下端)取得
scrollBottom = scrollTop + winH;
}, {passive: true});
//observer処理
function observerFunc(entries) {
entries.forEach(entry => {
//listener設定取得
const listener = setListener[entry.target.getAttribute('data-index')];
if(entry.isIntersecting) {
//画面に表示されている要素のみスクロールイベントへ追加
window.addEventListener('scroll', listener, {passive: true});
} else {
//画面外のときはスクロールイベント削除
window.removeEventListener('scroll', listener, {passive: true});
}
});
}
//パララックス位置調整関数
function parallaxFunk() {
//番号取得
const index = Number(this.getAttribute('data-index'));
//表示エリアの位置取得
const targetPosi = this.getBoundingClientRect().top + scrollTop;
//ウィンドウの高さに対するスクロール量を取得(小数点第2以下は四捨五入)
const setVal = ((scrollBottom - targetPosi) * settings[index].scrollRatio).toFixed(1);
//スクロール値を設定
settings[index].child.style.transform = 'translate3d(0,'+ (setVal * -1) +'px,0)';
}
}
対象class名を変更したい場合は、targetClass「表示エリア class」と、childClass「動かす要素 class」を編集してください。
関数の呼び出し
任意の場所で以下を実行し関数を呼び出してください。
//パララックス呼び出し
parallax();
関連リンク
- 【JavaScript】Intersection Observer + requestAnimationFrameでパララックスを実装する
- 【脱Jquery】Vanilla JSでシンプルなパララックスを実装する
参考リンク
- 交差オブザーバー API
- EventTarget.addEventListener()
- EventTarget.removeEventListener()
- addEventListenerで関数に引数を渡す
- simpleParallax.js
- 猫でもわかるスクロールイベントパフォーマンス改善ポイント2018 スクロールイベントを最適化する
- addEventListener の第3引数が拡張されてるという話