IntersectionObserverをカスケード
Updated: 5/14/2022 Original: 8/18/2020
要素が範囲内に現れたかどうかを判定するのに便利なIntersectionObserver。だけど、このObserverが要素にゴニョゴニョした後にその要素の中の別要素をnew IntersectionObserverでまたなんとかしようとしてつまづきました。
例えばですね、こんなケースです。
-
親要素(targetA)はビューポートの中段に来た頃にフェードイン
-
その後、targetA内にあるtargetBがビューポートの上端に達したらなんか発動
みたいなときです。結果的には、並列に書いちゃだめで、入れ子で作らなきゃいけないってことでした。簡略化しまくったのでこのままでは動きませんが、要は次のようなイメージです。
const observerA = new IntersectionObserver((entriesA) => {
entriesA.forEach(entryInA => {
if (entryInA.isIntersecting) {
/* DO SOMETHING FOR targetA using entryInA*/
/* Add observer for targetB */
const observerB = new IntersectionObserver(
(entriesB) => {
/*DO SOMETHING FOR targetB using entriesB*/
}, {});
observerB.observe(entryInA.target.querySelector("#targetB"));
/* remove observer not to duplicate */
observerA.unobserve(entry.target);
}
});
}, {});
observerA.observe(document.querySelector('#targetA'));
observerAとobserverBは順番付けとかないと全然反応してくれないんですね。随分と時間を食ってしまいました、とほほ。
追記(8/25):loadのイベントリスナー内に入れたら大丈夫でした。結構普通な解決になってしまった。
//code for targetA, then:
window.addEventListener("load",()=>{
const targetB = document.querySelectorAll('.targetB');
const handlerB = (entries) => {
entries.forEach(e => {
//do something for targetB elements
});
};
const observerB = new IntersectionObserver(handlerB, {
//options
});
targetB.forEach(b => {
observerB.observe(b);
});
},false);
https://developer.mozilla.org/ja/docs/Web/API/Intersection_Observer_API/Timing_element_visibility