logo

在 React 中加入基本「滾動顯示」過場效果

Title 1
Title 2
Title 3
Title 4

為網站加上過場效果,會大大地提升網站體驗,用戶也願意花更多時間在網站上停留。互動式的效果通常會透過以下鼠標事件來觸發:

  • 點擊
  • 懸浮 (Hover)
  • 移動
  • 滾動

在這我想和大家分享一段可重覆使用的程式碼,讓每個 React 元件都能很簡易地加上「滾動顯示」的過場效果。過去我們需要透過偵測網站大小和 Body dom 裡面的不同屬性 (如 scrollHeight),來計算目前用戶滾動到的位置,需要顯示哪些對應的元件。現在我們有一個非常方便的 IntersectionObserver API 可以處理這些和「可視範圍」(viewport) 有關的計算。

讓我們直接來看這段程式碼

import { useEffect, useRef, useState } from 'react'; function useScrollToReveal(): { domRef: React.MutableRefObject<any>; fadeInStyle: React.CSSProperties; } { const domRef = useRef<any>(null); const [isVisible, setVisible] = useState(false); useEffect(() => { const observer = new IntersectionObserver( (entries) => { if (!domRef || !domRef.current) return; // In your case there's only one element to observe: if (entries[0].isIntersecting) { setTimeout(() => setVisible(true), 450); // No need to keep observing: observer.unobserve(domRef.current); } }, { rootMargin: '48px' } ); if (domRef && domRef.current) { observer.observe(domRef && domRef.current); } return () => { if (domRef && domRef.current) { observer.unobserve(domRef.current); } }; }, []); return { domRef, fadeInStyle: { transition: 'all .8s ease-in', opacity: isVisible ? 1 : 0 }, }; } export default useScrollToReveal;
import useScrollToReveal from '@hooks/useScrollToReveal'; function RevealBlock({ title }) { const { domRef, fadeInStyle } = useScrollToReveal(); return ( <div {/* Assign the domRef from useScrollToReveal hook, allow the hook know which component to observe */} ref={domRef} style={{ ...fadeInStyle, height: '300px', fontSize: '1.25rem', backgroundColor: '#FCD9B8', color: '#222', display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: '72px', }} > {title} </div> ); } function ScrollToRevealExample() { return ( <> <RevealBlock title="Title 1" /> <RevealBlock title="Title 2" /> <RevealBlock title="Title 3" /> <RevealBlock title="Title 4" /> </> ); } export default ScrollToRevealExample;

2023 ❤️ MH Tsai