更新记录
1.1.1(2026-11-04)
首个发布版本,支持 Android / iOS / 微信小程序三端。
- 调用原生相机拍照并在照片上合成水印:Android 走 Camera2 + TextureView,iOS 走 AVFoundation 自定义相机页,微信小程序走 camera 组件 + OffscreenCanvas
- 文字水印:支持多条叠加、多行文本,可设字号、行高、颜色、加粗、背景色、透明度
- 图片水印:支持多张叠加,可设宽度/高度、等比缩放、旋转、透明度
- 位置排版:九宫格锚点(9 个)+ 边距 + X/Y 偏移,按 1080 设计稿等比换算
- 实时水印预览:未按下快门时水印即叠加在取景画面上,与成片所见即所得
- 变焦能力:支持
zoom初始倍数,Android/iOS 支持双指捏合实时变焦,小程序通过setZoom应用 - 出图质量可调(1-100),Android 端出图分辨率上限约 1200 万像素,避免高像素机型内存溢出
平台兼容性
uni-app
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | × | × | √ | - | √ | √ | × |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 2.16.1 | - | - | - | - | - | - | - | - | - | - | - |
lingbug-watermarkcam 接入说明文档
版本:1.0.0 | 适用:HBuilderX 3.98+ | 适配:Android / iOS / 微信小程序
lingbug-watermarkcam 是一个 UTS 插件,调用原生相机模块拍照,并在照片上合成可完全自定义的文字水印与图片水印。三端(app-android / app-ios / mp-weixin)提供统一 API。
一、插件安装
- 将
uni_modules/lingbug-watermarkcam整个目录复制到你项目的uni_modules/目录下(或通过 HBuilderX 导入插件)。 - 项目要求:
- uni-app 项目(Vue 3)或 uni-app x 项目;
- HBuilderX 3.98 及以上(UTS 编译器)。
- 无需引入任何第三方依赖。
插件目录结构
uni_modules/lingbug-watermarkcam/
├── package.json # 插件元信息
├── changelog.md
├── readme.md
└── utssdk/
├── interface.uts # 三端公共类型定义(API 契约)
├── app-android/
│ ├── index.uts # Android 实现:Camera2 自定义相机 + Canvas 合成
│ └── AndroidManifest.xml # 自动合并的权限声明
├── app-ios/
│ └── index.uts # iOS 实现:AVFoundation 自定义相机 + CoreGraphics 合成
├── mp-weixin/
│ └── index.uts # 微信小程序实现:camera 组件 + OffscreenCanvas 合成
└── components/
└── wm-watermark-overlay/wm-watermark-overlay.vue # 小程序端实时水印预览组件(easycom)
二、三端配置
2.1 Android
- 权限:插件自带
AndroidManifest.xml,云打包/自定义基座时会自动合并android.permission.CAMERA权限声明,无需手动配置。 - 运行权限:插件内部已调用系统权限弹窗申请相机权限,业务侧无需处理。
- 照片保存位置:
Android/data/<包名>/files/Pictures/watermark_camera/(应用私有目录,无需存储权限)。回调返回的path为绝对路径,可直接用于image组件展示或上传。 - 调试要求:UTS 插件需使用自定义基座运行(HBuilderX 菜单:运行 → 运行到手机或模拟器 → 制作自定义调试基座)。
2.2 iOS
- 隐私权限描述:在
manifest.json→App常用其它设置→iOS隐私权限申请描述(或源码视图app-plus.distribute.ios.privacyDescription)中添加:
{
"app-plus": {
"distribute": {
"ios": {
"privacyDescription": {
"NSCameraUsageDescription": "需要使用相机拍摄照片并添加水印"
}
}
}
}
}
- 照片保存在应用沙盒
tmp目录,回调返回绝对路径。 - iOS 端 UTS 插件需云打包/自定义基座才能生效。
2.3 微信小程序
小程序端无法弹出原生相机页面,本插件通过页面内的 <camera> 组件取景,因此:
- 调用
takePhoto的页面必须放置 camera 组件(组件可以按需自定义样式、位置,也可以放在页面外视觉隐藏,但不能不写):
<camera device-position="back" flash="off" resolution="high"
style="width: 100%; height: 500rpx;" />
- 基础库要求:≥ 2.16.1(OffscreenCanvas 2d 类型)。
- 图片水印域名:若水印图片使用网络地址,需在微信公众平台配置
downloadFile合法域名;推荐使用本地路径(如/static/logo.png)。 - 用户隐私:在
manifest.json→mp-weixin中按需配置requiredPrivateInfos/ 隐私协议(如水印中包含位置信息时由业务自行获取并传入文字)。
三、API 参考
3.1 takePhoto(options, callback)
打开相机拍照并合成水印。三端签名完全一致,业务代码无需条件编译。
| 参数 | 类型 | 说明 |
|---|---|---|
options |
TakePhotoOptions |
拍照与水印配置,见下表 |
callback |
(res: TakePhotoResult) => void |
结果回调(异步,回调参数见下文) |
TakePhotoOptions(所有字段必填;因 UTS iOS 平台限制,类型定义不支持字段默认值)
| 字段 | 类型 | 取值 / 建议值 | 说明 |
|---|---|---|---|
cameraDevice |
string |
"back" 或 "front"(建议 "back") |
前/后置摄像头 |
flash |
string |
"off" / "on" / "auto"(建议 "off") |
闪光灯模式 |
quality |
number |
90 |
输出 JPEG 质量 1~100 |
zoom |
number(可选) |
1.0 起,如 2 表示 2 倍变焦 |
初始变焦倍数。Android/iOS 打开相机后还可双指捏合实时调整(Android 顶部显示当前倍数),拍照时按当前倍数出片;小程序端拍照前通过 CameraContext.setZoom 应用(基础库 ≥2.10.0)。倍数超出设备上限时自动收敛 |
texts |
WatermarkTextItem[](可选) |
— | 文字水印列表,可叠加多条 |
images |
WatermarkImageItem[](可选) |
— | 图片水印列表,可叠加多张 |
WatermarkTextItem(一条文字水印;backgroundColor 可选,其余必填)
{
text: {
content: string, // 文字内容,支持 "\n" 多行排版(必填)
fontSize: number, // 字号(设计稿像素,建议 28)(必填)
lineHeight: number, // 行高倍数(建议 1.4)(必填)
color: string, // 颜色 "#RRGGBB"(建议 "#FFFFFF")(必填)
backgroundColor: string, // 文字背景色(可选,不传则无背景)
bold: boolean, // 加粗(必填,不加大写 false)
opacity: number // 0~1(必填,不透明传 1)
},
position: WatermarkPosition
}
WatermarkImageItem(一张图片水印;height 可选,其余必填)
{
image: {
path: string, // 图片路径(App:本地路径;小程序:本地或 https 地址)(必填)
width: number, // 目标宽度(设计稿像素)(必填)
height: number, // 目标高度(可选;不传时按原图宽高比自动计算)
opacity: number, // 0~1(必填,不透明传 1)
rotation: number // 顺时针旋转角度(度)(必填,不旋转传 0)
},
position: WatermarkPosition
}
WatermarkPosition(定位排版,文字与图片通用,所有字段必填)
| 字段 | 类型 | 建议值 | 说明 |
|---|---|---|---|
anchor |
string |
"bottomLeft" |
九宫格锚点,见下 |
margin |
number |
24 |
距照片边缘的边距 |
offsetX |
number |
0 |
水平偏移,向右为正 |
offsetY |
number |
0 |
垂直偏移,向下为正 |
anchor 取值(九宫格):
topLeft topCenter topRight
centerLeft center centerRight
bottomLeft bottomCenter bottomRight
竖直方向锚点仅以
top/center/bottom开头生效,水平方向以Left/Center/Right结尾生效,组合使用即可。
TakePhotoResult(回调结果)
| 字段 | 类型 | 说明 |
|---|---|---|
success |
boolean |
是否成功 |
errMsg |
string \| null |
失败原因 |
path |
string \| null |
成品照片路径(App:绝对路径;小程序:临时路径) |
width |
number \| null |
照片宽度(像素) |
height |
number \| null |
照片高度(像素) |
3.2 尺寸单位(重要)
fontSize、width/height、margin、offsetX/offsetY 均以设计稿像素为单位(基准 1080px 宽)。实际绘制时按 照片宽度 / 1080 等比缩放,保证同一组参数在不同分辨率照片上视觉大小一致。
例:fontSize: 34 在 4000px 宽的照片上实际绘制约 34 × (4000/1080) ≈ 126px。
3.3 composeWatermark(srcPath, options, callback)(仅微信小程序)
小程序端可对已有图片单独合成水印(源图片可为本地临时路径或网络地址)。
四、完整示例
import { takePhoto } from '@/uni_modules/lingbug-watermarkcam'
takePhoto(
{
cameraDevice: 'back',
flash: 'off',
quality: 90,
texts: [
{
// 多行文字 + 背景
text: {
content: '2026-10-30 11:20\n地点:示例项目工地',
fontSize: 34,
lineHeight: 1.5,
color: '#FFFFFF',
backgroundColor: '#000000',
opacity: 0.8
},
position: { anchor: 'bottomLeft', margin: 40 }
},
{
// 右上角金色加粗小字
text: {
content: 'Watermark Demo',
fontSize: 24,
color: '#FFD700',
bold: true,
opacity: 0.9
},
position: { anchor: 'topRight', margin: 40, offsetY: 0 }
}
],
images: [
{
// 左上角 logo,宽 160(自动等比)
image: { path: '/static/logo.png', width: 160, opacity: 0.9 },
position: { anchor: 'topLeft', margin: 40 }
}
]
},
(res) => {
if (res.success) {
uni.previewImage({ urls: [res.path] })
} else {
uni.showToast({ title: res.errMsg || '拍照失败', icon: 'none' })
}
}
)
三端通用示例页面见 example/pages/watermark-demo.vue,将其复制到项目 pages 目录并在 pages.json 注册即可运行体验。
五、实时水印预览(拍照前预览界面显示水印)
插件支持所见即所得:打开相机、尚未按下快门时,水印即实时叠加在取景画面上。
实现原理:预览层与成片合成使用同一套 texts / images / position 参数,按当前预览区域宽度相对 1080 基准等比换算。按下快门后,成片仍按完整参数重新合成——以成片效果为准(预览为高保真近似)。
5.1 Android / iOS:自动生效
原生相机页内部已集成预览水印叠加层(Android:TextureView 上方叠加原生 TextView/ImageView;iOS:预览图层上方叠加 UILabel/UIImageView),调用 takePhoto 时传入什么水印参数,预览界面就直接显示什么,无需额外配置。
5.2 微信小程序:使用 wm-watermark-overlay 组件
小程序端相机是页面里的 <camera> 组件(其子节点只允许 cover-view / cover-image),因此插件提供了预览水印组件(uni_modules easycom 自动注册,无需 import):
<camera device-position="back" flash="off" resolution="high"
style="width: 100%; height: 500rpx;">
<!-- 参数与 takePhoto 的 texts / images 完全同构,建议与拍照参数共用同一份数据 -->
<wm-watermark-overlay :texts="wmOptions.texts" :images="wmOptions.images" />
</camera>
组件行为:
- 自动测量取景区域尺寸,按与成片一致的锚点/边距/偏移规则定位水印;
- 文字水印逐行渲染,保证多行排版与成片一致;
- 图片水印未指定
height时自动读取原图宽高比等比缩放; texts/images数据变化时预览实时刷新(如更新时间戳文字)。
5.3 预览与成片的细微差异说明
| 场景 | 差异 | 说明 |
|---|---|---|
| 取景区域被裁切 | 预览画面 aspectFill 有裁边,成片是完整画面 | 靠近画面边缘的水印,预览位置可能略偏 |
| 文字行高 | 预览用系统控件默认行距,成片用 lineHeight 精确行高 |
多行文字的行距可能有细微差别 |
| 图片旋转 | 预览按视图中心旋转,成片按位图旋转后定位 | 旋转 + 靠边定位时预览可能有 1~2% 偏差 |
以上均为高保真近似;若业务要求预览与成片像素级一致,可适当将水印锚点远离画面边缘、避免依赖精确行高。
六、各端实现原理
| 端 | 相机 | 水印合成 | 保存 |
|---|---|---|---|
| Android | Camera2 API + TextureView 全屏预览,ImageReader 获取 JPEG | android.graphics.Canvas(Paint/Matrix) |
应用私有 Pictures 目录,JPEG |
| iOS | AVFoundation AVCaptureSession + AVCapturePhotoOutput | UIGraphicsImageRenderer(CoreGraphics) |
沙盒 tmp 目录,JPEG |
| 微信小程序 | 页面 <camera> 组件 + uni.createCameraContext().takePhoto();预览水印由 wm-watermark-overlay 组件(cover-view/cover-image)叠加 |
OffscreenCanvas 2d(canvas.getContext('2d')) |
wx.canvasToTempFilePath 临时文件 |
七、注意事项与 FAQ
- App 端必须使用自定义基座:标准基座不包含自定义 UTS 插件,需先「制作自定义调试基座」再真机运行。
- iOS 首次调用:系统会弹出相机权限弹窗;若用户拒绝,
errMsg会提示到设置中开启。 - Android 拍照方向:已按 Camera2 官方公式(屏幕方向 +
sensorOrientation)计算JPEG_ORIENTATION,并兼容「HAL 只写 EXIF 不旋转像素」的机型(按解码后宽高判据自动补转);如个别机型仍出现方向问题,可在反馈中说明机型。 - Android 预览黑边:预览画面按相机流宽高比等比放入屏幕(fit-center),与屏幕比例不一致时会上下/左右留黑边——这是保证不变形的正确行为;成片为完整画幅(多为 4:3),视野可能比取景框略大,属正常差异。
- 图片水印路径:
- App 端:传本地文件绝对路径(如通过
plus.io或下载后的文件路径); - 小程序端:本地路径或已配置域名的 https 地址。
- App 端:传本地文件绝对路径(如通过
- 小程序 camera 组件:必须在调用页存在;若业务不想展示取景画面,可将组件样式设置为极小/透明(不可用
v-if移除)。 - 性能建议:水印数量一般不超过 10 条;图片水印建议预先压缩,避免大图解码耗时。
- UTS 编译器版本:不同 HBuilderX 版本的 UTS 语法略有差异,若编译报错请先升级到最新正式版 HBuilderX;iOS 端建议在 HBuilderX 最新 alpha/正式版 + 云打包环境下验证。
- Android 出图分辨率上限:为避免高像素机型(5000万/1亿像素传感器)解码合成时 OOM 闪退,Android 端拍照分辨率收敛到约 1200 万像素(超出时自动选最接近上限的尺寸),对水印相机场景完全够用。
八、错误码 / 常见 errMsg
| errMsg | 原因 | 处理 |
|---|---|---|
相机权限被拒绝 / 用户拒绝相机权限 |
未授权 | 引导用户到系统设置开启 |
未找到可用的前置/后置摄像头 |
设备无对应摄像头 | 检查 cameraDevice 参数 |
微信基础库版本过低 |
基础库 < 2.16.1 | 提示用户升级微信 |
当前页面未找到 camera 组件 |
小程序页面缺少 camera | 添加 camera 组件 |
用户取消拍摄 |
用户点关闭 | 业务侧静默处理即可 |

收藏人数:
购买普通授权版(
试用
赞赏(0)
下载 0
赞赏 0
下载 12741647
赞赏 1959
赞赏
京公网安备:11010802035340号