Skip to content

SVG 路径(path)

SVG 的 <path> 元素是最强大的图形元素,通过 d 属性中的指令可以绘制任意复杂的二维图形。路径指令包括移动、画线、弧线、贝塞尔曲线等,是 SVG 图形表达的核心。本节将详细介绍 d 属性中各种指令的用法和组合技巧。

前置知识

阅读本节前,建议先了解:SVG 基本图形

基础概念

<path>d 属性是一系列绘图指令的集合。每条指令由一个命令字母和随后的参数组成。命令分为绝对坐标(大写字母)和相对坐标(小写字母)两种形式。

指令分类

类别指令说明
移动M / m移动到指定点
直线L / l画直线到指定点
水平线H / h画水平线
垂直线V / v画垂直线
三次贝塞尔C / c三次贝塞尔曲线
简写三次贝塞尔S / s平滑三次贝塞尔
二次贝塞尔Q / q二次贝塞尔曲线
简写二次贝塞尔T / t平滑二次贝塞尔
弧线A / a椭圆弧
闭合Z / z闭合路径

详细说明

M - 移动(Move To)

M x,ym dx,dy 移动画笔到指定位置,不画线。

html
<!-- 绝对移动 -->
<path d="M 50,50 L 200,50" stroke="#4285f4" stroke-width="2" fill="none"/>

<!-- 相对移动 -->
<path d="M 50,100 m 50,0 L 200,100" stroke="#34a853" stroke-width="2" fill="none"/>
<!-- m 50,0 表示从当前位置向右移动 50 -->

L - 直线(Line To)

html
<!-- 绘制三角形 -->
<path d="M 100,20 L 180,160 L 20,160 Z"
      fill="#4285f4" stroke="#333" stroke-width="2"/>

<!-- 多条连续直线 -->
<path d="M 20,20 L 80,20 L 80,80 L 20,80 Z"
      fill="#ea4335" stroke="none"/>

H - 水平线 / V - 垂直线

html
<!-- H:水平线到指定 X -->
<path d="M 20,50 H 200" stroke="#4285f4" stroke-width="2" fill="none"/>

<!-- V:垂直线到指定 Y -->
<path d="M 100,20 V 150" stroke="#34a853" stroke-width="2" fill="none"/>

<!-- 组合:阶梯形 -->
<path d="M 20,150 H 60 V 100 H 100 V 50 H 140 V 20"
      stroke="#ea4335" stroke-width="2" fill="none" stroke-linejoin="round"/>

C - 三次贝塞尔曲线

C cp1x,cp1y cp2x,cp2y x,y 使用两个控制点绘制三次贝塞尔曲线。

html
<path d="M 20,200 C 100,50 200,350 380,200"
      stroke="#4285f4" stroke-width="2" fill="none"/>

<!-- 带控制点辅助线的可视化 -->
<svg width="400" height="250" viewBox="0 0 400 250">
  <!-- 曲线 -->
  <path d="M 20,200 C 100,50 200,350 380,200"
        stroke="#4285f4" stroke-width="2" fill="none"/>

  <!-- 控制点辅助线 -->
  <line x1="20" y1="200" x2="100" y2="50" stroke="#ccc" stroke-dasharray="5,5"/>
  <line x1="100" y1="50" x2="200" y2="350" stroke="#ccc" stroke-dasharray="5,5"/>
  <line x1="200" y1="350" x2="380" y2="200" stroke="#ccc" stroke-dasharray="5,5"/>

  <!-- 控制点 -->
  <circle cx="20" cy="200" r="4" fill="#ea4335"/>
  <circle cx="100" cy="50" r="4" fill="#fbbc05"/>
  <circle cx="200" cy="350" r="4" fill="#fbbc05"/>
  <circle cx="380" cy="200" r="4" fill="#ea4335"/>
</svg>

S - 平滑三次贝塞尔

S cp2x,cp2y x,y 是三次贝塞尔的简写形式,第一个控制点自动从前一条曲线的第二个控制点反射得到。

html
<!-- 两条连续的三次贝塞尔 -->
<path d="M 20,200 C 80,50 150,50 200,200 S 320,350 380,200"
      stroke="#4285f4" stroke-width="2" fill="none"/>

Q - 二次贝塞尔曲线

Q cpx,cpy x,y 使用一个控制点绘制二次贝塞尔曲线。

html
<path d="M 20,200 Q 200,20 380,200"
      stroke="#34a853" stroke-width="2" fill="none"/>

<!-- 控制点辅助线 -->
<line x1="20" y1="200" x2="200" y2="20" stroke="#ccc" stroke-dasharray="5,5"/>
<line x1="200" y1="20" x2="380" y2="200" stroke="#ccc" stroke-dasharray="5,5"/>
<circle cx="200" cy="20" r="4" fill="#ea4335"/>

T - 平滑二次贝塞尔

T x,y 是二次贝塞尔的简写形式,控制点自动反射。

html
<path d="M 20,200 Q 100,20 200,200 T 380,200"
      stroke="#9c27b0" stroke-width="2" fill="none"/>

A - 椭圆弧

A rx ry x-rotation large-arc-flag sweep-flag x,y 绘制椭圆弧。

html
<!-- A 的参数说明 -->
<!--
  rx, ry: 椭圆半径
  x-rotation: 椭圆旋转角度
  large-arc-flag: 0(小弧)或 1(大弧)
  sweep-flag: 0(逆时针)或 1(顺时针)
  x, y: 终点坐标
-->

<!-- 绘制半圆弧 -->
<path d="M 50,150 A 100,100 0 0 1 250,150"
      stroke="#4285f4" stroke-width="2" fill="none"/>

<!-- 大弧 vs 小弧 -->
<path d="M 50,100 A 80,80 0 0 0 250,100"
      stroke="#34a853" stroke-width="2" fill="none"/> <!-- 小弧 -->
<path d="M 50,100 A 80,80 0 1 0 250,100"
      stroke="#ea4335" stroke-width="2" fill="none" stroke-dasharray="5,5"/> <!-- 大弧 -->

<!-- 顺时针 vs 逆时针 -->
<path d="M 150,20 A 80,80 0 0 1 230,100"
      stroke="#9c27b0" stroke-width="2" fill="none"/> <!-- 顺时针 -->
<path d="M 150,20 A 80,80 0 0 0 230,100"
      stroke="#fbbc05" stroke-width="2" fill="none"/> <!-- 逆时针 -->

Z - 闭合路径

Zz 从当前点画直线到路径起点,闭合路径。

html
<!-- 闭合路径 -->
<path d="M 100,20 L 180,160 L 20,160 Z"
      fill="#4285f4" fill-opacity="0.3" stroke="#4285f4" stroke-width="2"/>

贝塞尔曲线对比

曲线类型指令控制点灵活度适用场景
三次贝塞尔C2 个S 形曲线、复杂形状
平滑三次S1 个(自动反射)中高平滑连接
二次贝塞尔Q1 个简单曲线
平滑二次T0 个(自动反射)连续平滑曲线

实战示例

示例 1:常见图形用 path 绘制

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>SVG 路径图形</title>
  <style>
    svg { border: 1px solid #ccc; display: block; margin: 10px 0; }
  </style>
</head>
<body>
  <h1>SVG 路径绘制常见图形</h1>

  <svg width="600" height="400" viewBox="0 0 600 400">
    <!-- 心形 -->
    <path d="M 100,180
             C 100,140 60,100 30,100
             C -10,100 -10,150 30,190
             L 100,250
             L 170,190
             C 210,150 210,100 170,100
             C 140,100 100,140 100,180 Z"
          fill="#ea4335"/>

    <!-- 星形 -->
    <path d="M 300,30 L 315,100 L 385,100 L 330,145 L 350,215 L 300,175 L 250,215 L 270,145 L 215,100 L 285,100 Z"
          fill="#fbbc05" stroke="#ea4335" stroke-width="1"/>

    <!-- 箭头 -->
    <path d="M 420,50 L 560,130 L 420,210 M 460,130 L 560,130"
          stroke="#4285f4" stroke-width="3" fill="none" stroke-linecap="round" stroke-linejoin="round"/>

    <!-- 云朵 -->
    <path d="M 400,350
             a 30,30 0 0 1 50,-10
             a 40,40 0 0 1 70,0
             a 30,30 0 0 1 50,10
             Z"
          fill="#90caf9" stroke="#4285f4" stroke-width="1"/>

    <!-- 标签 -->
    <text x="70" y="280" font-size="12" fill="#333">心形</text>
    <text x="280" y="250" font-size="12" fill="#333">星形</text>
    <text x="450" y="250" font-size="12" fill="#333">箭头</text>
  </svg>
</body>
</html>

示例 2:波浪线

html
<svg width="400" height="100" viewBox="0 0 400 100">
  <!-- 正弦波 -->
  <path d="M 0,50 Q 50,0 100,50 T 200,50 T 300,50 T 400,50"
        stroke="#4285f4" stroke-width="2" fill="none"/>

  <!-- 更密集的波浪 -->
  <path d="M 0,80 Q 25,60 50,80 T 100,80 T 150,80 T 200,80 T 250,80 T 300,80 T 350,80 T 400,80"
        stroke="#34a853" stroke-width="1.5" fill="none"/>
</svg>

示例 3:图表中的路径

html
<!-- 面积图 -->
<svg width="400" height="200" viewBox="0 0 400 200">
  <defs>
    <linearGradient id="areaGrad" x1="0" y1="0" x2="0" y2="1">
      <stop offset="0%" stop-color="#4285f4" stop-opacity="0.5"/>
      <stop offset="100%" stop-color="#4285f4" stop-opacity="0.1"/>
    </linearGradient>
  </defs>

  <!-- 填充区域 -->
  <path d="M 0,180 L 40,140 C 60,120 80,100 120,110
           S 180,80 200,60 S 240,100 280,90
           S 340,50 360,40 L 400,30 L 400,200 L 0,200 Z"
        fill="url(#areaGrad)"/>

  <!-- 线条 -->
  <path d="M 0,180 L 40,140 C 60,120 80,100 120,110
           S 180,80 200,60 S 240,100 280,90
           S 340,50 360,40 L 400,30"
        stroke="#4285f4" stroke-width="2" fill="none"/>

  <!-- 数据点 -->
  <circle cx="0" cy="180" r="3" fill="#4285f4"/>
  <circle cx="40" cy="140" r="3" fill="#4285f4"/>
  <circle cx="120" cy="110" r="3" fill="#4285f4"/>
  <circle cx="200" cy="60" r="3" fill="#4285f4"/>
  <circle cx="280" cy="90" r="3" fill="#4285f4"/>
  <circle cx="360" cy="40" r="3" fill="#4285f4"/>
</svg>

注意事项

1. 指令参数分隔

html
<!-- 正确:逗号或空格分隔 -->
<path d="M 10,10 L 100,100"/>
<path d="M10 10 L100 100"/>
<path d="M10,10 L100,100"/>

<!-- 也可以混合使用 -->
<path d="M 10 10, L 100,100"/>

2. 省略重复指令

html
<!-- M 后的多个坐标隐含 L 指令 -->
<path d="M 10,10 100,10 100,100 10,100 Z"/>
<!-- 等价于 -->
<path d="M 10,10 L 100,10 L 100,100 L 10,100 Z"/>

3. 弧线指令的常见问题

html
<!-- 弧线半径不能为 0 -->
<path d="M 0,0 A 0,0 0 0 1 100,100"/> <!-- 错误! -->

<!-- 终点不能与起点相同(需要用弧线闭合用 Z) -->

最佳实践

1. 使用工具生成路径

复杂路径通常由设计工具(Figma、Illustrator、Inkscape)导出,手动编写容易出错。

2. 路径简化技巧

html
<!-- 复杂:多个 M 指令 -->
<path d="M 10,10 L 50,10 M 10,30 L 50,30 M 10,50 L 50,50"/>

<!-- 简化:合并到同一路径(用 M 划分子路径) -->
<path d="M 10,10 h 40 M 10,30 h 40 M 10,50 h 40"/>

<!-- 用 CSS 控制样式 -->
<style>
  .line-group path { stroke: #4285f4; stroke-width: 2; fill: none; }
</style>
<g class="line-group">
  <path d="M 10,10 h 40 M 10,30 h 40 M 10,50 h 40"/>
</g>

3. pathLength 属性(动画利器)

html
<!-- pathLength 可以让路径长度标准化为 1 -->
<svg width="200" height="100" viewBox="0 0 200 100">
  <path d="M 10,50 Q 100,0 190,50"
        stroke="#4285f4" stroke-width="3" fill="none"
        stroke-dasharray="1" stroke-dashoffset="1"
        pathLength="1">
    <animate attributeName="stroke-dashoffset" from="1" to="0" dur="2s" fill="freeze"/>
  </path>
</svg>

下一节

继续学习:SVG 渐变与滤镜

参考链接