フロントエンド開発といえば。
react アプリの初期化( npm init vite@latest <アプリ名> )

ビューポートの高さと特定の要素のビューポート上端からの相対的なY座標の両方を返すカスタムフックを作成する

import { useState, useEffect, useRef, RefObject } from 'react';

interface ViewportPositionHook {
  elementRef: RefObject<HTMLDivElement>;
  relativeY: number | null;
  viewportHeight: number;
}

function useViewportPosition(): ViewportPositionHook {
  // 要素のrefを保持するためのstate
  const elementRef = useRef<HTMLDivElement>(null);
  // 要素のビューポートに対する相対Y座標を保持するためのstate
  const [relativeY, setRelativeY] = useState<number | null>(null);
  // ビューポートの高さを保持するためのstate
  const [viewportHeight, setViewportHeight] = useState<number>(window.innerHeight);

  const updatePosition = () => {
    // ビューポートの高さを更新
    setViewportHeight(window.innerHeight);

    if (elementRef.current) {
      // ビューポートに対する要素の相対位置を取得
      const rect = elementRef.current.getBoundingClientRect();
      // ビューポートの上端からの相対的なY座標をstateにセット
      setRelativeY(rect.top);
    }
  };

  useEffect(() => {
    // リサイズイベントにハンドラーを追加
    window.addEventListener('resize', updatePosition);
    // リサイズイベントが発生した際に位置を更新
    updatePosition();

    // コンポーネントのアンマウント時にイベントリスナーをクリーンアップ
    return () => window.removeEventListener('resize', updatePosition);
  }, []);

  return { elementRef, relativeY, viewportHeight };
}

// 使用例
const MyComponent: React.FC = () => {
  const { elementRef, relativeY, viewportHeight } = useViewportPosition();

  return (
    <div>
      <div ref={elementRef}>この要素のY座標</div>
      {relativeY !== null && (
        <p>この要素のビューポート上端からの相対的なY座標: {relativeY}px</p>
      )}
      <p>ビューポートの高さ: {viewportHeight}px</p>
    </div>
  );
}

export default MyComponent;

No.2413
11/09 15:15

edit