最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
uni-app解决小程序端Canvas绘制在iOS端显示模糊Bug的方法
时间:2026-07-13 11:54:45 编辑:袖梨 来源:一聚教程网
iOS真机Canvas发虚是因pixelRatio为3时未适配物理像素:需同时设置canvas.width/height为逻辑尺寸×dpr,并调用ctx.scale(dpr,dpr),再配合CSS固定显示尺寸,缺一不可。
为什么iOS真机上Canvas总是发虚,而开发者工具不报错?
因为微信小程序在iOS端的Canvas渲染管线对dpr更敏感,且不自动做像素对齐。开发者工具用的是Mac桌面WebView模拟,pixelRatio固定为1或2,而真实iPhone(尤其是12/13/14系列)的pixelRatio是3,但canvas若仍按375×667逻辑尺寸初始化,就会被强制拉伸——不是“画得糊”,是“画得少,再被撑大”。
必须同时改 canvas.width/height 和 ctx.scale(),缺一不可
只调ctx.scale(dpr, dpr)不行,只改CSS宽高也不行。关键点在于:canvas元素的width和height属性决定绘图缓冲区物理像素数,CSS控制显示大小,两者必须按比例匹配。
-
canvas.width = 375 * dpr、canvas.height = 667 * dpr(以设计稿375px宽为例) - 紧接着调用
ctx.scale(dpr, dpr),让后续所有坐标、字号、线宽都按逻辑尺寸写(比如fillText('hello', 20, 30)不用乘dpr) - Canvas组件的
:style里仍设width: '375px'; height: '667px',保持布局不变
onReady里拿不到canvas节点?用createSelectorQuery异步查
uni-app中this.$refs.canvas在iOS真机上常为null,尤其配合v-if或条件渲染时。必须用uni.createSelectorQuery()主动查询,且要等exec回调返回node才安全。
- 别在
mounted里直接uni.createCanvasContext,此时DOM还没就绪 - 正确时机是
onReady钩子 +createSelectorQuery().select('#myCanvas').fields({ node: true }).exec() - 拿到
res[0].node后,再调node.getContext('2d')(注意:uni-app里推荐用uni.createCanvasContext,但需传入该node)
drawImage加载图片仍模糊?先下载再绘,绕过跨域和降采样
iOS WebView对远程drawImage('https://...')有双重限制:一是CORS拦截导致空白,二是自动降采样(尤其带orientation的JPEG),哪怕原图是@3x也会被压成模糊块。
- 必须走
uni.downloadFile→uni.getImageInfo→ctx.drawImage三步链 -
getImageInfo返回的width/height是原始物理像素,绘图时要除以dpr换算成逻辑尺寸(否则会超框) - 如果水印文字仍毛边,加一句
ctx.imageSmoothingEnabled = false关掉插值,细线和小字立刻锐利
最易被忽略的是:每次重绘前都要重新scale,不能只在初始化时调一次;还有就是canvas.width/height设完后,务必确认它没被其他样式或父容器约束覆盖——iOS对flex容器里的canvas尺寸计算特别脆弱。