一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

uni-app实现电子签名画布 uni-app用canvas导出图片

时间:2026-06-15 09:47:52 编辑:袖梨 来源:一聚教程网

Canvas签名不响应触摸事件,主因是未正确绑定事件或未设宽高;图片模糊因未适配dpr;导出失败因上下文不匹配或绘制未完成;背景异常因未清空填充。

uni-app里Canvas画布签名不响应触摸事件

真机调试时签名区域完全没反应,或者只在部分区域生效——大概率是 canvas 组件没正确绑定触摸事件或未设置宽高。uni-app 的 canvas(尤其是 2D 上下文)在不同平台行为差异大,H5 和小程序对 touchstart/touchmove 的处理逻辑也不同。

实操建议:

  • 必须用 canvas-id + type="2d" 声明 canvas,并在 onReady 后通过 uni.createCanvasContext 获取上下文,不要用 querySelector 或直接操作 DOM
  • H5 端需手动监听 touchstart/touchmove 事件并调用 ctx.moveTo/ctx.lineTo;小程序端可直接用 bindtouchstart/bindtouchmove 属性,但要确保事件对象里能拿到 touches[0].x/y
  • canvas 宽高必须用 rpx 或 px 显式设置,不能靠父容器撑开;同时在 style 中加 touch-action: none 防止 iOS Safari 默认滚动拦截

导出的签名图片模糊、边缘锯齿严重

导出的 PNG 图片在手机上看起来发虚、线条断续,不是因为分辨率低,而是 canvas 像素比(dpr)没适配。uni-app 的 canvas 默认以 1:1 渲染,而 iPhone 和安卓高端机 dpr 多为 2 或 3,导致绘制点被拉伸模糊。

实操建议:

  • 创建 canvas 上下文前,先用 uni.getSystemInfoSync().pixelRatio 获取设备 dpr,再将 canvas 的 widthheight 属性设为「设计宽高 × dpr」,同时用 CSS 将 canvas 样式宽高设为原始设计尺寸(如 375×200px)
  • 绘图前调用 ctx.scale(dpr, dpr),让所有坐标和线宽自动按比例缩放
  • 避免使用 ctx.lineWidth = 1 这类固定值,应设为 1 / dpr,否则高 dpr 下线条会过粗

uni.canvasToTempFilePath 导出失败或返回空路径

调用 uni.canvasToTempFilePath 后回调不触发、报错 canvas is not found,或生成的临时文件路径为空——这是最常踩的坑,核心原因是 canvas 实例与导出 API 不在同一上下文,或 canvas 尚未完成绘制就调用了导出。

实操建议:

  • 必须等 canvas 内容绘制完毕(比如最后一次 ctx.stroke() 执行完),再调用 uni.canvasToTempFilePath;可在 setTimeout 中延后 16ms(一帧)再执行,避免渲染队列未 flush
  • 小程序端务必传入 canvasId 和当前页面的 this 实例(即 success 回调里的 res.tempFilePath 才有效),H5 端则要用 canvas.toDataURL('image/png') 替代
  • 导出前检查 canvas 是否已挂载:uni.createSelectorQuery().select('#myCanvas').fields({ node: true, size: true }),确保 node 存在且 width/height > 0

签名图片导出后背景为黑色或透明异常

导出的图片本该是白底黑线,结果全是黑底,或关键线条消失——这是因为 canvas 默认背景透明,而某些平台(尤其 Android 微信)在导出时把 alpha 通道当成了黑底合成。

实操建议:

  • 绘制前先清空画布并填充白色:ctx.fillStyle = '#ffffff'; ctx.fillRect(0, 0, width, height);,注意这个 width/height 是 canvas 元素的逻辑宽高(非像素宽高)
  • 如果需要透明背景,导出前不要 fill,但得确认目标平台支持 PNG alpha;微信小程序中,canvasToTempFilePathfileType 必须显式设为 'png',jpg 不支持透明
  • 导出后若仍异常,可用 uni.getImageInfo 检查临时文件是否加载成功,再用 uni.uploadFile 上传前做一次校验

真正麻烦的是多端 dpr 适配和 canvas 生命周期管理——很多问题不是代码写错了,而是 canvas 被重建了两次,或者导出时机卡在 draw call 还没提交到 GPU。动手前先 console.log 出 dpr、canvas node、ctx 对象,比盲调快得多。

热门栏目