前言:当你在微信小程序中制作照片时,你可能需要添加水印,以便在分享时保护你的照片,并标识出你的品牌或网站。本文将介绍如何在微信小程序中添加照片水印。
最近接到个需求:
效果图:
我的环境:
系统:Windows 11
微信开发者工具:1.06.2209190
调试基础库:2.32.2
说下思路:就是创建一个画布 把照片放到画布上 在画一个水印 然后融合
根据我的需求 我是一个 上传控件开始 要求只能拍照 不能从相册选择
<van-uploader capture="{{['camera']}}"
multiple="true"
preview-size="{{screenWidth*0.2}}"
file-list="{{ fileList }}"
bind:after-read="afterRead"
bind:delete="deleteImg">
</van-uploader>
重点是 capture="{{['camera']}}" 我用的vant控件 所以查看文档 可解决
然后 实现 拍照水印:
wxml:
<canvas id="mycanvas" type="2d" :style="{ width: canvasWidthValue + 'px', height: canvasHeightValue + 'px', position: 'fixed' }" style=" left:9000px;"></canvas>
这个 画布 我放在了屏幕之外 这样 就不用 display:none 而导致绘图白屏了~~
然后他的宽度 和 高度 根据图片的大小而改变的 双向绑定的
js:
/* 上传方法 */
afterRead(event) {
const that = this;
const {
file
} = event.detail;
// 获取当前时间和位置信息
const currentTime =this.data.currentDate+" "+this.data.signTime; //时间
const currentLocation = this.data.address ; //地址
const files = event.detail.file;
// 遍历每个文件对象
files.forEach((file, index) => {
// 获取图片宽度和高度
wx.getImageInfo({
src: file.path,
success(res) {
file.width = res.width;
file.height = res.height;
that.setData({
canvasWidthValue: res.width,
canvasHeightValue:res.height,
})
file.path = res.path;
// 将时间和位置信息添加到文件对象中
file.currentTime = currentTime;
file.currentLocation = currentLocation;
// 创建一个临时canvas对象 query
const query = wx.createSelectorQuery()
query.select('#mycanvas').fields({
node: true,
size: true
})
.exec(res => {
const canvas = res[0].node
const ctx = canvas.getContext('2d');
const img = canvas.createImage()
img.src = file.path
img.onload = function () {
//设置画布到校绘制原图到canvas中
ctx.canvas.width = file.width/2
ctx.canvas.height = file.height/2
ctx.drawImage(img, 0, 0, file.width/2, file.height/2)
// 设置水印字体大小、颜色和位置
ctx.font = "18px arial";
ctx.fillStyle = "#FFFFFF";
ctx.textAlign = "left";
ctx.textBaseline = "bottom";
// 绘制时间和位置信息到canvas中
ctx.fillText(currentTime, 10, 60);
that.drawText(ctx,currentLocation,10, 90 , 232,that.data.windowWidth/6*5) // 自动换行
setTimeout(() => {
// 将canvas转换成图片,并将其添加到文件对象中
wx.canvasToTempFilePath({
canvas: canvas,
success: (res) => {
file.path = res.tempFilePath;
// 上传包含水印的图片
wx.uploadFile({
url: `${config.server_add}:${config.server_port}/iboss/interface/upload/${app.globalData.iboss_user.id}/StaffClock`,
filePath: file.path,
name: 'file',
header: {
'content-type': 'multipart/form-data'
},
success(res) {
res.data = JSON.parse(res.data);
console.log('res',res);
if (res.data.code === 200) {
console.log('200');
let arr = that.data.fileList;
arr.push({
url: res.data.data.realUrl,
FilePath: res.data.data.url,
deletable: true,
FileName: file.path.substring(11)
});
that.setData({
fileList: arr
});
} else {
wx.showToast({
title: '图片上传失败',
image: '../../../static/image/error.png',
duration: 1000
});
}
},
fail(res) {
console.error('生成图片失败', res)
}
});
},
fail(res) {
console.error('失败', res)
}
});
}, 1000);
}
})
}
});
});
},
//canvas文本过长 自动换行
drawText: function(ctx, str, leftWidth, initHeight, titleHeight, canvasWidth) {
console.log("woaini",canvasWidth)
var lineWidth = 0;
var lastSubStrIndex = 0; //每次开始截取的字符串的索引
for (let i = 0; i < str.length; i++) {
lineWidth += ctx.measureText(str[i]).width;
if (lineWidth > canvasWidth) {
ctx.fillText(str.substring(lastSubStrIndex, i), leftWidth, initHeight); //绘制截取部分
initHeight += 16; //16为字体的高度
lineWidth = 0;
lastSubStrIndex = i;
titleHeight += 30;
}
if (i == str.length - 1) { //绘制剩余部分
ctx.fillText(str.substring(lastSubStrIndex, i + 1), leftWidth, initHeight);
}
}
// 标题border-bottom 线距顶部距离
titleHeight = titleHeight + 10;
return titleHeight
},
大功告成~~~