/** * 在照片左下角叠加水印文字 * @param {string} imagePath - 原始图片路径 * @param {string} text - 水印文字(如 "2025/06/15 12:00 张三") * @returns {Promise} 带水印的临时文件路径 */ export function addWatermark(imagePath, text) { return new Promise((resolve, reject) => { uni.getImageInfo({ src: imagePath, success(imgInfo) { const canvasId = 'watermarkCanvas' const width = imgInfo.width const height = imgInfo.height // 使用 OffscreenCanvas(APP-PLUS 和 H5 均支持) // #ifdef APP-PLUS const bitmap = new plus.nativeObj.Bitmap('watermark') bitmap.load(imagePath, () => { const canvas = new plus.nativeObj.View('watermarkView', { left: '0px', top: '0px', width: width + 'px', height: height + 'px' }) // 绘制原图 canvas.drawBitmap(bitmap, {}, { left: '0px', top: '0px', width: width + 'px', height: height + 'px' }) // 水印参数 const fontSize = Math.max(Math.floor(width * 0.03), 14) const padding = Math.floor(fontSize * 0.8) const textX = padding const textY = height - padding // 绘制半透明背景 const bgHeight = fontSize + padding * 2 canvas.drawRect( { color: 'rgba(0,0,0,0.4)' }, { left: '0px', top: (height - bgHeight) + 'px', width: width + 'px', height: bgHeight + 'px' } ) // 绘制水印文字 canvas.drawText(text, { left: textX + 'px', top: (height - bgHeight + padding) + 'px', width: (width - textX * 2) + 'px', height: fontSize + 'px' }, { size: fontSize + 'px', color: '#ffffff' }) // 导出 const tempPath = `_doc/watermark_${Date.now()}.jpg` canvas.toBitmap(tempPath, {}, () => { bitmap.clear() resolve(tempPath) }, (err) => { bitmap.clear() reject(err) }) }, (err) => { reject(err) }) // #endif // #ifndef APP-PLUS // H5 / 小程序端使用 Canvas 2D const canvas = uni.createOffscreenCanvas({ type: '2d', width, height }) const ctx = canvas.getContext('2d') const img = canvas.createImage() img.onload = () => { // 绘制原图 ctx.drawImage(img, 0, 0, width, height) // 水印参数 const fontSize = Math.max(Math.floor(width * 0.03), 14) const padding = Math.floor(fontSize * 0.8) // 绘制半透明背景 const bgHeight = fontSize + padding * 2 ctx.fillStyle = 'rgba(0,0,0,0.4)' ctx.fillRect(0, height - bgHeight, width, bgHeight) // 绘制水印文字 ctx.fillStyle = '#ffffff' ctx.font = `${fontSize}px sans-serif` ctx.textBaseline = 'middle' ctx.fillText(text, padding, height - bgHeight / 2) // 导出为临时文件 const tempFilePath = canvas.toDataURL('image/jpeg', 0.9) resolve(tempFilePath) } img.onerror = (err) => { reject(err || new Error('图片加载失败')) } img.src = imagePath // #endif }, fail(err) { reject(err) } }) }) }