【JS】IntersectionObserverで複数を監視
こんにちは!JavaScriptのnewの意味が4年経ってもあんま分からないMizutani(@sirycity)です。オブジェクト指向に触れ合う機会がなかったの...
今日はIntersectionObserverで複数を監視する方法についてです。あとついでに簡単な書き方も紹介する。
結論
短く書いたバージョン
なるべく短く書くとこんな感じ。
window.addEventListener('DOMContentLoaded', () =>
['foo', 'bar', 'baz'].map((id, i)=>
new IntersectionObserver(([e]) =>
e.isIntersecting
? console.info(`${i}番目のやつが画面に入りました`)
: console.info(`${i}番目のやつが画面から出ました`)
).observe(document.getElementById(id))
)
)
丁寧に書いたバージョン
こんな感じ。上のやつと挙動は一緒よ。分解しただけ。
const ids = ['foo', 'bar', 'baz']
const elements = ids.map(({id}) => document.getElementById(id))
const checkIntersection = i => ([e]) =>
e.isIntersecting
? console.info(`${i}番目のやつが画面に入りました`)
: console.info(`${i}番目のやつが画面から出ました`)
const registarIntersection = (element, i) =>
new IntersectionObserver(checkIntersection(i)).observe(element)
const registarIntersections = () =>
elements.map(registarIntersection)
window.addEventListener('DOMContentLoaded', registerIntersections)
解説
↑の丁寧に書いたバージョンを6箇所に分けて解説してきます。こんな感じに
// 1
const ids = ['foo', 'bar', 'baz']
// 2
const elements = ids.map(({id}) => document.getElementById(id))
// 6
const checkIntersection = i => ([e]) =>
e.isIntersecting
? console.info(`${i}番目のやつが画面に入りました`)
: console.info(`${i}番目のやつが画面から出ました`)
// 5
const registarIntersection = (element, i) =>
new IntersectionObserver(checkIntersection(i)).observe(element)
// 4
const registarIntersections = () =>
elements.map(registarIntersection)
// 3
window.addEventListener('DOMContentLoaded', registerIntersections)
1. 使うidを羅列
画面内に入ってきたかを判定したい要素がいくつかあるとします。こんな感じに
<div>こいつが画面内に入ってきたか判定したい</div>
<div>こいつも判定したい</div>
<div>こいつも</div>
まずはこの3つにidを付けてまいましょう。 ここは色々やり方あるけど(同じクラスにするとか)、今回はバラバラのidにする。こう
<div id='foo'>こいつが画面内に入ってきたか判定したい</div>
<div id='bar'>こいつも判定したい</div>
<div id='baz'>こいつも</div>
ok、そしたらJS側に今付けたidを配列で定義しましょう。こう
const ids = ['foo', 'bar', 'baz']
これでおわり。
2. DOMを取得
1.で定義したIDのDOMを取得します。こう。
const elements = ids.map(({id}) => document.getElementById(id))
わけ分からない?要はやってることはこれと一緒よ。
const elements = [
document.getElementById('foo'),
document.getElementById('bar'),
document.getElementById('baz'),
]
こんだけのこと。「ID」を「そのIDが付いている要素」に変換するだけね!
「アロー関数」とか「分割代入」とか「javascript map」でググるともっと詳しいのが出ると思う。
3. ページが読み込み終わったら発火する処理
こんだけ。
window.addEventListener('DOMContentLoaded', registerIntersections)
これはコピペ感覚でいいかな?ページが読み込み終わったらregisterIntersections
を実行するよーってだけ。
4. 全ての要素にintersectionを登録する準備
ここは監視対象一つなら不要。今回は監視対象(elements)が複数なのでループしてる。そんだけ。
const registarIntersections = () =>
elements.map(registarIntersection)
5. IntersectionObserverを監視対象を指定して発動
IntersectionObserver発動。監視対象にelement(idを元に取ってきたDOM)を指定してます。
「このelementってやつを監視せえよ」ってイメージ。
具体的な監視内容は中の6.checkIntersectionで定義します
const registarIntersection = (element, i) =>
new IntersectionObserver(checkIntersection(i)).observe(element)
6. 監視の処理を定義
今回は短いけどこんな感じ。
const checkIntersection = i => ([e]) =>
e.isIntersecting
? console.info(`${i}番目のやつが画面に入りました`)
: console.info(`${i}番目のやつが画面から出ました`)
いくつかポイント解説。
([e])ってやつは引数()の配列の0番目の要素です。普通は(foo)みたいな感じで取って、foo[0]で最初の要素にアクセスする...みたいな書き方するね。
今回は引数に来るのがidに紐付いたDOMで、かつidは1つしか付けられないので配列の長さが1であることが確定しているからこんな書き方してます。
配列の長さが決まってたり、配列のn番目しか使わなかったりする場合に使うといいかも。ちなみに使わないとこんな書き方になる
const checkIntersection = i => e =>
e[0].isIntersecting
? console.info(`${i}番目のやつが画面に入りました`)
: console.info(`${i}番目のやつが画面から出ました`)
ちなみにちょっと前に書いたけどclassでDOM取る方法だとここの配列(e)が長さ複数になってめんどいです。今回はidで取ってるから長さは絶対1。安心。
そんで、その後のisIntersectingってのが画面内か(true)画面外か(false)の判定です。今回は画面内外に分けてconsole.logしてるけど、ここには任意の処理を書くといいと思う。
結論
うん、仕様が悪いな
なんかもうちょいわかりやすくできなかったのかな(ECMAに喧嘩を売っていくスタイル) intersectionは普通にaddEventLintenerに付けてほしかった。 newとか言われてもね。わかんないね。
intersection関連でもう1記事書きます!以上。
LINK
TAGS
LATESTS
POPULAR
- CSS2021/04/29【CSS】右寄せの方法は結局flexが一番良さそう
- React2020/07/13【JS】Reactのstyleの使い方、書き方いろいろ
- Payment2021/10/16GooglePayでVisaタッチを使う時に知っておきたい過酷な現実【追記あり】
- Others2021/07/11Slackに予約投稿機能ができて嬉しいけどそれでもまだ少し不満な理由【追記あり】
- CSS2020/04/30【CSS】tailwind.cssでよく使うデザインパターン
- CSS2019/03/30【CSS】100vhは「一画面」ではないという罠
- CSS2020/06/09【CSS】max-font-sizeやmin-font-sizeを使いたくなったら
- Vue2019/06/29【JS】Vueの:classの書き方3通り
- JavaScript2020/09/02【JS】yarnの長所とyarnからnpmに戻ってきた理由
- React2020/06/04【JS】ReactのclassNameの色々な書き方紹介