表題の通りですが、簡単なメモを残しておきます。
要件
- 要素がビューに入った際に1度だけ処理が走る
- 画面描画時に既に要素が表示されている場合は処理を即実行させる
- クロスブラウザに対応させる
対応ブラウザは以下を参照
IntersectionObserver/polyfill
デモ
jsdo.it(console.log
吐いてるだけなのでわかりづらいですね・・・)
解説
以下のjavascriptを3段階に分けて解説していきます。
また、polifillはrawgitを使用して読み込んでいます。
※rawgitについては【個人メモ】rawgithub(CDN)のサービスがアップデートされてたを参考にしました。
var intersectionObserver = new IntersectionObserver(function(entries) {
// target is out of view
if (entries[0].intersectionRatio <= 0) return;
// one time firing
intersectionObserver.unobserve(entries[0].target);
// some functions...
fn(entries[0].target);
});
var elements = document.querySelectorAll('.block');
Array.prototype.forEach.call(elements, function (elm) {
if (elm.getBoundingClientRect().top <= window.innerHeight) {
// target is already displayed
fn(elm);
} else {
intersectionObserver.observe(elm);
}
});
function fn(target) {
console.log('entered the view: ' + target.className);
}
インスタンス生成
var intersectionObserver = new IntersectionObserver(function(entries) {
// target is out of view
if (entries[0].intersectionRatio <= 0) return;
// one time firing
intersectionObserver.unobserve(entries[0].target);
// some functions...
fn(entries[0].target);
});
ここではインスタンスを生成し、要素がビューを出入りした際の処理をコールバックで書いています。
中に3つの処理を書いていますが、それぞれ
- 1つ目:要素が外に出た際には処理しない
- 2つ目:一度処理が走ったら以降処理しない
- 3つ目:何かしらの処理を外部関数で行う
という感じになっています。
entries[0].target
にイベントが発生した要素が入っていますので、これを外部関数fn
に渡しています。
インスタンスに要素を渡す
var elements = document.querySelectorAll('.block');
Array.prototype.forEach.call(elements, function (elm) {
if (elm.getBoundingClientRect().top <= window.innerHeight) {
// target is already displayed
fn(elm);
} else {
intersectionObserver.observe(elm);
}
});
今回は.block
という要素が複数あることを想定しています。
Array.prototype~
とやっているのは、querySelectorAll
で取得できるのがNodeList
という配列に似た何か(表現雑・・・)で、ChromeだとそのままforEach
で回ったりするのですが、確かIEだとエラー出るのでその回避のための記述です。
この中で行っている条件分岐は、要素が既に表示されていたら(既にビューを超えて画面上部に消えている場合も含む)というもので、true
なら外部関数を即実行、false
ならインスタンスに要素を渡す、としています。
外部関数
function fn(target) {
console.log('entered the view: ' + target.className);
}
この外部関数は、observer
から呼ばれるものと要素が既に表示されていたら〜から呼ばれる共通の関数です。
引数、内容はそれぞれの要望に合わせて変更してください。
おわりに
javascriptの進化半端ない