uni-app 无法直接操作 Canvas 像素点,因跨端 CanvasContext 非标准 DOM 实现;水印需分层绘制(drawImage + fillText 等),注意缩放、dpr、导出时机及平台差异。

uni-app 无法直接操作 Canvas 像素点(如 getImageData、putImageData),这不是 bug,而是跨端限制——小程序和 App 端的 CanvasContext 不是标准 DOM Canvas,不暴露像素级 API。想走「读取原图 → 修改像素 → 写回」这条路,在 uni-app 里根本行不通。
uni-app 的 drawImage + fillText 是唯一可行路径
所有水印合成必须基于分层绘制:先用 drawImage 把原始图片画到底层,再用 fillText、drawImage(水印图)、rect+fill 等叠加水印元素。没有中间态像素操作,只有“画布上画什么、在哪画、怎么画”。
- 文字水印靠
fillText,必须提前设置setFontFamily、setFontSize、setFillStyle - 图标水印靠二次
drawImage,源必须是本地临时路径(tempFilePath),网络图需先uni.downloadFile - 半透明背景框要配合
setGlobalAlpha和rect+fill,注意调用顺序:先设透明度 → 画矩形 → 填充 → 恢复透明度再画文字 - 多行文本需手动拆分、逐行
fillText,不能依赖自动换行;measureText返回宽度可用于居中或右对齐计算
iOS 上 canvas 绘制空白?大概率是尺寸越界
iOS WebKit 对单个 Canvas 有硬性限制:最大面积 ≤ 16,777,216 像素(≈4096×4096),且内存按 width × height × 4 字节计算。相机直出图(如 4032×3024)直接塞进去,Canvas 就会静默失败,返回空白。
- 必须缩放:取
Math.min(1440 / width, 1440 / height, 1)得缩放比,再算新宽高 - canvas 元素的
width/height属性必须设为物理像素(resizedWidth × dpr),CSS 宽高只控制显示大小 - 调用
ctx.scale(dpr, dpr)后,所有坐标和尺寸按逻辑像素写,否则文字模糊或错位 - H5 端若用
transform: scale()缩放 canvas,会导致绘制偏移,禁用
canvasToTempFilePath 导出失败?检查这些硬性条件
uni.canvasToTempFilePath 不是万能导出函数,它对上下文状态极其敏感:
- 必须在
drawImage或fillText后显式调用context.draw(true, callback),true表示同步绘制,否则可能导出空白 - canvas 元素不能被
display: none或visibility: hidden隐藏,哪怕只是临时藏到屏幕外也要用position: fixed; left: -9999px - 微信小程序要求
canvas-id必须与uni.createCanvasContext第一个参数严格一致,大小写、空格都不能错 - App 端(尤其 iOS WKWebView)偶发 canvas 渲染白屏,需加兜底:检测导出失败后,降级为 SVG 水印覆盖层(
<svg></svg>+text+ base64 data URL)
真正难的不是“怎么画”,而是“在哪儿画得准、导得稳、缩得对”。每个平台对 canvas 的容忍度不同,同一套代码在 H5 跑得飞起,在小程序里可能黑屏,在 App 里又卡顿——得把设备像素比、缩放策略、导出时机、错误降级全串成一条链,少一环就掉帧或丢图。


















