JavascriptでHTML要素が画面に入った時に処理を実行する

WebサイトやUI作成時に使えるようメモ。

・scrollイベントを拾う方法 → scrollごとにイベント発火

・IntersectionObserverを使った方法 → root要素と対象要素が交差した時にイベント発火。

IntersectionObserverの方が発火頻度が少なく軽量らしいので、こちらを使う。

1 サンプル

See the Pen InView by snst.lab (@snst-lab) on CodePen.

2 関数の定義

/**
* @function HTMLElement.prototype.inview HTML要素と画面の交差を判定し処理を実行する
*/
if(!HTMLElement.prototype.inview){
Object.defineProperty(HTMLElement.prototype, "inview", {
configurable: true,
enumerable: false,
writable: true,
/**
* @function callbackInView HTML要素が画面内に入った時に実行する関数
* @function callbackOutView HTML要素が画面から出た時に実行する関数
*/
value: function(callbackInView, callbackOutView) {
const options = {
root: null,
rootMargin: '0%', //要素が交差する手前でコールバックを呼び出したい場合はrootMarginに0%以外の値を
threshold: [0.5] //交差領域が50%変化した時にコールバックを呼び出す
};
const observer = new IntersectionObserver((entries) => {
for(const e of entries) {
//要素が画面内に入った時( e.isIntersecting 交差を判定するブール値)
if(e.isIntersecting && Object.prototype.toString.call(callbackInView) === '[object Function]'){
callbackInView(e);
}
//要素が画面から出た時
else if(!e.isIntersecting && Object.prototype.toString.call(callbackOutView) === '[object Function]'){
callbackOutView(e);
}
}
},options);
observer.observe(this);
}
});
}

3 使用例

HTML

下方向にスクロールすると要素がスライドインします↓
<div class='item' style='margin-left:80%;opacity:0;'></div>

Javascript

const item = document.querySelector('.item');
item.inview(
function(){
//要素が画面内に入った時slideinアニメーションを適用
item.style.animation = 'slidein 1000ms linear forwards';
},function(){
//要素が画面内から出たら初期値に戻す
item.style = 'margin-left:80%;opacity:0;';
});

CSS

.item{
width:10rem;
height:10rem;
margin-top:100vh;
border-radius:50%;
}

@keyframes slidein {
0% {
opacity:0;
margin-left: 30vw;
}
50% {
opacity:1.0;
margin-left: 1vw;
background:deeppink;
}
80%{
background: yellow;
}
100%{
opacity:1.0;
margin-left: 1vw;
background:turquoise;
}
}

4 ブラウザ対応状況&参考URL

https://developer.mozilla.org/ja/docs/Web/API/Intersection_Observer_API#Browser_compatibility
Chrome >5.1
Edge >15
Firefox >55

Leave a Reply

Your email address will not be published. Required fields are marked *