画面スクロールによりある要素を画面表示に入ってきたら、あるイベントを引き起こせるニーズがあるかもしれない。
例えて言うと、画面ファストビューに入ってない画像やコンテンツなどを非同期に表示すれば、ユーザに快適的にページを閲覧ができます。
従来では独自のJS方法を各々に作成して、画面スクロールを計算し、監視対象がモニタに入ってきたら非同期でコンテンツを取得して表示できますが、
画面スクロールは頻繁に起こして、ブラウザの重くなる原因になります。
近年になって新しく導入されたIntersectionObserverを使えば、パフォーマンスへの影響を気にすることなく、要素の交差判定を簡単に実装することができます。
なお、IntersectionObserverは現在のところ一部のブラウザが対応していません。(IEやsafariが未対応)そのため、実装する前に必ずブラウザの対応状況を確認してください。
と言っても、交差監視IntersectionObserverは非常にシンプルな機能のため、今後の主流ブラウザは対応する可能性が高いと信じてます。
以下はデモページでソースコードでは、コピペで利用できるので、ぜひお試してみてください。
<!DOCTYPE html>
<html lang='ja''>
<head>
<meta charset="utf-8">
<style>
html {
height: 200%;
min-height: 400px;
text-align: center;
font-family: sans-serif;
padding-top: 3.5em;
}
/*-------------------------------------- Processingアニメーション--- */
.Processing-wrap {
width: 100%;
display: table;
position: relative;
/*border: 1px solid #CCC;*/
height: 100%;
}
.Processing {
width: 100%;
height: 100%;
margin: 0 auto;
text-align: center;
display: table-cell;
vertical-align: middle;
}
.Processing__bounce {
width: 12px;
height: 12px;
background-color: rgba(0,0,255,1);
border-radius: 100%;
display: inline-block;
-webkit-animation: Processing__bouncedelay 1.4s infinite ease-in-out;
animation: Processing__bouncedelay 1.4s infinite ease-in-out;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
display: inline-block;
box-sizing: border-box;
}
.Processing__bounce1 {
-webkit-animation-delay: -.64s;
animation-delay: -.64s;
opacity: 0.6;
}
.Processing__bounce2 {
-webkit-animation-delay: -.48s;
animation-delay: -.48s;
opacity: 0.7;
}
.Processing__bounce3 {
-webkit-animation-delay: -.32s;
animation-delay: -.32s;
opacity: 0.8;
}
.Processing__bounce4 {
-webkit-animation-delay: -.16s;
animation-delay: -.16s;
opacity: 0.9;
}
@-webkit-keyframes Processing__bouncedelay {
0%,100%,80% {-webkit-transform: scale(0)}
40% {-webkit-transform: scale(1)}
}
@keyframes Processing__bouncedelay {
0%,100%,80% {transform: scale(0);-webkit-transform: scale(0)}
40% {transform: scale(1);-webkit-transform: scale(1)}
}
/*-------------------------------------- target定義--- */
#target,
#target2,
#target3,
#target4,
#target5 {
display: inline-block;
margin: 0 auto 50vh;
padding: 14em 3em;
position: relative;
}
.UnderInquiry {
/* background-color: #DEDEDE;*/
}
.FinishedInquiry {
background-color: transparent;
color: #222;
}
</style>
</head>
<body>
<p>下へスクロールしたら、非同期でコンテンツを取得にし表示します….<p>
<br>
<div id="target" class="">Target</div>
<br>--------------------------Target2--------------------------<br>
<div id="target2"class="">Targe2t</div>
<br>--------------------------Target3--------------------------<br>
<div id="target3"class="">Target3</div>
<br>--------------------------Target4--------------------------<br>
<div id="target4"class="">Target4</div>
<br>--------------------------Target5--------------------------<br>
<div id="target5"class="">Target5</div>
<script >
/*************************************************************
* observerCallback receives
* a list of IntersectionObserverEntry objects and the observer
*************************************************************/
function observerCallback(entries, observer) {
for (entry of entries) {
//console.log(entry);
//監視対象の表示割合
let ratio = entry.intersectionRatio;
if (ratio >= 1) {
console.log('INFO:' + entry.target.id + 'が完全視界に入りました。');
dummyFun(entry.target.id);
} else if (ratio <= 0) {
console.log('INFO:' + entry.target.id + 'が視界から去りました。');
} else {// entering OR leaving
console.log('INFO:' + entry.target.id + 'の一部が視界に入っています。');
dummyFun(entry.target.id);
}
}
}
/* This custom threshold invokes the handler(observerCallback) whenever:
1. The target begins entering the viewport (0 < ratio < 1).
2. The target fully enters the viewport (ratio >= 1).
3. The target begins leaving the viewport (1 > ratio > 0).
4. The target fully leaves the viewport (ratio <= 0).
Try adding additional thresholds!
*/
let observerOptions = {//オプション
root: null,
rootMargin: '0px',
threshold: [0,1]
}
let observer = new IntersectionObserver(observerCallback, observerOptions);
//監視する要素を配列に入れる
var targetList = new Array('target','target2','target3','target4','target5');
//要素を監視
for(var i in targetList) {
var targetId = targetList[i];
observer.observe(document.getElementById(targetId));
}
/*
* ダミーメソッドです。
* 実業務の場合、非同期でサーバから取得した内容を、引数でID指定した要素にセットして表示。
*/
function dummyFun (elemId) {
var emObj = document.getElementById(elemId);
//初期状態の場合、処理
if(emObj.className == ''){
emObj.className = 'UnderInquiry';
// 処理中に画面で表示
emObj.innerHTML = document.getElementById('temp-proccessing').innerHTML ;
//TODO get date from server
setTimeout(function(){
emObj = document.getElementById(elemId);
emObj.className = 'FinishedInquiry';
var dummyMsg = 'welcome to ' + elemId + '<br>';
dummyMsg += '最新の内容を取得しました。';
emObj.innerHTML = dummyMsg;
}, 3000);
}
return;
}
</script>
<!-- 処理中のアニメーション(入れ子として用意しておく) -->
<div id="temp-proccessing" style="display:none;">
<div class="Processing-wrap">
<div class="Processing">
<div class="Processing__bounce Processing__bounce1"></div>
<div class="Processing__bounce Processing__bounce2"></div>
<div class="Processing__bounce Processing__bounce3"></div>
<div class="Processing__bounce Processing__bounce4"></div>
<div class="Processing__bounce Processing__bounce5"></div>
</div>
</div>
</div>
</body>
</html>
♪ 当記事がお役に立ちましたらシェアして頂ければ嬉しいです。
★ 当記事を閲覧の方は下記の【関連記事】も閲覧していました。
zanmai @2016年03月31日
» ①②③④の順で設定できるはず。…