canvas电子签名平滑笔迹的核心是用贝塞尔曲线拟合轨迹并合理采样插值:以相邻点中点为控制点调用quadraticcurveto,配合距离阈值去抖与线性插值提升密度。

Canvas 实现电子签名平滑笔迹,核心不是“画得快”,而是**用贝塞尔曲线拟合用户移动轨迹,同时合理采样、插值和抗锯齿**。直接用 lineTo 连接每个鼠标/触摸点,会因采样率高、抖动大而出现毛刺、断续或锯齿感。
用二次贝塞尔曲线替代直线段
人手移动天然带弧度,直线硬连每个点(尤其快速签名时)会产生大量小折角。改用 quadraticCurveTo(cpX, cpY, endX, endY),以当前点为起点、上一点与当前点中点为控制点、当前点为终点,能自然“圆滑”轨迹。
- 记录所有触摸/鼠标坐标点(
points = []) - 每新增一个点
p,取前一个点prev和p的中点作为控制点:cp = {x: (prev.x + p.x)/2, y: (prev.y + p.y)/2} - 调用
ctx.quadraticCurveTo(cp.x, cp.y, p.x, p.y),而非lineTo(p.x, p.y)
做轻量级轨迹降噪与插值
手指/触控笔存在微抖,原始点列含高频噪声。不建议暴力滤波丢点(易失真),推荐“动态合并+线性插值”:
- 只在两点距离 > 2px 时才记录新点(跳过微抖)
- 绘制前,对已有点列做一次线性插值:在每两个相邻点之间插入一个中点,再用贝塞尔重绘——相当于提升采样密度,让曲线更顺滑
- 例如:
smoothed = []; points.forEach((p, i) => { smoothed.push(p); if (i
开启抗锯齿并优化线宽与端点样式
Canvas 默认开启抗锯齿(ctx.imageSmoothingEnabled = true),但需确保没被意外关闭;同时配合视觉优化:
- 设置
ctx.lineCap = 'round'和ctx.lineJoin = 'round',避免转角生硬 - 线宽建议 ≥ 2px(如 2.5 或 3),太细放大后锯齿明显,太粗失真
- 启用高DPI适配:按设备像素比缩放 canvas,再用 CSS 缩回,保证清晰度(否则在 Retina 屏上模糊)
触摸场景下优先使用 touchstart/move/end 并禁用默认行为
移动端 touch 事件比 mouse 更精准、延迟更低。务必:
- 监听
touchstart、touchmove(阻止e.preventDefault()防止页面滚动) - 从
e.touches[0]取坐标,而非e.changedTouches[0](后者可能漏点) - 在
touchend后清空当前笔画缓存,准备下一笔
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











