2022 第20週 實作筆記:在 React APP 中實作滾動視差
總結
使用 position: sticky; 製作出滾動視差(parallax effect)效果

展示:https://tzynwang.github.io/react-parallax-effect/ 原始碼:https://github.com/tzynwang/react-parallax-effect/tree/feature/sticky 參考來源:Asana 首頁的動畫效果
筆記
關於 Asana 首頁的滾動視差
- 左側圖片的動畫效果是透過
transform製作出來的,並非 SVG 檔案;在捲動到一定位置時觸發transform來改變 HTMLElement 的位置(transform: translate(...);)與變形(transform: scale(...);)程度,以及border-radius數值 - 數值推測:
- 目測第一區塊右側文字的
getBoundingClientRect().top加上getBoundingClientRect().bottom除以二(即中線)超過window.innerHeight一半後開始position: sticky;效果 - 在第二區塊的
getBoundingClientRect().top超過window.innerHeight一半之後就開始進行圖片變形 - 第三區塊的「開始」判定看來同第二區塊,而「動畫結束」判定看起來是「區塊的
getBoundingClientRect().bottom小於window.innerHeight * 0.05後,將圖片的position: sticky;改為position: absolute;」
- 目測第一區塊右側文字的
實作
- 準備兩套圖文元件:
StaticSection與ScrollAnimationSection,StaticSection處理版面小於 900px 不展示捲動效果的情境,動畫相關的處理都放到ScrollAnimationSection與其子元件中 TextBlock一個設定為100vh高,總計三個,而ImageContainer則配合三個TextBlock堆疊起來的總高度設定為300vh- 元件
Body中,第 84-95 行旨在計算每一個TextBlock的頂部位置,配合useWindowScrollTop()回傳的捲動數值可以判定目前畫面捲動到哪一個區塊 - 元件
Body中的handleScroll會計算ImageContainer元件的頂部是否已經經過畫面頂端,若為true則開始準備展現滾動視差動畫效果 - 元件
AnimationImage根據目前畫面捲動的位置替換src內容- 設定
top: 50vh;搭配transform: translateY(-50%);做出圖片垂直置中的效果 - 因本實作觸發動畫的捲動點與 Asana 版本的不同,在畫面判定捲到最後一個區塊的時候設定
position: absolute;避免圖片繼續被往下推移
- 設定
- 需注意 FireFox 目前並不支援
transition-property: background;,圖片目前僅有在 Chrome 上才會有transition效果 - 需注意不能在 parent element 使用
display: flex;否則position: sticky;會失效