概述
记录一下前端添加水印,动态水印字体大小、间距
项目里需要对图片添加整片的水印最开始是直接引用这位大佬的。前端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.color
ctx.font = `${fontSize}px ${wmConfig.font}`;
ctx.textAlign = wmConfig.textAlign
ctx.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 = 3
let 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 * i
if (width < imgWidth) {
if (i == 7) {
dest = 7
}
continue
} else if (width = imgWidth) {
dest = i
break
} else {
dest = i - 1
break
}
}
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 * 7
if (width < imgWidth) {
continue
} else if (width = imgWidth) {
fontSize = i
break
} else {
fontSize = i - 1
break
}
}
}
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循环的话,欢迎指点!!!!
最后
以上就是老迟到小霸王为你收集整理的vue添加图片水印脱敏,动态水印字体大小、间距的全部内容,希望文章能够帮你解决vue添加图片水印脱敏,动态水印字体大小、间距所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复