iT邦幫忙

2022 iThome 鐵人賽

DAY 5
0
自我挑戰組

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

#05 Kage Bunshin no Jutsu - Variants

  • 分享至 

  • xImage
  •  

Variants 可以讓元件以字串的方式帶入動畫,同時可以把相同的動畫抽出來,可以說是動畫的影分身之術,此外還有傳播的功能,可以使子元件相同 key 的動畫一起動起來。

目錄

  1. 影分身之術 : variants
  2. Variants 的快遞員 : custom
  3. 手心貼手心 一起心電心 : Variants 的傳播
  4. 當個指揮家 : 在父元件控制子元件編排

本節資源 :
程式碼 | 網頁展示

影分身之術 : variants

在之前都是在個別動畫 props 帶入物件,並且 initialanimate 都共用同一個 transition 設定 :

<motion.div 
  initial={{ ... }}
  animate={{ ... }}
  transition={{ ... }}
/>

variants 可以看做加強版動畫包,更進一步提供 variants 的 props 屬性可以把所有設定提出來,並且可以個別調整動畫 props 的 transition 設定 :

// 建立 variants
const boxVariants={
  hidden :{
    x : -100
    // 個別設定
    transition:{
      ...
    }
  },
  show:{
    x : 0
    // 個別設定
    transition:{
      ...
    }
  }
}

// 在 motion component 使用
<motion.div
  initial= "hidden"  // 用 字串 代替物件
  animate="show" // 用 字串 代替物件
  variants={boxVariants} // 記得加上 variants
/>

官方雖然寫 hiddenshow ,但 只是建議取名,實際上要取什麼名字都可以,符合語意就好。

到本篇為止只有提到控制單個元素動畫, variants 可以把相同的動畫編排提出來,讓動畫能夠應用在不同元件上,不過巢狀元素動畫是很常使用的 variants 的概念的。

Variants 的快遞員 : custom

這時候可能想,阿提出去之後如果要搭配 React 資料流來改變怎麼辦 ? 是這樣嗎 ?

<motion.div
  initial= "hidden"
  animate="show"
  variants={boxVariants(myState)} // 變成 funciton
/>

每次都傳入新的 function 並不是好的操作 :( ,如果知道 React 的渲染機制會進行淺比較,這樣導致有關無關都會重新觸發動畫。

好在 motion 元件可以加入 custom props 屬性,在 variants 物件中使用函式,最多接收一個參數 :

const boxVariants={
  // 接收一個參數 custom 
  hidden : (custom) => {
    // 一樣回傳物件
    return ({
          opacity : custom
          transition:{
            ...
        }
    })
  }
}

<motion.div
  initial= "hidden"
  animate="show"
  variants={boxVariants}
  custom={1}  // 加入 custom props 
/>
  • 按照順序延遲

手心貼手心 一起心電心 : Variants 的傳播

在 JavaScript 的事件機制裡,有先捕獲後冒泡的概念,如果子層或父層同時帶有事件監聽,點擊事件也會被傳播而觸發,在 motion 元件裡也有這個概念。

如果 motion 元件的子元件的 variantsinitialanimate 也都叫同一個名字,只要傳入 variants 不用特別設定那兩個動畫 props 的字串,當父元件觸發時 motion 也會一併觸發相同的子元件的動畫。除非子元件自己訂動畫蓋過去。

簡單來說,我們不需要再為子元件一個個添加 initialanimation 字串

const parent = {
  show : {...},
  hidden : {...}
};
          
const child ={
  show : {...},
  hidden : {...}
}

<motion.div 
  variants={parent} 
  initial="hidden" 
  animate="show"
>
  <motion.span 
    variants={child} // 這裡只要填 variants 就好
  >
    Child
  <motion.span>
</motion.div>

當父元件觸發動畫,子元件也會跟著動,如果 key 的名字沒對不到就不會動。

  • 效果,第二個我取名叫 yoyo 就打斷傳鏈了。

當個指揮家 : 在父元件控制子元件編排

transition 除了基本的屬性外,還提供可以控制子元件與本身元件出現的時間點 :

  • when : 本身元素的動畫觸發時間點,有 false"beforeChildren""afterChildren" ,子動畫前/後,或是通通一起出現的 false。
  • staggerChildren : 底下子元件按照節點順序動畫的時間,比如 1 號結束才會換 2 號,等於 Item(n) = Item(n-1) 的時間 + StaggerTime ,就是累加的延遲時間。

還有延遲跟反轉順序的屬性,後面會再提到,這兩個使用上就蠻綽綽有餘的。

實作 : 逐一漂浮文字

// 父元件動畫,設定子元件的照順序的延遲時間
const boxVariants = {
     show: {
        background: "#fa0", // 顏色會再子元素都跑完後才會觸發
        transition: {
            when: "afterChildren", // 再子元素之後才啟動動畫
            staggerChildren: 0.2,
        },
    },
};

// 把個別文字設定腳本
const wordVariants = {
    show: {
        opacity: 1,
        y: 0,
    },
    hidden: {
        opacity: 0,
        y: 20,
    },
};

let name = "RosaHong";

export default function NameFloating() {
    return (
        <motion.div
            className="wordContainer"
            initial="hidden"
            animate="show"
            variants={boxVariants}
        >
            {name.split("").map((word) => (
                <motion.span
                    key={word}
                    className="nameWord"
                    variants={wordVariants} // 只要添加 variants
                >
                    {word}
                </motion.span>
            ))}
        </motion.div>
    );
}
  • 效果 :

總結

  • variants : 加強版 initialanimate 可以個別控制 transition 屬性。
  • custom props : 傳到 variants 物件作為函式接收一個參數。
  • variants 的傳播概念 : 在巢狀 motion 元件內,父元件的 variants 所使用的 animation 與 initial 字串名會延續到子元件的 variants 。如果子元件的 variants 沒有對應 key-name 則不會動。
  • 父元件可以透過 variants 個別的 transition props 控制子元件的動畫編排方式以及本身要在子元件動畫結束/開始啟動。

明天會介紹很奇妙的 layout props。

鄰近 921 有點敏感,雖然我沒有經歷過,但這兩天被地震嚇得不輕,心神不寧難以坐下來好好寫文 @@,希望大家都平安。

參考資料

  1. 官方文件 : Animation | Framer for Developers

上一篇
#04 Put your Gestures up II - Pan, whileDrag, whileInView
下一篇
#06 Magic ! layout props
系列文
向網頁施點魔法粉 framer-motion 15
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言