一、是不是你想要的效果,可扫小程序码查看一把先:
二、实现步骤:
1. 生成水印前的一些参数设置及图片选择:
(1)先选择要加水印的图片,可以是拍照,也可以是从相册选择;将选择的图片地址赋值给imagesrc显示到image上:
关键js代码:
* 选择图片:
*/
choicePic() {
wx.chooseMedia({
count: 1,
mediaType: ['image'],
maxDuration: 60,
success: (result) => {
console.log(result)
this.setData({
imgsrc: result.tempFiles[0].tempFilePath
})
},
fail: (result) => {
console.log(result)
}
})
}
(2)选择完图片,点击图片可预览,关键代码:
* 预览图片:
*/
previewPic() {
wx.previewImage({
current: this.data.imgsrc,
urls: [this.data.imgsrc],
})
}
(3)输入要添加的水印内容和选择字体颜色、字体大小,这个就不在此赘述,可以自己实现
(4)点击添加水印,携带选择完成的参数跳入下个生成水印的页面
2. 生成水印页面功能实现:
(1) 首先wxml中添加cavas组件(其他非关键性的组件代码就不粘贴出来了,可以自己添加):
<canvas style="position:fixed;top: 0;left: -100%" type="2d" id="Canvas"></canvas>
(2)定义data数据:
* 页面的初始数据
*/
data: {
imageSrc: "",
_canvas: null,
ctx: null,
_printText: undefined,
_textLength: undefined,
_textWidth: undefined,
_textHeight: 120,
_fontSize: 30,
_canSave: false,
_color: undefined,
},
(3)将上个页面传过来的参数赋值给data,此处不再赘述
(4)获取canvas及cavasContext,需要计算要输入水印的宽度,用来绘制水印时候计算位置
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
const query = wx.createSelectorQuery()
query.select('#Canvas')
.fields({
node: true,
size: true
})
.exec((res) => {
const _canvas = res[0].node
const ctx = _canvas.getContext('2d')
this.setData({
_canvas,
ctx
})
console.log('this.data.imageSrc', this.data.imageSrc)
// 先获取一下文字的宽:
this.data.ctx.font = this.data._fontSize + "px serif";
ctx.fillText(this.data._printText, -1000, -1000)
const textWidth = ctx.measureText(this.data._printText + "").width
this.setData({
_textWidth: textWidth * 1.5
})
// 开始绘制水印:
this.addWatermark(this.data.imageSrc)
})
},
(5)添加水印,并将添加后的水印图片更新到image上,直接贴代码,自己研究一下吧:
addWatermark(tempFilePath) {
return new Promise(async (resolve, reject) => {
// 获取图片信息
const imgInfo = await wx.getImageInfo({
src: tempFilePath
})
// 设置canvas宽高
this.data._canvas.width = imgInfo.width
this.data._canvas.height = imgInfo.height
console.log(imgInfo)
const xSize = Math.floor(imgInfo.width / this.data._textWidth + 1)
const ySize = Math.floor(imgInfo.height / this.data._textHeight + 1)
console.log(ySize)
// 创建一个图片对象
const image = this.data._canvas.createImage();
image.src = tempFilePath;
image.onload = () => {
// 将图片绘制到canvas上
this.data.ctx.drawImage(image, 0, 0, imgInfo.width, imgInfo.height)
// 左右各多出一半图片宽度的水印,是用来处理旋转后盖住空白部分的;上下同理:
for (var x = 0; x < xSize * 2; x++) {
// x控制横向多少个水印:
for (var y = 0; y < ySize * 2; y++) {
// y控制纵向多少个水印:
// 绘制文字 注意::绘制斜体文字 旋转以后会发生位移,所以必须在旋转之后进行位置的调整;
// this.drawText((x * -100), (150 * y), ((x * this.data._textWidth)), ((y * this.data._textHeight)) + 30)
this.drawText((imgInfo.width), (imgInfo.height), -imgInfo.width / 2 + ((x * this.data._textWidth)), -imgInfo.height / 2 + ((y * this.data._textHeight)))
}
}
// 将canvas转为为图片
wx.canvasToTempFilePath({
canvas: this.data._canvas,
success: (res) => {
this.setData({
imageSrc: res.tempFilePath,
_canSave: true
})
resolve(res.tempFilePath)
},
})
}
})
},
drawText(imgWidth, imgHeight, x, y) {
var text = this.data._printText;
this.data.ctx.save(); //保存原来的状态 绘制字体都是需要旋转倾斜 那么之前绘制的图片就要进行状态的保存
// https://www.cnblogs.com/fangsmile/p/5647390.html
this.data.ctx.globalAlpha = 0.6
// 移动到中心点,再旋转相当于按照之前的原点旋转了
this.data.ctx.translate(imgWidth / 2, imgHeight / 2)
this.data.ctx.rotate(-Math.PI / 6); //绘制倾斜字体
// 移动回原来的位置:
this.data.ctx.translate(-imgWidth / 2, -imgHeight / 2)
//this.data.ctx.translate(tsx, tsy); //发生位移进行位移的恢复
this.data.ctx.font = this.data._fontSize + "px serif";
this.data.ctx.fillStyle = this.data._color;
this.data.ctx.fillText(text, x, y);
this.data.ctx.restore(); //状态的恢复
},
(6)保存图片到本地相册:
* 保存图片:
*/
onSavePic() {
if (!this.data._canSave) {
wx.showToast({
title: '正在生成水印中,请生成后再保存',
icon: 'none'
})
return
}
wx.saveImageToPhotosAlbum({
filePath: this.data.imageSrc,
success: (res) => {
console.log(res)
wx.showToast({
title: '保存图片成功',
icon: 'none'
})
},
fail: (res) => {
console.log(res)
wx.showToast({
title: '保存图片失败',
icon: 'none'
})
}
})
}
三.感觉有用的话,可以打赏一把么?一毛不嫌少,100不嫌多