1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > vue添加图片水印脱敏 动态水印字体大小 间距

vue添加图片水印脱敏 动态水印字体大小 间距

时间:2022-09-15 07:59:33

相关推荐

vue添加图片水印脱敏 动态水印字体大小 间距

记录一下前端添加水印,动态水印字体大小、间距

项目里需要对图片添加整片的水印最开始是直接引用这位大佬的。前端js实现给图片添加水印

这个大佬的方法里水印密度是手动传入的,对于同一个图片上传器。密度是固定的,或者说,对于同一个页面里的水印添加方法要实现传入不同的水印密度,就要多次调用,所以实际应用中,当窄图片和宽图片用同样的密度,即使缩小了字体,也会出现水印密密麻麻重叠的问题。并且水印字体的大小也区分的比较生硬。所以在此文代码基础上做了些修改以实现简单的动态字体大小、间距。

新建一个waterMarker.js

export function addWaterMark(base64Img, wmConfig) {return new Promise((resolve, reject) => {const canvas = document.createElement("canvas");const ctx = canvas.getContext("2d");const img = new Image()img.src = base64Img;let resultBase64 = null;img.onload = function () {canvas.width = img.width;canvas.height = img.height;//canvas绘制图片,0 0 为左上角坐标原点ctx.drawImage(img, 0, 0);//写入水印drawWaterMark(ctx, img.width, img.height, wmConfig);resultBase64 = canvas.toDataURL("image/jpeg");if (!resultBase64) {reject();} else {resolve(resultBase64);}}})};

const drawWaterMark = (ctx, imgWidth, imgHeight, wmConfig) => {//调用函数确定字体大小和密度let [fontSize, density] = setFontSize(imgWidth, wmConfig)ctx.fillStyle = wmConfig.colorctx.font = `${fontSize}px ${wmConfig.font}`;ctx.textAlign = wmConfig.textAlignctx.textBaseline = wmConfig.textBaseline//获取图片宽高最大值,以确定水印的行数和列数,如果水印行数和列数不按照最大值排列,可能会出现上下空白或者左右空白const maxPx = Math.max(imgWidth, imgHeight);//获取图宽根据密度划分后的单个宽度,这里以宽度为准,也可以以高度为准,效果是一样的const stepPx = Math.floor(imgWidth / density);//这里将水印划分成一个高宽相等的方块,计算y轴方向的密度const densityY = Math.floor(imgHeight / stepPx)let arrayX = [0];//初始水印位置 canvas坐标 0 0 点while (arrayX[arrayX.length - 1] < maxPx / 2) {arrayX.push(arrayX[arrayX.length - 1] + stepPx);}arrayX.push(...arrayX.slice(1, arrayX.length).map((el) => {return -el;}));for (let i = 0; i < arrayX.length; i++) {for (let j = 0; j < arrayX.length; j++) {ctx.save();ctx.translate(imgWidth / 2, imgHeight / 2); ///画布旋转原点 移到 图片中心ctx.rotate(-Math.PI / 5);if (wmConfig.textArray.length > 3) {wmConfig.textArray = wmConfig.textArray.slice(0, 3);}wmConfig.textArray.forEach((el, index) => {let offsetY = fontSize * index + 2;ctx.fillText(el, arrayX[i], arrayX[j] + offsetY);});ctx.restore();}}};

动态设置字体大小和密度的方法,本项目里暂时设置最小密度是3,最小字体是8px,这个看项目需要。

这也是存在些问题的,当一张图片非常大的时候,我密度还是7的话,水印字体会非常大,即使颜色是灰色也很难忽略,不好看,所以这个可以用if…else if…根据图片宽度确定一下最大密度。

const setFontSize = (imgWidth, wmConfig) => {//maxDest 最大密度,目前暂定任何图片尺寸最大密度都是7,当imgwidth超过某个值时,水印fontSize将会越来越大,是不合理的// 此时可以引入maxDest,根据图片宽度,增加水印密度,控制水印字体大小,使之处于一个合理的范围。let fontSize = 8, dest = 3let strLengthMin = Math.ceil(getStrLeng(wmConfig.textArray[0], fontSize, wmConfig.font))let itemWidthMin = Math.floor(strLengthMin * 1.5)let minWidth = itemWidthMin * dest// console.log(strLengthMin, itemWidthMin, minWidth, imgWidth)if (imgWidth < minWidth) {return [fontSize, dest]} else {for (let i = 3; i < 8; i++) {let strLength = Math.ceil(getStrLeng(wmConfig.textArray[0], 8, wmConfig.font))let itemWidth = Math.floor(strLength * 1.5)let width = itemWidth * iif (width < imgWidth) {if (i == 7) {dest = 7}continue} else if (width = imgWidth) {dest = ibreak} else {dest = i - 1break}}if (dest == 7) {for (let i = 8; i > 0; i++) {let strLength = Math.ceil(getStrLeng(wmConfig.textArray[0], i, wmConfig.font))let itemWidth = Math.floor(strLength * 1.5)let width = itemWidth * 7if (width < imgWidth) {continue} else if (width = imgWidth) {fontSize = ibreak} else {fontSize = i - 1break}}}return [fontSize, dest]}}

获取水印文本宽度方法,因为我的项目移动端做了px2vw的适配所以,我要将字体按照比例转换一下,如果没有做这种适配的可以不用转,如果你的水印还加了字间距letterSpace的话也要加进来,还有字体也要统一,避免水印宽度计算有误差。

const getStrLeng = (str, fontSize, fontFamily) => {let viewWidth = window.innerWidth;let result = 0;let ele = document.createElement("div");ele.style.position = "absolute";ele.style.whiteSpace = "nowrap";ele.style.fontSize = ((fontSize / 375) * viewWidth).toFixed(5) + "px";ele.style.fontFamily = fontFamily;ele.style.opacity = 0;ele.innerText = str;document.body.append(ele);result = ele.getBoundingClientRect().width;document.body.removeChild(ele);return result;};

函数写的还是很小白,没有想到更好的写法,有大佬能优化一下if大法和for循环的话,欢迎指点!!!!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。