最直接方式是用<path>的d属性中C命令:C x1 y1, x2 y2, x y,需先以M定义起点,两个控制点决定起止曲率,S命令可实现平滑续接。

用 <path> 的 d 属性写三次贝塞尔曲线最直接
SVG 本身不提供“画贝塞尔曲线”的独立标签,<path> 是唯一通用且可控的方式。关键在 d 属性里的 C 命令(三次贝塞尔)或 S(平滑续接),不是 Q(二次)——后者不够灵活,控制点难调出真正平滑的连续形变。
常见错误是把坐标写成绝对值却忘了起始点,或者误用 Q 当 C 用,结果曲线突兀、不连贯。
-
C x1 y1, x2 y2, x y:从当前点出发,经两个控制点(x1,y1)和(x2,y2),到达终点(x,y) - 必须先有起点,比如用
M 10 100定义起始位置,否则C会报错或无效果 - 控制点不是曲线上经过的点,而是“牵引力”方向和强度的体现;两个控制点越靠近,曲线越紧;越远或错位,越容易出现尖锐拐点
控制点怎么选才看起来“平滑”
所谓平滑,通常指多段贝塞尔拼接时没有角度跳变,即切线连续(C¹ 连续)。这要求相邻曲线段在连接点处共享切线方向——对 C 而言,就是前一段的终点控制点与后一段的起点控制点关于连接点中心对称。
例如,前一段以 C 50 30, 90 30, 100 50 结束,那么下一段若从 (100,50) 开始,应写作 S 110 70, 140 80(S 会自动镜像前一个控制点 (90,30) 得到第一个控制点 (110,70))。
立即学习“前端免费学习笔记(深入)”;
- 手动配对时,若前一段终点控制点是
(cx2, cy2),连接点是(x,y),则后一段的S第一个控制点应为(x + (x - cx2), y + (y - cy2)) - 用
S替代C可省一个控制点,但前提是前一条是C或S,否则S行为未定义 - 浏览器渲染时不会校验“是否真的平滑”,只按坐标画;肉眼觉得卡顿,大概率是控制点没对齐切线方向
实际画一条带起止点的平滑曲线示例
下面这段 SVG 画的是从 (20,100) 到 (180,100) 的拱形曲线,上下凸起可调:
<svg width="200" height="150">
<path d="M 20 100 C 60 40, 140 40, 180 100"
stroke="#333" fill="none" stroke-width="2"/>
</svg>这里两个控制点 (60,40) 和 (140,40) 水平对称,所以曲线顶部圆润、无偏斜。如果改成 (60,40), (140,60),右侧就会塌陷,视觉上立刻“不平滑”。
- 控制点 y 值越小,拱越高;x 值越靠近端点,曲线越“急弯”
- 想让曲线更缓,把两个控制点往中间靠(如
80 60, 120 60),但别重合,否则退化成直线 - 注意单位是像素,没有自动缩放;在响应式页面中,建议用
viewBox配合 CSSwidth控制尺寸,而非固定width/height
为什么不用 <polyline> 或 JS 库生成路径
有人试过用 <polyline> 连一堆点假装是曲线,或者引入 D3、Snap.svg 动态生成 d 字符串——没必要。原生 <path> 渲染最快,DOM 最轻量,且所有现代浏览器对 C 命令支持完善(IE9+ 即可)。
真正复杂的需求(比如插值动画、实时拖拽控制点)才需要 JS 辅助;静态图、图标、简单动效,手写 d 属性更稳、更易调试、更容易被搜索引擎和屏幕阅读器识别。
- JS 动态拼接
d字符串时,容易漏空格或逗号,导致整个路径不显示,错误信息只在控制台报Invalid value for <path> attribute d - 用
stroke-linecap="round"或stroke-linejoin="round"对贝塞尔曲线无效,这些只影响线段连接处,而<path>是单条路径 - 移动端 Safari 对超长
d字符串(>10k 字符)偶有截断,但几十个控制点完全没问题
平滑不是靠多加控制点,而是两个控制点与端点构成的夹角是否自然;多数时候,三组坐标(起点、两控点、终点)就够用,反复调 y 值比堆参数更有效。



















