根本原因是uni.canvasToTempFilePath必须在canvas绘制完成回调中调用,而非drawImage后立即执行;H5端需用toDataURL替代,真机需限制canvas尺寸、适配dpr、预加载图片并分层绘制。
uni-app 里 canvas 转图片失败:drawImage 不生效或生成空白图
根本原因不是代码没写,而是 uni.canvastotempfilepath 必须在 canvas 绘制完成的回调里调用——很多人直接写在 drawimage 后面,但 canvas 渲染是异步的。
- 必须用
uni.createCanvasContext获取上下文,并确保传入正确的canvasId和当前页面实例(this) - 绘制完成后不能立刻转图,得等
ctx.draw(false, () => { ... })的回调执行完再调uni.canvasToTempFilePath - H5 端不支持
canvasToTempFilePath,需用canvas.toDataURL()替代,且要手动处理 base64 前缀和跨域图片(如远程头像) - 真机调试时,安卓部分机型对 canvas 宽高超过 2000px 会截断或报错,建议限制最大尺寸为
1242px(iPhone 宽度)
uni-app 图片合成时文字换行、字体模糊、中文不显示
canvas 上绘文字最常踩的坑是字体加载不可控 + 尺寸单位混乱。uni-app 的 canvas 不支持 CSS 字体栈,也不能用 font-family: "PingFang SC" 这类写法。
- 文字必须用系统默认字体(iOS 是
"sans-serif",Android 多为"Droid Sans"),不能指定中文字体文件 - 换行得自己切字符串 + 循环
fillText,别指望ctx.textWrap(不存在) - 字号写
14px没用,canvas 的fontSize只接受纯数字(单位是 px,但不带单位字符串),应写成ctx.setFontSize(14) - 字体模糊通常是因为 canvas 像素比(dpr)没适配:用
uni.getSystemInfoSync().pixelRatio放大 canvas 宽高,再用 CSS 缩小 canvas 元素本身
分享海报到微信失败:saveImageToPhotosAlbum 被拒绝或无响应
不是权限没申请,而是 iOS 和 Android 对「保存图片」的触发时机要求极严:必须由用户手势(如 button 的 click)直接触发,不能套在 promise.then 或 setTimeout 里。
- 调用
uni.saveImageToPhotosAlbum前,必须确保图片路径是本地临时路径(tempFilePath),不能是网络地址或 base64 - iOS 需提前在
manifest.json → App iOS 设置 → 相册权限打开「相册访问」,否则静默失败 - 微信内嵌浏览器(包括微信小程序环境)不支持
saveImageToPhotosAlbum,此时只能引导用户长按图片保存,或跳转到 H5 页面用canvas.toDataURL+a[download](仅 Safari 支持) - 安卓部分厂商(如华为、小米)会拦截非用户主动点击的保存行为,建议加一层确认弹窗,按钮绑定
@click而非@tap
uni-app 海报生成性能差:滚动卡顿、多次生成变慢
每次生成海报都重新创建 canvas + 绘制全部内容,尤其含多张网络图时,IO 和解码开销会累积。关键不是优化单次绘制,而是复用和缓存。
- 避免重复创建 context:把
uni.createCanvasContext实例缓存为 data 属性,重绘前先clearRect - 网络图片必须预加载:用
uni.downloadFile把头像、背景图提前下到本地临时路径,再传给drawImage,别直接传 url - 复杂海报建议分层绘制:背景层、文字层、二维码层分别用不同 canvas,最后合并(用
drawImage把其他 canvas 当图片画进来) - 频繁生成场景(如用户改昵称实时预览),只重绘变化区域,比如只清空文字区域再重写,而非整屏重绘










