uni-app 中 canvas 需用 uni.createCanvasContext('canvas-id') 获取上下文,不可用 getContext('2d');签名需缓存坐标点、换算 pixelRatio、动态缩放校准,并用 canvasToTempFilePath 导出。
canvas 在 uni-app 里不能直接用 getContext('2d')
uni-app 的 canvas 是组件化封装的,不是原生 dom canvas,所以你写 document.getelementbyid('mycanvas').getcontext('2d') 会报错或返回 null。真机和 h5 都一样——它压根没挂载到 document 上。
必须用 uni.createCanvasContext,且传入的是 canvas 组件的 canvas-id(不是 id 或 ref),同时要等组件渲染完成再调用。
- 确保
<canvas canvas-id="signCanvas" />写在模板里,canvas-id必须是字符串,不能带变量或空格 - 在
onReady或nextTick后创建 context,不要在onLoad就调 - H5 平台下如果用了
type="2d",context 创建方式不同(需用uni.createSelectorQuery),但签名场景推荐统一用默认 2D 模式 +canvas-id
签名轨迹怎么存、怎么清、怎么导出图片
签名本质是记录 touchmove 坐标点序列,不是实时绘图到 canvas 上——否则缩放、横竖屏切换时坐标会错乱。得先缓存点,再批量重绘;导出时也得靠 canvasToTempFilePath,不能用 toDataURL。
- 用数组存每条笔画:例如
[[{x:10,y:20}, {x:15,y:25}], [{x:30,y:40}]],每次touchstart开新数组,touchmovepush 点 - 清空画布别用
clearRect(不生效),而是重置点数组 + 调用一次重绘函数 - 导出前务必先调
drawCanvas强制绘制,否则canvasToTempFilePath返回空白图;H5 下还要注意域名白名单和 HTTPS -
canvasToTempFilePath的canvasId必须和模板中一致,且不能漏传success回调——失败时不报错,只静默返回空路径
真机上签名偏移、点不准、断笔严重
这是最常踩的坑:uni-app 的 touch 事件坐标是屏幕坐标,而 canvas 坐标系受设备像素比(pixelRatio)、缩放、自定义宽高影响。直接用 e.touches[0].x 会偏移几十像素。
- 必须用
uni.getSystemInfoSync().pixelRatio换算:原始坐标 ÷ pixelRatio 才是 canvas 内部坐标 - canvas 组件设了
width/height属性?那它实际渲染尺寸可能被拉伸,要用getBoundingClientRect动态算缩放系数(H5);App 端建议固定宽高,不用百分比 - 避免高频 touchmove 触发太多点,加个距离阈值(比如两点距离
- App 端 iOS 对 touchstart/touchend 响应慢,可改用
bind:touchstart+catchtouchmove防止事件冒泡干扰
签名板适配暗色模式、低性能机型、微信小程序
canvas 渲染本身不感知系统主题,但线条颜色、背景色得手动判断;低端安卓机上连续重绘易卡顿;微信小程序对 canvas-id 和文件导出有额外限制。
- 背景别用纯白:
fillStyle = '#ffffff'在暗色模式下刺眼,改成fillStyle = 'rgba(255,255,255,0.9)'更柔和 - 低端机上减少重绘频率:把连续 5~8 个点合并成一条 lineTo,而不是每个点都 stroke
- 微信小程序要求
canvas-id全局唯一,且不能动态修改;导出图片前必须确保 canvas 已显示(display: block),隐藏状态下调用canvasToTempFilePath会失败 - App 端如果签名后图片模糊,检查是否忘了乘
pixelRatio设置 canvas 的width和height属性(例如:实际宽高 = 设计宽高 × pixelRatio)
canvas-id 不是万能钥匙,点坐标不换算、导出不等绘制完成、真机不测 touch 偏移——这三处一错,签名就废一半。










