必须用pointerdown/pointermove/pointerup事件捕获轨迹,设touch-action:none防滚动,调用preventDefault()防菜单;用devicePixelRatio适配高DPI,重设canvas宽高并scale缩放;导出用toBlob避免IE11兼容问题,撤销通过存储路径点实现。

怎么用 canvas 捕获真实手写轨迹
直接监听 mousedown/mousemove/mouseup 会丢笔画、断连,尤其在触屏设备上。必须用 pointerdown/pointermove/pointerup,并开启 touch-action: none 阻止浏览器默认滚动行为。
实操建议:
- 给
设置style="touch-action: none;",否则 iOS Safari 会拦截pointermove - 在
pointerdown中调用event.preventDefault(),防止长按唤出菜单 - 用
ctx.lineCap = 'round'和ctx.lineJoin = 'round'让笔画两端圆润,避免生硬折角 - 记录每段轨迹的
timestamp,后续可做压感模拟或平滑插值
canvas 绘制时为什么线条发虚、边缘锯齿
根本原因是 canvas 像素比(devicePixelRatio)没对齐。浏览器渲染 canvas 时若未按物理像素缩放,就会模糊。
实操建议:
- 获取
window.devicePixelRatio,重设canvas.width和canvas.height为逻辑尺寸 × DPR - 用
ctx.scale(dpr, dpr)缩放绘图上下文,让所有坐标保持逻辑单位 - 别用 CSS width/height 缩放 canvas,那只是拉伸位图,不是高清渲染
- 示例关键代码:
const dpr = window.devicePixelRatio || 1;<br>canvas.width = canvas.clientWidth * dpr;<br>canvas.height = canvas.clientHeight * dpr;<br>ctx.scale(dpr, dpr);
签名后怎么导出清晰 PNG 且兼容 IE11
canvas.toDataURL('image/png') 在 IE11 下不支持高 DPI 导出,且默认压缩质量不可控;更严重的是,若 canvas 内容含跨域图片(比如水印),会触发 SecurityError 导致导出失败。
实操建议:
- 导出前检查
canvas.toBlob是否存在,IE11 不支持,需 fallback 到canvas.msToBlob() - 避免在 canvas 上 drawImage 跨域资源;如必须,加
crossOrigin="anonymous"并确保服务端返回 CORS 头 - 导出 PNG 时不要依赖默认质量参数(它只对 JPEG 有效),PNG 始终无损
- 生成下载链接推荐用
URL.createObjectURL(blob),比 data URL 更省内存,尤其大签名图
清空画布后为什么还能“撤销”——如何实现简易历史栈
canvas 本身不保存绘制历史,clearRect() 是彻底擦除。所谓“撤销”,其实是把每次笔画存成路径数组,再逐条重绘。
实操建议:
- 每次
pointerdown → pointerup形成一个stroke对象,含 points 数组和 lineWidth/color 等元数据 - 用
Array.push()存入historyStack,historyStack.pop()即撤销最后一步 - 撤销后调用
ctx.clearRect(0, 0, canvas.width, canvas.height),再遍历剩余 history 重绘 - 注意:别存整帧图像(如 toDataURL),内存爆炸;路径点数据轻量得多
实际项目里最容易被忽略的是 devicePixelRatio 的动态适配——用户旋转 iPad 或缩放页面时,DPR 可能变化,但 canvas 尺寸不会自动更新。得监听 resize 和 orientationchange,重新计算并清空重绘。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











