必须监听touchstart、touchmove、touchend三类事件,因移动端浏览器会拦截mousedown等鼠标事件以实现滚动或缩放,导致签名轨迹断连或无响应。

canvas 电子签名必须监听哪几类事件
只监听 mousedown/mousemove/mouseup 会导致移动端完全无法签名。必须同时适配触控事件,否则在 iPhone、Android 平板上点不动、划不了。
正确做法是用特征检测判断设备能力,而不是 UA 判断:
-
touchstart替代mousedown(注意:需调用e.preventDefault()阻止页面滚动) -
touchmove替代mousemove(取e.touches[0],不是e.changedTouches[0]) -
touchend替代mouseup - PC 和移动端共用同一套坐标转换逻辑,避免重复写两套
getPosition
为什么签名线总是断开或抖动
根本原因是没处理好路径连续性:每次 mousemove 或 touchmove 都调用 ctx.beginPath(),等于每画一笔就新建一条路径,导致线条不连贯、锯齿严重。
关键修复点:
立即学习“前端免费学习笔记(深入)”;
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
- 只在
startDrawing里调一次ctx.beginPath()和ctx.moveTo() -
draw函数中只调ctx.lineTo()+ctx.stroke(),不要重复beginPath - 设置
ctx.lineCap = 'round'和ctx.lineJoin = 'round',否则转角生硬、末端露尖 - 移动端高频触控下,
touchmove触发太密,可加 10–16ms 节流(但别用setTimeout堆队列,直接用requestAnimationFrame)
导出签名图片时空白或尺寸错乱
canvas.toDataURL('image/png') 返回空图或模糊,90% 是因为 canvas 的像素尺寸和 CSS 显示尺寸不一致。浏览器渲染时会自动缩放,但 toDataURL 读的是原始像素缓冲区。
典型错误写法:<canvas width="300" height="200" style="width:100%;max-width:400px;">
正确做法:
- canvas 的
width和height属性必须设为实际绘制分辨率(比如 600×400) - 用 CSS 控制显示大小:
style="width:100%;height:auto;",再配合transform: scale(0.5)缩放显示(保持清晰度) - 导出前确保已清空背景:
ctx.fillStyle = '#fff'; ctx.fillRect(0, 0, canvas.width, canvas.height); - 若要高清输出,可按设备像素比放大 canvas 尺寸,再用
ctx.scale(dpr, dpr)缩放绘图坐标
签名清除后再次绘制出现残留
不是没清画布,而是没重置绘图状态。常见残留包括:上次的 lineWidth、strokeStyle、甚至未闭合的路径影响后续 stroke() 行为。
安全清除方式分两层:
- 视觉清除:
ctx.clearRect(0, 0, canvas.width, canvas.height) - 状态重置:
ctx.beginPath()、重设strokeStyle、lineWidth等关键属性(不能只靠 clearRect) - 如果用了离屏 canvas 做缓存,记得同步清掉缓存 canvas
- 务必把
isDrawing = false放在清除逻辑末尾,否则用户点一下就又开始画了


















