0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

IntersectionObserverで動的にscrollMarginを変更したい

Last updated at Posted at 2024-02-19

スクロールイベントを検知するAPIのIntersection Observerですが、インスタンス生成後にscrollMarginを動的に変更することはできません。
以下の記事でも、同じように悩んでいる人がいました。
"How to dynamically change Intersection Observer's configuration"
https://stackoverflow.com/questions/49511503/how-to-dynamically-change-intersection-observers-configuration

今回は、以下のようにラッパークラスを作り対応しました。

/**
 * IntersectionObserverを拡張し、rootMarginの動的な更新をサポートするラッパークラス。
 * 標準のIntersectionObserverでは、rootMarginを変更するためには新しいインスタンスの作成が必要だが、
 * このクラスを使用することで、既存のインスタンスでrootMarginを容易に更新できる。
 */
class IntersectionObserverWrapper {
    private _intersectionObserver: IntersectionObserver;
    private _callback: IntersectionObserverCallback;
    private _options?: IntersectionObserverInit;
    private _targets: Element[] = [];

    /**
     * IntersectionObserverWrapperの新しいインスタンスを作成する。
     * @param callback 要素の視認性の変化を通知するコールバック関数。
     * @param options IntersectionObserverのオプション、rootMarginの初期値を含む。
     */
    constructor(callback: IntersectionObserverCallback, options?: IntersectionObserverInit) {
        this._intersectionObserver = new IntersectionObserver(callback, options);
        this._callback = callback;
        this._options = options;
    }

    /**
     * rootMarginを更新する。このメソッドを呼び出すと、監視中の全ての要素に対して、
     * 新しいrootMarginが適用される。
     * 
     * @param rootMargin 新しいrootMarginの値(例: `-80px 0px -1000px 0px`)。
     */
    updateRootMargin(rootMargin: string): void {
        // 指定された値が現状と変わらなければ何もしない
        if (this._intersectionObserver.rootMargin === rootMargin) {
            return;
        }
        this._intersectionObserver.disconnect();
        const newOptions = { ...this._options, rootMargin: rootMargin };
        this._intersectionObserver = new IntersectionObserver(this._callback, newOptions);
        this._targets.forEach(target => this._intersectionObserver.observe(target));
    }

    /**
     * 指定した要素を監視対象に追加する。
     * 
     * @param target 監視対象に追加する要素。
     */
    observe(target: Element): void {
        this._intersectionObserver.observe(target);
        this._targets.push(target);
    }

    /**
     * 監視を終了し、全ての要素の監視を停止する。
     */
    disconnect(): void {
        this._intersectionObserver.disconnect();
    }
}


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?