😎

IntersectionObserverを使うときに、複数作っても大丈夫?と悩んだのでメモ

2022/07/12に公開

observer = new IntersectionObserver はいくつも作れます!

コーディング練習でPhotoshopカンプからのコーディングを練習していたときに、
少し悩みました。
でも、よく考えたら、ふつうにつくれるでしょうということのような気もしますが、
ぼくの勉強も含めて記事にしようと思いました。

やりたかったこと

1つのページの中で、交差オブザーバーを使って、以下の2つを付けたいと思いました。

  • ある程度スクロールしてきたらヘッダー出現
  • スクロールに合わせて、タイトルや画像が入ってくる、よくあるやつ

最初にヘッダーの出現をIntersectionObseverを使って実装していました。
その後、スクロールに合わせてのアニメーションはお手軽なAOSにしようとしました。
すると、まだきちんと確認していないのですが、競合してしまっているような感じがしました。
なので、すべてのアニメーションをIntersectionObseverを使おうとしました。

ちがうアニメーションをつけたい。

ということで、オブザーバーのインスタンス(?)を2つ作りたいなと思ったのですが、
ふと、
「2つ作っても大丈夫なのか?」と
疑問に感じたので、調べてみようと思い立ったしだいです。

検索してみた

「IntersectionObsever 複数」などで検索すると
「複数要素を監視」の記事が多くて、Observerインスタンスを2つ作れるのか、
複数のインスタンスを作って、違うコールバック関数を使いたいという例が出てきません。

でも、よくよく考えてみれば、
インスタンスなのだから、いくつか作っても全くOKってあとで気づいた次第です。

解決して書いたコード

// ヘッダーが現れるときのアクション
// これはある程度スクロールしたらクローンのヘッダーが上からスライドダウンしてくるアニメーションを付けています。
const options = {
  rootMargin: "80%",
  threshold: 1.0,
};
const headerObserver = new IntersectionObserver((entries) => {
  entries.forEach((e) => {
    if (!e.isIntersecting) {
      headerClone.classList.add("clone-open");
    }
    if (e.isIntersecting) {
      headerClone.classList.remove("clone-open");
    }
  });
}, options);
headerObserver.observe(mv);

// タイトルアニメーション
// これは各セクションのタイトルが見えたら、左からシュッと入ってくるアニメーション
const titleObserver = new IntersectionObserver((entries) => {
  entries.forEach((e) => {
    if (e.isIntersecting && !e.target.classList.contains('slideLeft')) {
      console.log(e.target);
      e.target.classList.add("slideLeft");
    }
  });
});
const animateTitles = document.querySelectorAll('.c-section__heading-block');
animateTitles.forEach((t)=>{
	titleObserver.observe(t);
})

// 画像のアニメーション
// いくつかの画像に下からシュッと出現するアニメーション
const imageObserver = new IntersectionObserver((entries)=>{
	entries.forEach((e)=>{
		if (e.isIntersecting && !e.target.classList.contains('fadeUp')) {
      console.log(e.target);
      e.target.classList.add("fadeUp");
    }
	})
})
const animateImages = document.querySelectorAll('.js-animate-image');
animateImages.forEach((t)=>{
	console.log(t.target);
	imageObserver.observe(t);
})

今後のこと

パフォーマンス的にどうなのだろうかというところは今後の課題。
Obseverインスタンスを1つにして、
その中のコールバック関数で、
要素の種類に応じて、違うアニメーションをつけるとかいう方法もあるのだろうか、
とかぼんやり考えています。

Discussion