ios小程序canvas文字居中失效是因渲染层未做dpr校正,需显式设置canvas宽高并scale适配:先用selectquery获取真实尺寸×dpr赋值给width/height属性,再ctx.scale(dpr,dpr),文字坐标须基于缓冲区像素计算,绘制前重置变换矩阵。

iOS端Canvas文字居中失效的典型表现
在微信小程序 iOS 真机上,ctx.setTextAlign('center') + ctx.fillText('文本', x, y) 画出来的文字明显偏左,甚至紧贴 canvas 左边;ctx.textBaseline = 'middle' 也常让文字垂直位置飘高或下沉。这不是 bug,而是 iOS 小程序 Canvas 渲染层对锚点坐标的解析与 Android/H5 不一致导致的——它会把 CSS 像素坐标直接当设备像素用,而没做 DPR 校正。
必须显式设置 canvas 实际宽高而非仅靠 style
很多开发者只写 <canvas style="width: 100%; height: 200px"></canvas>,但 iOS 小程序会把 canvas 的默认 width 和 height 属性(即“绘图缓冲区”)当作 300×150,远小于显示尺寸,导致文字坐标被严重压缩拉伸。
- 务必在
onReady中用uni.createSelectorQuery()获取真实渲染宽高 - 再赋值给 canvas 元素的
width和height属性(不是 style) - 例如:
canvas.width = rect.width * dpr、canvas.height = rect.height * dpr - 之后调用
ctx.scale(dpr, dpr),否则文字会变小或模糊
文字坐标必须基于 canvas 缓冲区像素计算
设定了 canvas.width = 750、canvas.height = 400 后,所有 fillText 的 x 和 y 都要按这个像素范围算,不能套用 CSS 百分比或 rem 值。
- 想让文字水平居中?x 必须是
canvas.width / 2,不是rect.width / 2 - 想垂直居中?y 应为
canvas.height / 2,再配合ctx.textBaseline = 'middle' - 若用了
ctx.scale(dpr, dpr),就不要再把坐标再乘一遍 dpr,否则 double scaling
setTextAlign + fillText 的坐标陷阱
ctx.setTextAlign('center') 只表示“以你传入的 x 为文字水平中心点”,但它不关心你这个 x 是怎么来的。iOS 上常见错误是:
- 用
getBoundingClientRect().left算出的 x 值直接传进去 → 错,这是 CSS 像素,没转设备像素 - canvas 宽高没设、也没 scale,却用
rect.width / 2当 x → 错,坐标系错位 - 写了
ctx.translate()旋转后没ctx.setTransform(1, 0, 0, 1, 0, 0)重置 → 文字跟着整个坐标系偏移
最稳的做法:每次绘制前先 ctx.setTransform(1, 0, 0, 1, 0, 0),再设 textAlign 和 textBaseline,最后传入基于 canvas 缓冲区像素的绝对坐标。











