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;