canvas绘制贝塞尔曲线核心是设起点后调用方法:二次用quadraticcurveto(cpx,cpy,endx,endy),需moveto显式设起点,控制点不在线上但决定弧度;三次用beziercurveto(cp1x,cp1y,cp2x,cp2y,endx,endy),双控制点分别调控起止段弯曲。

二次贝塞尔:一个控制点,够用又轻量
适合圆角、气泡尾巴、简单弹道等场景。语法是 quadraticCurveTo(cpX, cpY, endX, endY),其中:
- 起点必须提前用
moveTo(x, y)显式设定,否则默认从 (0, 0) 开始,容易错位 -
cpX/cpY是唯一控制点,像磁铁一样把直线往自己方向“吸”——离得越远,弧度越大;放在起点和终点连线的垂直方向上,就能得到标准拱形 - 常见误区:误把控制点当成中间经过的点,其实曲线完全不经过它
例如画一个微笑弧线:
ctx.beginPath();<br>ctx.moveTo(50, 100);<br>ctx.quadraticCurveTo(200, 20, 350, 100);<br>ctx.stroke();
控制点 (200, 20) 在上方居中,自然拉出平滑上凸弧。
三次贝塞尔:两个控制点,精准掌控起止形态
适合更复杂的平滑路径,比如手写体连笔、UI 动效路径、矢量图标描边。语法是 bezierCurveTo(cp1X, cp1Y, cp2X, cp2Y, endX, endY):
-
cp1主要影响起点附近的弯曲方向和陡峭程度(起始段) -
cp2主要影响终点附近的弯曲趋势(结束段) - 若两个控制点对称分布在起点→终点连线两侧,曲线会更均衡;若都偏向一侧,会出现明显“甩尾”或“回钩”效果
例如画一条从左下到右上的柔和上升弧:
ctx.beginPath();<br>ctx.moveTo(50, 150);<br>ctx.bezierCurveTo(100, 50, 300, 50, 350, 150);<br>ctx.stroke();
两个控制点都在上方,合力托起整条曲线,形成饱满拱形。
避坑要点:路径状态比画法更重要
很多“曲线没出来”“连错位置”的问题,根源不在控制点坐标,而在 Canvas 路径管理:
- 每次绘制新曲线前,务必调用
beginPath(),否则会接续上一段路径,造成意外连接 - 避免混用
lineTo()和贝塞尔方法在同一路径中,除非你明确需要折线+曲线混合 - 想闭合形状?用
closePath(),它只连接首尾点,与控制点无关 - 动画中频繁重绘时,别每次都
beginPath() + 全路径重绘,可考虑clearRect()清屏后增量更新
实战小技巧:从设计稿快速落地
设计师给的是 SVG 或 Figma 路径?别手动换算坐标:
- 导出 SVG 后,直接查看
d属性里的C(三次)或Q(二次)指令,提取参数即可复用 - 用在线工具如 Bezier Curve Playground 可视化拖拽调试,实时看到控制点变化效果
- 封装成工具函数,比如
drawSmoothArc(ctx, start, control, end),让业务代码专注逻辑而非数学











