uni.canvastotempfilepath 导出需满足三前提:canvas 渲染完成、canvas-id 严格匹配、参数必含 canvasid;uni.createcanvascontext 是唯一合法入口,因 为 native 节点,非 dom 元素。

直接用 uni.canvasToTempFilePath 就能导出,但必须满足三个前提:canvas 已渲染完成、canvas-id 严格匹配、参数里不能漏掉 canvasId 字段——漏一个,真机就返回 “canvas not found” 或静默失败。
为什么 uni.createCanvasContext 是唯一入口
uni-app 的 <canvas></canvas> 不是 DOM 元素,而是 native 渲染节点。你写 document.getElementById('myCanvas') 拿不到实例,调 getContext('2d') 在小程序和 App 端直接报错或白屏。H5 端虽可能“看起来能用”,但混用会导致多端行为不一致。
正确做法是:
- 模板中声明
<canvas canvas-id="myCanvas"></canvas>,注意canvas-id必须纯字母数字,不能含横线、下划线等(iOS 小程序会静默失败) -
onReady钩子内调用uni.createCanvasContext('myCanvas', this),第二个参数必须传当前 Vue 实例(Vue3 中是getCurrentInstance()或 setup 里的proxy) - 别在
onLoad或created里创建 context——某些平台(如微信小程序真机)此时 canvas 节点还没挂载,context 为空
canvasToTempFilePath 必传且易错的参数
这个 API 不是“调了就出图”,它依赖 canvas 当前帧状态,且字段缺失会直接失败:
-
canvasId必须显式传,且值要和模板中canvas-id完全一致(大小写敏感) -
width和height建议显式指定(单位 px),不要依赖样式宽高——安卓部分机型会按 CSS 像素截取,导致模糊或裁切 -
tempFilePath只在success回调里有效,别在回调外打印或赋值,此时还是undefined - H5 端若需 fallback,可加判断:
if (uni.getSystemInfoSync().platform === 'h5') { /* 用 html2canvas */ },但不建议长期混用
图片加载和像素比适配是清晰度关键
网络图片没加载完就 drawImage,结果是空白;字体写死 14px,在 iPhone 上细得看不见——这些不是 bug,是跨端默认行为差异。
- 网络图必须预加载:
uni.getImageInfo({ src: url })成功后再ctx.drawImage(res.path, ...) - 统一按设备像素比缩放画布:用
uni.getSystemInfoSync().pixelRatio获取实际倍率,把设计稿尺寸 × p 后传给canvas宽高和canvasToTempFilePath的width/height - 文字字号也建议乘以 pixelRatio,比如设计稿 28px → 实际设为
ctx.setFontSize(28 * p) - 导出前务必调
ctx.draw(true, callback),true表示同步绘制,避免异步时机问题
最常被忽略的是:canvas 元素本身要 visible(哪怕用 position: fixed; top: -9999px 移出视口),不能设 display: none 或 visibility: hidden——某些安卓机型会跳过渲染,导致导出黑图或空图。











