uniapp给照片使用canvas画水印,任意数量水印文字位于左下角不会被遮盖且自动换行
前言
本文讲的是,文字数量不确定、文字种类不确定时,如何在水印左下角画图时,自动换行。
实现效果如下:根据文字自适应水印
总体思路还是非常简单的,canvas画图是从左上角开始。
计算出文字的行数,计算出文字总体高度,画布高度-文字高度作为水印起始高度
换行就是通过画布宽度/文字宽度,计算每一行能放的文字数量
详细思路
将不同列文字组成一个数组A,例如arr=['记录人:didi','时间:2022-04-01']
获取画布宽度
文字总数/画布宽度来计算行数,
画布高度-行高*行数作为起始高度
画布宽度/文字宽度,计算每行能放下的文字数量
将文字切割成数组,数组的每个子元素放置相应数量的文字
代码
onLoad(){ //获取水印内容,otherWaterData是数组形式,如['记录人:didi','时间:2022-01-01‘] let otherWaterData = this.$store.state.waterStore; this.otherWaterData = JSON.parse(JSON.stringify(otherWaterData)); }
//参数是水印信息waterData为数组、画布宽度
waterHandle(waterData, canvasWidth) {
//转化为字符串 let waterString = waterData.join(",");
//获取水印的宽度 let waterWidth = waterString.length * 12;
//获取一行能放置的字数,字的宽度设为12 let oneLineWaterNum = Math.floor(canvasWidth / 12); //切割数组 let newWaterData = []; for (let i = 0; i < waterData.length; i++) { let item = waterData[i]; //子项字数小于一行能放下的字数,不换行 if (item.length < oneLineWaterNum) { newWaterData.push(item) } else { let itemWidth = item.length * 12; //字数宽度 let itemLineNum = Math.ceil(itemWidth / canvasWidth); //分为几行 let start = 0; let end = start + oneLineWaterNum; for (let i = 0; i < itemLineNum; i++) { newWaterData.push(item.slice(start, end)); start = end; end = start + oneLineWaterNum; } } } return newWaterData; },
canvasWather(res) { let that = this; let ctx = uni.createCanvasContext('firstCanvas', this); that.imgPath = res.path let canvasWidth = res.width / 2; let canvasHeight = res.height / 2; that.w = canvasWidth + 'px'; that.h = canvasHeight + 'px'; setTimeout(() => { //搜集水印数据 let waterData = that.otherWaterData;
//处理水印数据 let waterContentPosition = that.waterHandle(waterData, canvasWidth) //初始化画布 ctx.fillRect(0, 0, canvasWidth, canvasHeight); // //将图片src放到cancas内,宽高为图片大小 ctx.drawImage(res.path, 0, 0, canvasWidth, canvasHeight);
//开始绘画,字体大小为10,颜色为白色 ctx.beginPath() ctx.setFontSize(10) ctx.setFillStyle('#FFFFFF'); //行数 let lineNum = waterContentPosition.length;
//行高 let lineHeight = lineNum * 16;
//画布高度-行高=开始绘制高度 let top = canvasHeight - lineHeight; waterContentPosition.forEach((item, index) => {
//内容,左边距,上边距 ctx.fillText(item, 10, top + index * 16) }) ctx.draw(false, () => { uni.canvasToTempFilePath({ //将画布中内容转成图片,即水印与图片合成 canvasId: 'firstCanvas', success: (res) => {
//水印生成成功,可以将图片保存到本地了 that.saveFile(res); }, fail: (err) => { that.showToastHandler('图片水印绘制失败!') } }) }) }, 500) },
开源中国博客地址:https://my.oschina.net/u/2998098/blog/1540520