iT邦幫忙

2022 iThome 鐵人賽

DAY 7
0
自我挑戰組

向網頁施點魔法粉 framer-motion 系列 第 7

#07 Magic is happening again - layout type & layoutGroup

  • 分享至 

  • xImage
  •  

目錄

  1. 腰間骨會痛記得要用 : layout 的其他種類
  2. 共享朋友 : layoutId
  3. 兄弟會 : LayoutGroup Component

本節資源 : (待補)

今天使用到的範例圖來自 : Everything about Framer Motion layout animations - Maxime Heckel's Blog ,之後會補上自己的實作部分,今天小休息一下。另外尷尬的是免費的影片轉檔 10 張扣打被我用光光了... QQ。

腰間骨會痛記得要用 : layout 的其他種類

碰到網頁 reflow 突然版面會出現跳針、抽蓄的情況,可以試試看其他 layout 屬性來解決。

layout 除了基本直接 layout 單個這樣,它還有不同的值,各司其職。上一篇提到 layout 背後大概做了什麼,歸納一下大概做兩件事 :

  1. 進行 transform 的 位移 到新 re-render 的元件位置
  2. 利用 scale 來 縮放 到 re-render 元件的準確的比例,縮放父元件與反縮放子元件。

也對應到 layout 的其他種類 :

  • true : 預設,同時做縮放大小與位移的漸變動畫。
  • position : 只做位移上的漸變動畫,遇到大小相關會突然直接跳過去
  • size : 只做縮放大小漸變動畫,遇到位移相關屬性改變會突然直接跳過去
<motion.div
  layout = "true"
  layout ="position"
  layout ="size"
/>

可以看到 layout=true 兩件事都有做,position 在一開始放大就跳過去,才做移動;相反的 size 先縮放,而位移變順移了。

不過既然預設 layout 都這麼無敵了,position 跟 size 有何用武之地 ?

我只做位移 : position

官方提到跟 文字有關的元件為了避免被伸縮拉長, position 是最佳的替代屬性。

而在版面上有什麼幫助呢 ? flexbox 是排版聖品,尤其是會自動壓一壓跟自動流向排版,我們只要拿捏好伸縮壓縮比 (glow 、 shrink)跟寫好方向,在不同裝置就可以做出理想的版面。但加上動畫的時候,由於是排版屬性會造成 reflow,像 flex 屬性會根據比例調配剩下的空間或壓縮程度,同時影響到 transform 的 postion 與 scale。

  • 使用 layout=true,會發現 label 會被伸縮給影響跳了一下,因為 flex 跟剩下的空間壓縮比有關,避免這樣的情形,這時可以改用 position。
  • 使用 layout=position,少掉伸縮的閃爍問題

共享朋友 : layoutId

在 React 我們很常會改變節點 render 的狀況 ,例如 :

{isShow ? <div>出來</div> :  <div>消失</div> } // 替代另一種元件
{isShow ? <div>出來</div> :  null } // 從 Render tree 消失

或是做元件上的替換,前者我們會看到元件 "啪 !" 就不見了,就算用 CSS transition 也變得像跟 display : none 直接消失,而 layoutId 幫助在 節點消失/交換在 Render tree 時到下一個 render 進行動畫

可以先 參考官方的範例,可以看到 Tab 底下的 underline 是在個別 <li> 元素,但卻又可以在 標籤消失時進行動畫。其原理是先拿 render 之後的元件,並且拷貝上一個消失或交換的元素位置,利用 transform 移到正確 render之後元件該出現的地方。

兄弟會 : LayoutGroup Component

改變 layout 意味著也可能改變別的元素版面,比如元素消失,底下的元素按照排版流補上。我們知道 layout 先做 transform 位移與縮放,但是實際上最後 render 還是會存在於版面中的實體正確位置,佔據確實的空間,如果有兩個以上的 layout 存在,那 motion 怎麼在原本的排版流 (layout flow) 進行動畫補間排序呢 ?

<LayoutGroup> 就是幫助處理這樣的情形,具體上適用於兩種情境 :

  1. 自身版面的改變,影響到鄰居元素的排版流位置,鄰居元素並沒有動畫可以過渡,直接出現在最終位置,透過 <LayoutGroup> 幫我們加上補間。
  2. 擁有共享 layoutId 的元件群組分開

上面我們提到 layoutId 使得跨元件內部可以漸變同一個元件 layoutId 的動畫補間,但要注意 layoutId 元件是全域的,也就是同時有兩組用到一樣的 layoutId 會導致另一組失靈,而 <layoutGroup> 將個別群組起來並且使用獨特的 id 來辨別避免這個問題發生。

(影片轉換扣打不夠 QQ)

總結

  • layout 還有其他種類, positionsize ,前者只處理位移,後者只處理縮放大小。
  • layoutId : 使跨元件的節點可以進行漸變動畫,看起來像共享元件動畫。
  • <layoutGroup> : 協調多個版面動畫的排版流向或是隔開 layoutId 造成打架的問題。

關於 layout 還有另一個實用的場景,會等到 <Reoreder> 元件在一起討論。明天來點會來點輕鬆的介紹 transition 各種 type 屬性的設定值,並且把 motion props 的部份做總結,下一個大章節會是 motion 其他的 component ,包含最大特色的 <AnimatePresence>

參考資料

  1. 官方文件 : Motion components | Framer for Developers
  2. 非常推薦的文章 : Everything about Framer Motion layout animations - Maxime Heckel's Blog

上一篇
#06 Magic ! layout props
下一篇
#08 Everything in ... transition type
系列文
向網頁施點魔法粉 framer-motion 15
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言