一般來說 CSS 無法 對漸層產生動畫效果,而在 framer-motion 更新後官方文件有特別介紹漸層的動畫效果是可以實現的。我們可以用此特性來製作**百頁窗效果 Blind ** 的 Reveal
效果示意圖如下
首先運用 CSS mask-image 圖片遮罩效果,把漸層當作遮罩來使用
準備好兩組遮罩來處理:運用 repeating-linear-gradient 完成百葉窗的遮罩
const hiddenMask = `repeating-linear-gradient(to right, rgba(0,0,0,0) 0px, rgba(0,0,0,0) 30px, rgba(0,0,0,1) 30px, rgba(0,0,0,1) 30px)`;
const visibleMask = `repeating-linear-gradient(to right, rgba(0,0,0,0) 0px, rgba(0,0,0,0) 0px, rgba(0,0,0,1) 0px, rgba(0,0,0,1) 30px)`;
準備好 Image 並由 Box(作為遮罩) 包住。
我們準備好兩個 state 一個是圖片載入另一個是進入 viewport
const [isLoaded, setIsLoaded] = useState(false);
const [isInView, setIsInView] = useState(false);
<MotionBox
viewport={{ once: true }}
onViewportEnter={() => setIsInView(true)} // 進入畫面時 setIsInView(true)
>
<Image src={ithome} onLoad={() => setIsLoaded(true)} /> // 圖片載入好時 setIsLoaded(true)
</MotionBOx>
設定好 animatie,當圖片載入且進到有效視角時時要從 hiddenMask -> visibleMask。
我們這邊用三元運算子來改變 animate 動畫狀態
<MotionBox
viewport={{ once: true }}
onViewportEnter={() => setIsInView(true)} // 進入畫面時 setIsInView(true)
animate={
isLoaded && isInView
? { WebkitMaskImage: visibleMask, maskImage: visibleMask }
: { WebkitMaskImage: hiddenMask, maskImage: hiddenMask }
}
initial={false}
transition={{ duration: 1, delay: 1 }}
>
<Image src={ithome} onLoad={() => setIsLoaded(true)} /> // 圖片載入好時 setIsLoaded(true)
</MotionBOx>