SVG饼图用<path>的A命令绘制扇形,通过动态计算起止角度并插值d属性实现动画;CSS transition需保持路径命令结构一致,JS插值则用requestAnimationFrame手动控制进度。

用 SVG 的 <path> 绘制饼图扇形,配合 CSS transition 或 JavaScript 动画(如 requestAnimationFrame)可实现平滑的百分比变化动画。关键在于动态计算起始/终止角度,并用 d 属性描画弧线路径,再通过插值更新路径数据。
核心思路:用 arc 命令绘制扇形 + 路径数据插值
SVG 饼图不是靠 <circle> 填充,而是用 <path> 的 A(椭圆弧)命令画出从圆心出发、沿圆周扫过的扇形轮廓。动画本质是让 d 属性中弧线参数(半径、起止角度、大弧标志等)随时间连续变化。
- 固定圆心为
(cx, cy),半径为r - 起始角统一设为
-90°(即 12 点方向),便于视觉对齐 - 终止角 =
-90° + 360° × 百分比,需转为弧度传入三角函数 - 使用
path.arc()(如 D3 的d3.arc())或手动拼接d字符串(M cx,cy L x1,y1 A r,r 0 large-flag,sweep-flag x2,y2 Z)
CSS transition 方案(适合简单、单次变化)
给 <path> 设置 transition: d 0.8s ease-in-out,然后在 JS 中直接修改其 d 属性值。浏览器会自动对路径数据做线性插值(仅支持同结构路径,即相同命令序列和参数数量)。
- ⚠️ 注意:必须确保起始
d和目标d使用完全一致的命令顺序(例如都用M L A Z) - 推荐预先生成“空扇形”(0%)和“满扇形”(100%)的
d字符串模板,动画时只替换坐标值 - 示例片段:
path.style.transition = 'd 0.6s cubic-bezier(0.34, 1.56, 0.64, 1)';<br>path.setAttribute('d', getArcPath(0.75)); // 更新为 75%
JavaScript 插值方案(更可控、支持中断与多状态)
用 requestAnimationFrame 手动计算每帧的中间百分比,重绘 d 属性。适用于需要暂停、反向、多扇形联动或响应用户交互的场景。
立即学习“前端免费学习笔记(深入)”;
- 定义起始值
startPercent和目标值endPercent - 每帧按时间比例计算当前
t ∈ [0,1],用缓动函数(如t²(3−2t))映射为进度 - 调用
getArcPath(currentPercent)生成新路径字符串并赋值 - 避免高频重排:使用
transform: translateZ(0)或will-change: transform提升图层(对<path>本身无效,但可包裹在<g>中做位移优化)
实用技巧与避坑点
实际开发中几个容易卡住的细节:
-
角度归一化:JavaScript 的
Math.sin/cos接收弧度,别忘了deg × Math.PI / 180 -
大弧标志(large-arc-flag):当扇形 > 50%(即角度 > 180°)时必须设为
1,否则弧线会走短路径,导致扇形“翻转” -
起点一致性:所有扇形统一从
-90°开始,后续扇形起始角 = 上一个的终止角,避免缝隙或重叠 -
响应式适配:用
viewBox替代固定宽高,让 SVG 自适应容器,路径计算基于相对坐标(如cx=100, cy=100, r=80)



















