
SVG 動畫很常在一些使用者互動上看到,例如 Navbar 上的小漢堡。而在 motion API SVG 也可以變成 motion.path、motion.circle ... 這類元件直接進行操作。我對 SVG 還在摸索,今天主要以實現簡單的動畫為主。
在 CSS 中 SVG 線段動畫會使用到 stroke-dashoffset 、 stroke-dasharray 來控制。而在 motion 元件中要直接操作可以使用類似屬性來達效果 :
pathLength : 以使用者單位 (user units) 指定路徑的總長度。通過使用比率 pathLength/(路徑長度的計算值) 縮放所有距離計算來校準瀏覽器與圖片本身距離計算。例如 :  stroke-dasharray 的起點是 0 終點就是 pathLength。pathSpacing  :  對應到 stroke-dasharray 的第二個數值,每個切割線段間距多少。pathOffset :  對應到 stroke-dashoffset 線段的位移量註 : 使用者單位 (user units) 是什麼 ? 可以參考 這篇文章提到的 SVG 規範
// CSS
.checkbox{
    width: 150px;
    height: 150px;
    border-radius: 30px;
    cursor: pointer;
}
// JS
const [isChecked, setIsChecked] = useState(false);
<motion.div
  className="checkbox"
  animate={{
      scale: isChecked ? 1 : 0.8,
      backgroundColor: isChecked
          ? "rgba(0,0,0,1)"
          : "rgba(0,0,0,.4)",
  }}
  transition={{ type: "spring", stiffness: 300, damping: 20 }}
  onTap={() => setIsChecked(!isChecked)}>
  <svg
      xmlns="http://www.w3.org/2000/svg"
      width="150"
      height="150">
      <motion.path
          d="M38 74.707l24.647 24.646L116.5 45.5"
          fill="transparent"
          strokeWidth="20"
          stroke="#fa0"
          strokeLinecap="round"
          animate={{
              pathLength: isChecked ? 0.9 : 0,
              opacity: isChecked ? 1 : 0,
          }}
      />
  </svg>
</motion.div>
在操作圖形變形動畫,framer motion 官方建議搭配 flubber ,主要的目的是矯正圖形之間節點變換的問題,如果 A、B 兩張圖,依靠座標點來進行位移,從 A1 點移到 B1 點的位置可能跑到非常遙遠的位置,導致破圖,另一個就是兩張圖節點數不同,變成點憑空出現,這些問題導致圖片在轉化過程破損。

操作 SVG 我沒有很多經驗,最多使用到線段動畫而已,爬文過程中發現原來 SVG 還有更多的屬性可以操作,例如 SMIL,提供更多語意化標籤直接操作動畫。這些標籤也都可以搭配 motion 元件。
下一個章節會來認識 Motion values 的 Hooks ,這些 Hooks 可以追蹤動畫的狀態,做出更細微的互動動畫效果。