uni-app中canvas常画不出图,因uni.createCanvasContext返回旧版上下文,不支持网络图片drawImage、createPattern等;需开启系统WebView,图片须转本地路径,安卓设字体大小12–28,drawImage须等图片加载完成,H5查canvas要.in(this),保存海报各端差异大,文字宽度需手动计算。

canvas在uni-app里为什么经常画不出图
因为uni-app的canvas是分“2D”和“WebGL”两种上下文,而多数海报需求用的是uni.createCanvasContext——它返回的是**兼容性受限的旧版 canvas 上下文**,不支持drawImage直接画网络图片、不支持createPattern、甚至fillText中文字体渲染在某些安卓机上会空白。
- 真机调试前务必在
manifest.json里开启「启用系统WebView」(iOS 必开,Android 部分厂商 Webview 也依赖它) - 所有图片必须先用
uni.downloadFile或uni.getFileSystemManager().readFile转成本地临时路径,再传给ctx.drawImage;直接传https://地址会静默失败 - 安卓低端机上
ctx.setFontSize设太大(比如>40)可能导致fillText不显示,建议控制在12–28之间并用ctx.setTextAlign('center')辅助对齐
drawImage加载图片失败的三个典型错误
这是生成海报时最常卡住的环节:调了ctx.drawImage但 canvas 一片空白,控制台也没报错。
-
drawImage第二个参数是x坐标,不是宽高——写成ctx.drawImage(img, 0, 0, 300, 400)是对的,但若漏掉后两个参数(目标宽高),图片可能被缩成一个点或溢出画布 - 图片未加载完成就执行
ctx.draw():必须等uni.getImageInfo或uni.downloadFile的success回调里再调ctx.drawImage,不能靠setTimeout赌时间 - H5端用
uni.createSelectorQuery查不到canvas节点?得加.in(this)并确保组件已挂载,否则fields返回空对象
保存海报到相册的兼容性要点
uni.canvasToTempFilePath在不同平台行为差异极大,不是调了就能存。
- App端(iOS/Android)必须传
canvasId且该canvas元素需在当前页面 DOM 中(不能v-if隐藏,要用v-show或opacity:0) - 微信小程序要求
canvas组件width/height属性值与style里的宽高一致,否则导出图拉伸或裁切 - H5端无法直接保存到相册,只能用
a[href=data:...].download触发下载,且部分浏览器(如iOS Safari)会拦截自动下载,需用户手动点击
字体和文字换行得自己算,别信ctx.measureText
ctx.measureText返回的width在uni-app里基本不准——尤其中文,不同端返回值偏差可达30%。想让一段文案居中、多行、不超宽,必须手动切字+累加宽度。
- 推荐用
uni.getSystemInfoSync().fontSizeSetting获取设备默认字号作基准,再按比例缩放 - 逐字调用
ctx.measureText(char).width太慢,改成预估:汉字按16px字号≈14px宽,英文数字≈8px,空格≈6px,再加2px容差 - 换行逻辑示例:
const words = text.split(''); let line = ''; let lines = []; for (let w of words) { const testLine = line + w; const width = measureWidth(testLine); if (width > maxWidth) { lines.push(line); line = w; } else { line = testLine; } }
真机上测过才知道哪些字体会 fallback 到系统默认黑体,哪些会直接不显示——特别是「思源黑体」「霞鹜文楷」这类自定义字体,在App端要转成base64内联,小程序要提前声明@font-face,H5则要看CDN是否允许跨域。这些细节不提前压测,上线后海报就只剩方框。











