形状变形
MorphSVG
MorphSVG SVG 变形 路径变形 形状过渡 Shape Morphing Path Morph
GSAP 动画让一个 SVG 路径平滑变成另一个形状;GSAP 的 MorphSVG 插件会自动处理两条路径锚点数量不同的问题。
又称:SVG 变形 · 路径变形 · 形状过渡 · Shape Morphing · Path Morph
- GSAP
- Claude / Cursor
Prompt 片段
用 GSAP MorphSVGPlugin 做图标切换:同一个 path 依次变成星形、心形再变回圆形,每段 duration 1,ease expo.inOut,同时过渡 fill 颜色,timeline 设 repeat: -1。把播放按钮的三角形 path 变形为暂停图标,点击时 morphSVG 到暂停路径,再点击变回;两条路径都放在 viewBox 0 0 24 24 的同一坐标系里。变形过程中形状扭曲得厉害,帮我调整 morphSVG 的 shapeIndex,或把 type 改成 'rotational' 试试效果。
是什么
形状变形(MorphSVG)是让一个 SVG 形状平滑过渡成另一个形状的动画。浏览器原生只能在锚点数量和命令结构一致的两条路径之间插值,实际的图标几乎不可能满足这个条件。MorphSVGPlugin 会自动补齐锚点、匹配起点,让任意两条路径都能过渡。它随 gsap 包免费提供,从 gsap/MorphSVGPlugin 导入。
上方演示只有一个 path 元素:先从圆形变成五角星,再变成心形,最后回到圆形,填充色同步从紫色过渡到橙色、红色。每段变形使用 expo.inOut,中间停顿 0.6 秒。
核心参数
| 写法 | 含义 |
|---|---|
morphSVG: '#star' |
目标可以是选择器、元素或路径字符串 |
shape |
对象写法中的目标形状 |
shapeIndex |
调整起点对应关系,用来修正扭曲 |
type |
'linear' 或 'rotational',后者适合有旋转感的变形 |
map |
锚点匹配策略:'size'、'position'、'complexity' |
MorphSVGPlugin.convertToPath() |
把 circle、rect 等转成 path |
代码示例
import { gsap } from 'gsap';
import { MorphSVGPlugin } from 'gsap/MorphSVGPlugin';
gsap.registerPlugin(MorphSVGPlugin);
// 三条路径都在 viewBox="0 0 100 100" 中
const CIRCLE = 'M50,10 C72.1,10 90,27.9 90,50 C90,72.1 72.1,90 50,90 C27.9,90 10,72.1 10,50 C10,27.9 27.9,10 50,10 Z';
const STAR = 'M50,8 L61.8,37.6 L93.7,39.2 L69,59.4 L77,90.2 L50,73 L23,90.2 L31,59.4 L6.3,39.2 L38.2,37.6 Z';
const HEART = 'M50,88 C50,88 10,62 10,36 C10,22 21,12 33,12 C41,12 47,17 50,23 C53,17 59,12 67,12 C79,12 90,22 90,36 C90,62 50,88 50,88 Z';
const tl = gsap.timeline({ repeat: -1, repeatDelay: 0.6, defaults: { duration: 1, ease: 'expo.inOut' } });
tl.to('#shape', { morphSVG: STAR, fill: '#ff9f0a' })
.to('#shape', { morphSVG: HEART, fill: '#ff375f' }, '+=0.6')
.to('#shape', { morphSVG: CIRCLE, fill: '#bf5af2' }, '+=0.6');
什么时候用
- 图标状态切换:播放与暂停、菜单与关闭、加号与对勾。
- 插画、Logo 的变形转场。
- 数据可视化中形状之间的过渡。
常见误区
- 对 circle、rect 等非 path 元素直接变形:先用
convertToPath()转成 path。 - 源和目标来自不同画板、坐标系不一致:变形时会连带产生位移和缩放。
- 形状差异太大:插件能保证过渡,但中间帧可能很难看。设计时让形状的重心和大小接近,效果更自然。