调用 uni.canvasToTempFilePath 返回空路径或报错“canvas is empty”的最常见原因是未在 ctx.draw() 的回调中执行该方法,因 canvas 渲染异步,必须等待绘制完成;需确保 canvasId 与模板一致、自定义组件中传入 this 实例;destWidth/destHeight 控制输出尺寸,quality 控制 JPG 质量;H5 返回 base64 字符串而非文件路径;跨平台时需注意图片加载方式差异。

直接调用 uni.canvasToTempFilePath 即可,但必须确保 canvas 已完成绘制,且传参正确——否则返回空路径或报错“canvas is empty”。
为什么调用后 tempFilePath 是空或报错?
最常见原因是:在 ctx.draw() 的绘制逻辑还没真正完成时就执行了 uni.canvasToTempFilePath。微信小程序的 canvas 渲染是异步的,ctx.draw(false, callback) 中的 callback 才是安全时机。
- ❌ 错误写法:
ctx.draw(); uni.canvasToTempFilePath({...})—— 没等绘制结束就导出 - ✅ 正确写法:必须把
uni.canvasToTempFilePath放进ctx.draw的回调里 - ⚠️ 注意:即使用了
setTimeout延迟,也不如draw回调可靠,因为不同设备绘制耗时不确定
canvasId 和组件实例参数怎么传?
canvasId 必须和模板中 的值完全一致(注意不是 id)。在自定义组件内调用时,第二个参数必须传入当前组件实例 this,否则找不到画布。
- 页面中调用:
uni.canvasToTempFilePath({ canvasId: 'myCanvas' }, this) - 自定义组件中调用:
uni.canvasToTempFilePath({ canvasId: 'myCanvas' }, this)—— 缺少this会导致失败(尤其在 H5 或某些小程序平台) - 支付宝小程序例外:它用的是
id属性而非canvas-id,需按平台条件判断
导出图片尺寸和质量怎么控制?
默认输出尺寸会乘以屏幕像素密度(dpr),导致高分屏下图片过大。用 destWidth 和 destHeight 可强制指定目标分辨率;quality 控制 JPG 压缩质量(仅对 fileType: 'jpg' 生效)。
- 导出 750rpx 宽的 PNG:
destWidth: 750, fileType: 'png' - 导出 1242×2208 的 JPG(高质量):
destWidth: 1242, destHeight: 2208, fileType: 'jpg', quality: 0.95 - 不设
destWidth/destHeight时,实际尺寸 =(width - x) * dpr,iOS 真机 dpr 常为 3,易超 2MB 限制
H5 平台下 tempFilePath 是 base64?
是的。H5 不生成真实文件路径,res.tempFilePath 返回的是 data:image/png;base64,... 字符串。若后续要上传或预览,需统一处理:
- 上传前:检查是否以
data:开头,是则直接作为file内容体发送(如用uni.uploadFile的filePath参数会失败,得改用formData) - 预览:H5 可直接赋给
;小程序端才能用uni.previewImage - 别硬套同一套逻辑——跨平台时务必用
uni.getSystemInfoSync().platform分支处理
真正容易被忽略的点是:canvas 绘制内容本身是否支持跨平台。比如你用 ctx.drawImage 加载网络图片,在微信小程序需先 uni.downloadFile 转成本地临时路径;而 H5 直接支持 HTTP 地址。这个环节出错,canvasToTempFilePath 就永远拿不到有效图像。











