Last active
February 13, 2025 08:55
-
-
Save manabuyasuda/3632ec15d04106adf254a816919b9f3c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* スクロール方向 | |
* 'up': ページトップ方向へのスクロール(ページを上に戻る) | |
* 'down': ページボトム方向へのスクロール(ページを下に進める) | |
* 'none': スクロールが発生していない状態 | |
*/ | |
type VerticalScrollDirection = 'up' | 'down' | 'none'; | |
/** | |
* スクロール方向を監視するhook | |
* @returns {VerticalScrollDirection} スクロール方向 | |
* - 'up': ページトップ方向へのスクロール(ページを上に戻る) | |
* - 'down': ページボトム方向へのスクロール(ページを下に進める) | |
* - 'none': スクロールが発生していない状態 | |
*/ | |
export const useVerticalScrollDirection = () => { | |
const [direction, setDirection] = useState<VerticalScrollDirection>('none'); | |
const prevScrollY = useRef<number>(0); | |
// アニメーションフレーム処理中フラグ | |
const ticking = useRef<boolean>(false); | |
useEffect(() => { | |
const handleScroll = () => { | |
// 処理が実行されていない場合だけ実行する | |
if (!ticking.current) { | |
// ブラウザの描画タイミングに合わせて処理を予約する | |
requestAnimationFrame(() => { | |
const currentScrollY = window.scrollY; | |
const newDirection: VerticalScrollDirection = | |
currentScrollY > prevScrollY.current ? 'down' : 'up'; | |
// スクロール位置が0の場合はnoneを設定 | |
if (currentScrollY === 0) { | |
setDirection('none'); | |
} else { | |
setDirection(newDirection); | |
} | |
prevScrollY.current = currentScrollY; | |
// 処理を完了し、次のイベントを受付可能にする | |
ticking.current = false; | |
}); | |
// 状態を処理中に更新して、これ以降のイベントをブロックする | |
ticking.current = true; | |
} | |
}; | |
// Scroll Junkを防止してパフォーマンスを最適化する | |
window.addEventListener('scroll', handleScroll, { passive: true }); | |
return () => window.removeEventListener('scroll', handleScroll); | |
}, []); | |
return direction; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment