arc()是中心定义法,按圆心、半径、起止角度画弧;arcto()是切线连接法,用两个切点和半径自动生成相切圆弧,适用于圆角路径。

Canvas 中的 arc() 和 arcTo() 都能画圆弧,但用途、参数逻辑和适用场景完全不同,容易混淆。关键区别在于:arc() 是“中心定义法”,按圆心、半径、起止角度画一段圆弧;arcTo() 是“切线连接法”,用两个切点和一个半径,自动生成与前后线段相切的圆弧——它不指定圆心,也不直接控制角度。
arc(x, y, radius, startAngle, endAngle, anticlockwise)
这是最常用的圆弧绘制方法,适合明确知道圆心位置的场景(如画饼图、仪表盘、圆形按钮等)。
- x, y:圆弧所在圆的圆心坐标(相对于 canvas 左上角)
- radius:圆的半径,必须 ≥ 0;为 0 时画不出可见弧线
-
startAngle, endAngle:起始角和终止角,单位是弧度(不是度数),从正 x 轴开始逆时针测量
例如:0是 3 点钟方向,Math.PI / 2是 6 点钟方向,Math.PI是 9 点钟方向 -
anticlockwise:布尔值,
false(默认)表示顺时针画弧(视觉上是从 start 到 end 沿较短路径);true表示逆时针画弧
⚠️ 注意:这个参数影响的是“绘图方向”,不是角度正负;即使startAngle > endAngle,设为false仍会顺时针跨越 0 弧度(可能绕一圈)
常见错误:把角度当度数传,比如写 arc(100,100,50,0,90,false) —— 这实际画的是从 0 弧度到 90 弧度(约 5157°),几乎绕满整个圆。正确写法应是 0 到 Math.PI/2。
arcTo(x1, y1, x2, y2, radius)
这个方法不画独立圆弧,而是补在线段之间,用来实现“圆角连接”——比如画带圆角的多边形、平滑拐弯的路径、按钮外轮廓等。它依赖当前路径的最后一个点(即“起点”)。
- 调用前必须已有路径起点(通常由
moveTo()或前一个lineTo()设定) - (x1, y1):第一条切线的终点(即“拐角前”的端点)
- (x2, y2):第二条切线的终点(即“拐角后”的端点)
- radius:圆弧半径;若大于两线段夹角所能容纳的最大圆角,浏览器会自动降级为最大可行半径(即取夹角内切圆半径)
执行过程:Canvas 自动找出一条与线段 A(起点→x1,y1)和线段 B(x1,y1→x2,y2)都相切、且半径为 radius 的圆弧,并将该圆弧追加到当前路径中。圆弧起点是线段 A 的切点,终点是线段 B 的切点——你无法直接控制这两个点坐标,它们由几何关系唯一确定。
示例:画一个右下角带圆角的矩形,可这样写:
ctx.beginPath(); ctx.moveTo(10, 10); ctx.lineTo(190, 10); // 上边 ctx.lineTo(190, 90); // 右边(到拐角前一点) ctx.arcTo(200, 90, 200, 100, 10); // 从 (190,90) 切向 (200,90),再切向 (200,100),半径 10 ctx.lineTo(10, 100); // 下边 ctx.closePath();
如何选择用哪个?
- 要画一个完整扇形、环形、或已知圆心的局部圆?→ 用
arc() - 要给折线路径加圆角,让转折平滑自然?→ 用
arcTo()(注意它必须接在已有线段后) - 想精确控制圆弧起止点坐标?→
arc()更直观;arcTo()的起止点是计算出来的,不可直接指定 - 需要动态适配不同夹角的圆角(如响应式 UI)?→
arcTo()会自动处理极限情况(半径过大时降级),更鲁棒
小贴士:调试技巧
- 画
arc()前,可用ctx.fillRect(x-2, y-2, 4, 4)标出圆心,方便对齐 - 画
arcTo()时,临时用ctx.lineTo(x1,y1); ctx.lineTo(x2,y2)把辅助线画出来,看清切线走向 - 所有角度务必用
Math.PI * degrees / 180转换,或封装一个deg2rad = d => d * Math.PI / 180 -
arcTo()在radius = 0时退化为直线(即画一条从当前点到(x2,y2)的线),可作兼容处理
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










