1、效果图(最下方贴有完整代码)
2、代码详解
wxml
在微信的wxml给个canvas元素给上id,canvas的宽高下面js中也有用到,统一放到data里面。
<canvas canvas-id='myCanvas' style='width:{{canvasWidth}}px;height:{{canvasHeight}}px;'>canvas>
js(主要看js)
data里面放了canvas宽、高
data: {
canvasWidth: 250,//canvas宽
canvasHeight: 250//canvas高
}
disposePath(url, canvasId, callback)方法主要是为了处理图片路径
三个参数:url(图片地址)、canvasId(canvas的Id)、callback(回调函数)
如果是线上图片需要使用wx.downloadFile(),将图片转成本地路径进行画图,如果图片为本地路径直接传值。
disposePath(url, canvasId, callback) {
let that = this;
//本地路径直接传
// that.getCanvasImg('/image/01.png', canvasId).then((url) => {
// if (callback) callback(url);
// }, (err) => {
// console.log('err',err);
// })
//线上图片
wx.downloadFile({
url,
success(res) {
if (res.tempFilePath) {
that.getCanvasImg(res.tempFilePath, canvasId).then((url) => {
if (callback) callback(url);
}, (err) => {
console.log('err',err);
})
}
},
fail(err) {
console.log('err',err);
}
})
},
getCanvasImg(localImgUrl, canvasId)方法生成canvas水印图片
两个参数localImgUrl(本地图片路径),canvasId(canvas的id)方法里面使用promise返回canvas生成结果;
绘图的整个思路就是在获取图片的宽、高最长边的2倍,以最长边的2倍为边长形成一个正方形,在正方形里面铺满水印文字,最终旋转铺满水印文字的正方型。
水印文字配置:宽度行高根据自己需求调整
let fontSize = 14; //水印字体大小
let maskText = '仅供自己使用'; //水印文字
let fontColor = "rgba(255,255,255,.5)"; //水印颜色
let lineHeight = 45; //水印文字行高
let textWidth = 100; //水印文字宽度
通过canvas的宽高得出最长边
let {canvasWidth,canvasHeight} = this.data;
let diagonalLength = canvasHeight > canvasWidth ? canvasHeight * 2 : canvasWidth; //选取最长边
let ctx = wx.createCanvasContext(canvasId);
ctx.drawImage(localImgUrl, 0, 0, canvasWidth, canvasHeight) //在画布上绘入图片宽高等于canvas宽高
移动原点坐标
ctx.translate(canvasWidth / 2, -diagonalLength);
设置旋转角度
ctx.rotate(45 * Math.PI / 180); //设置文字的旋转角度,角度为45°;
根据最长边的2倍分别除以水印文字的宽、高,计算出铺满正方形所需要渲染水印文字的横向、纵向次数。
// 横向循环次数
let crossTime = Math.ceil(diagonalLength * 2 / textWidth);
// 纵向循环次数
let verticalTime = Math.ceil(diagonalLength * 2 / lineHeight);
根据所得渲染横向、纵向次数进行循环渲染文字
for (let j = 0; j < verticalTime; j++) { //纵向循环
ctx.setFontSize(fontSize);
ctx.setFillStyle(fontColor);
ctx.fillText(maskText, 0, lineHeight * j);
for (let i = 1; i < crossTime; i++) { //横向循环
ctx.setFontSize(fontSize);
ctx.setFillStyle(fontColor);
ctx.fillText(maskText, textWidth * i, lineHeight * j);
}
}
整个绘图先更改原点位置如图
再旋转45°如图
绘图
ctx.draw(false, () => {
wx.canvasToTempFilePath({
width: canvasWidth,
height: canvasHeight,
canvasId,
success: function (res) {
resolve(res.tempFilePath)
},
fail: function (res) {
reject(res)
}
}, this);
});
在disposePath方法的callback里面获取水印路径
let onlineImg = 'https://iph.href.lu/250x250?text=%E5%8D%A0%E4%BD%8D%E5%9B%BE%E7%89%87';
this.disposePath(onlineImg, 'myCanvas', url => {
console.log(url)
})
到这整个绘图结束,如果要求水印方向,可以自行调节原点位置,以及渲染文字的位置,像那种左下角、右下角展示某个商家或者某个公司的署名水印更为简单。
下期更新微信小程序分享海报并保存到手机相册,包含圆角头像,文字超出显示省略号,多行超出显示省略号,声明一下我不是为了凑字数在这瞎掰,哈哈哈
整个代码放到下面了可以直接复制预览查看,有问题欢迎在下面评论!!!
wxml
<canvas canvas-id='myCanvas' style='width:{{canvasWidth}}px;height:{{canvasHeight}}px;'>canvas>
js
Page({
data: {
canvasWidth: 250,
canvasHeight: 250
},
// 将在线图片生成带水印图片
disposePath(url, canvasId, callback) {
let that = this;
that.getCanvasImg('/image/01.png', canvasId).then((url) => {
if (callback) callback(url);
}, (err) => {
console.log(err, 'err');
})
return;
//将在线资源变成本地路径
wx.downloadFile({
url,
success(res) {
if (res.tempFilePath) {
that.getCanvasImg(res.tempFilePath, canvasId).then((url) => {
if (callback) callback(url);
}, (err) => {
console.log(err, 'err');
})
}
},
fail(err) {
console.log(err);
}
})
},
// 使用canvas绘制水印图片
getCanvasImg(localImgUrl, canvasId) {
return new Promise((resolve, reject) => {
//水印文字样式相关
let fontSize = 14; //水印字体大小
let maskText = '仅供自己使用'; //水印文字
let fontColor = "rgba(255,255,255,.5)"; //水印颜色
let lineHeight = 45; //水印文字行高
let textWidth = 100; //水印文字宽度
let {
canvasWidth,
canvasHeight
} = this.data;
let diagonalLength = canvasHeight > canvasWidth ? canvasHeight * 2 : canvasWidth; //选取最长边
// 保证水印文字范围是矩形最长边的2倍
let ctx = wx.createCanvasContext(canvasId);
ctx.drawImage(localImgUrl, 0, 0, canvasWidth, canvasHeight) //在画布上绘入图片宽高等于canvas宽高
ctx.translate(canvasWidth / 2, -diagonalLength);
ctx.rotate(45 * Math.PI / 180); //设置文字的旋转角度,角度为45°;
// 横向循环次数
let crossTime = Math.ceil(diagonalLength * 2 / textWidth);
// 竖向循环次数
let verticalTime = Math.ceil(diagonalLength * 2 / lineHeight);
console.log(crossTime, verticalTime);
for (let j = 0; j < verticalTime; j++) { //纵向循环
ctx.setFontSize(fontSize);
ctx.setFillStyle(fontColor);
ctx.fillText(maskText, 0, lineHeight * j);
for (let i = 1; i < crossTime; i++) { //横向循环
ctx.setFontSize(fontSize);
ctx.setFillStyle(fontColor);
ctx.fillText(maskText, textWidth * i, lineHeight * j);
}
};
ctx.draw(false, () => {
wx.canvasToTempFilePath({
width: canvasWidth,
height: canvasHeight,
canvasId,
success: function (res) {
resolve(res.tempFilePath)
},
fail: function (res) {
reject(res)
}
}, this);
});
})
},
onLoad() {
let onlineImg = 'https://iph.href.lu/250x250?text=%E5%8D%A0%E4%BD%8D%E5%9B%BE%E7%89%87';
this.disposePath(onlineImg, 'myCanvas', url => {
console.log(url)
})
},
})