小程序Canvas导出图片模糊主因是未适配devicePixelRatio:需用pixelRatio放大canvas DOM宽高并调用ctx.scale(dpr,dpr),drawImage须用本地路径,canvasToTempFilePath导出时必须显式传入destWidth/destHeight等参数。

小程序端Canvas导出图片模糊,90%是因为没处理devicePixelRatio——不是图片源问题,也不是uni-app bug,而是你画布的物理像素数不够。
canvas.width/height属性必须乘dpr,不能只改CSS
很多人只写了:style="{ width: '750rpx', height: '1000rpx' }',这仅控制显示大小,不改变绘图缓冲区分辨率。Canvas实际绘制区域仍是逻辑尺寸(比如750×1000),在iPhone上会被拉伸到1500×2000物理像素,导致插值模糊。
- 先用
uni.getSystemInfoSync().pixelRatio拿到设备dpr(iOS常为2或3,安卓部分机型为3.5) - 用
uni.createSelectorQuery()拿到canvas节点,再设node.width = 750 * dpr、node.height = 1000 * dpr(注意:是DOM属性,不是style) - 千万别漏掉
ctx.scale(dpr, dpr)——它让后续所有坐标、字号、线宽按逻辑尺寸写,不用手动乘dpr
drawImage加载远程图必须走本地路径
直接ctx.drawImage('https://xxx.png', ...)会触发CORS,且iOS WebView可能对网络图做降采样。即使dpr设对了,图源本身就被压缩过,再放大也糊。
- 改用
uni.downloadFile下载到tempFilePath,再传给uni.getImageInfo -
getImageInfo返回的width/height是原始像素值,绘图时按比例缩放:比如目标区域宽300rpx,图源宽1200px,那scaleX = 300 * dpr / 1200 - 避免用
base64字符串传图——解码损耗+内存压力大,真机易卡顿或崩溃
uni.canvasToTempFilePath必须传全参数
导出时没指定width/height,微信会按canvas元素的CSS宽高生成图片,而不是你设的物理像素尺寸——结果就是把1500×2000的图硬压成750×1000,细节全丢。
- 导出时显式传
{ width: 750 * dpr, height: 1000 * dpr, canvasId: 'myCanvas', destWidth: 750 * dpr, destHeight: 1000 * dpr } -
destWidth/destHeight决定输出图的像素尺寸,width/height决定裁剪区域(若不填则全图) - 小程序平台必须填
canvasId,H5端可为空;App端需确认是否启用type='2d'上下文(iOS某些版本webgl不稳定)
最容易被忽略的一点:canvas尺寸变化后(比如横竖屏切换),必须重新设置node.width/node.height并重置ctx.scale——否则第二次绘制就直接糊了。别指望一次初始化能管全程。


















