用CanvasRenderingContext2D.arc()画笑脸最稳,关键在于精准控制四段圆弧:左右眼、上半脸(0到π)、嘴(π到2π,圆心下移15–25px),每段前必调beginPath()并及时stroke(),避免路径粘连;注意canvas像素比与CSS缩放匹配,嘴弧方向由角度范围和anticlockwise=false共同决定。

用 CanvasRenderingContext2D.arc() 画笑脸弧线最稳
HTML5 画笑脸,核心不是“画脸”,而是精准控制四段圆弧:左右眼、上半脸、嘴。所有弧线都得靠 arc(),别想用 bezierCurveTo() 模拟——它难控、易变形、上下嘴不对称。
关键参数只有三个要盯死:x、y(圆心)、radius(半径),而 startAngle 和 endAngle 决定哪一段被画出来。比如上半张脸是 0 到 π 的上半圆,嘴是 π 到 2π 的下半圆但只取中间一段。
-
arc(x, y, radius, startAngle, endAngle, anticlockwise)的角度单位永远是弧度,别传90,要传Math.PI / 2 - 嘴的弧线圆心必须略低于脸的圆心(通常下移 15–25px),否则会像没表情的球
- 眼睛不是实心圆,是小弧线:用
arc()画短弧(如0.2 * Math.PI到0.8 * Math.PI),再stroke(),别fill()
ctx.beginPath() 忘了调,弧线会连成一团乱线
这是新手最高频的“画不出来”原因:所有 arc() 都默认追加到当前路径。不手动切开,左眼、右眼、脸、嘴就全粘在一起,变成一条诡异的连续曲线。
- 每画一个独立弧线前,必须先调一次
beginPath() - 画完一个部件(比如左眼)后,立刻
stroke()或fill(),别攒着一起画 - 别在
beginPath()前调moveTo()——arc()自带起点,moveTo()反而会多出一条线头
笑脸比例崩坏?检查 canvas 像素比和 CSS 缩放
用 定义的是绘图表面像素数;如果用 CSS(比如 style="width: 400px; height: 400px;")强行拉伸,所有弧线会变扁——因为 canvas 内部还是 200×200,只是被浏览器“压扁显示”了。
立即学习“前端免费学习笔记(深入)”;
- 要么去掉 CSS 宽高,让 canvas 按原像素渲染
- 要么同步改
width和height属性值,比如canvas.width = 400; canvas.height = 400; - 高 DPI 屏幕下,可检测
window.devicePixelRatio并缩放 canvas 内部尺寸,但对笑脸这种简单图形,通常没必要
嘴型翻车?起始/结束角度顺序和方向别搞反
嘴是向下凹的弧线,但很多人画出来是向上凸的——问题出在 anticlockwise 参数和角度顺序。默认顺时针画,从 π 到 1.5π 是右下角一小段,不是嘴;要画开口向下的嘴,得从 π 画到 2π,且保持顺时针(false)。
- 正确嘴弧:圆心
(cx, cy + 20),半径r * 0.6,startAngle = Math.PI,endAngle = 2 * Math.PI,anticlockwise = false - 如果传
anticlockwise = true,同样角度范围会画出反向弧(向上凸) - 别用
0到Math.PI画嘴——那是上半圆,会变成“倒笑脸”
弧线本身没“表情”,表情来自各部件的相对位置和开口朝向。调嘴的时候,宁可把圆心往下多移 5px,也别硬调角度去凑形状。










