用canvas生成图片为页面添加水印

做政府行业的项目经常会遇到需要为页面添加用户登陆信息水印的功能。

有几个需要注意的点

  1. 需要平铺整个页面
  2. 水印需要盖在内容上,但是不能影响操作
  3. 需要自适应窗口大小
考虑到以上需求有两种方案:

方案一:利用canvas生成图片并给容器添加background背景,并设置repeat,但是这样做有一个弊端,页面的内容不能再设置背景颜色,否则水印会被遮挡,这就不能满足需求了。

方案二:利用canvas生成图片后创建一个div,并将图片设置为div背景图,再将div定位到容器上。此时需要为div设置pointer-events:none,但该属性只兼容IE10+。

pointer-events就是用来进行事件穿透的,如果给父元素设置了pointer-events:none,那么父元素不再监听 鼠标事件事件。也就是说设置该属性后不会影响被遮盖内容的操作,相当于透明的存在,点击不到它。

在项目中需要兼容ie10以上,所以只能采取降级的方法,ie10以上及其他浏览器采用方案二,ie10采用方案一。

具体的实现代码

function IEVersion() {
const userAgent = navigator.userAgent;
const isIE =
userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1;
if (isIE) {
const reIE = new RegExp('MSIE (\\d+\\.\\d+);');
reIE.test(userAgent);
const fIEVersion = parseFloat(RegExp['$1']);
if (fIEVersion == 10) {
return 10;
}
} else {
return -1;
}
}


/*@text 水印文字数组 ['姓名', '身份证']
@sel容器的css选择器
@txtColor水印文字的颜色
*/
export function setWaterMarker(text, sel, txtColor = 'rgba(0, 0, 0, 0.1)') {
const sel= document.querySelector(sel);
let waterBox = null;
for (let node of sel.children) {
if (node.className === 'water-marker') {
waterBox = node;
}
}
//创建一个canvas并插入到body后隐藏
if (waterBox || sel.style.backgroundImage) {
return false;
}
let can = document.body.querySelector('#water-can');
if (!can) {
can = document.createElement('canvas');
can.setAttribute('id', 'water-can');
document.body.appendChild(can);
}
can.width = 280;
can.height = 280;
can.style.display = 'none';
const cans = can.getContext('2d');
cans.rotate((-20 * Math.PI) / 180); //旋转20度
cans.font = '20px Microsoft YaHei'; //设置文字样式
cans.fillStyle = txtColor; //设置文字颜色
cans.textBaseline = 'Middle';
for (let i = text.length - 1; i >= 0; i--) {
//将文字绘制到画布
cans.fillText(text[i], 0, 70 + i * 30);
}
cans.rotate((20 * Math.PI) / 180); //恢复旋转角度
if (IEVersion() === -1) {
//如果是ie10以外的浏览器
const box = document.createElement('div');
box.style.cssText = `background-image: url(${can.toDataURL(
'image/png'
)});background-repeat:repeat;position:absolute;top:0;bottom:0;left:0;right:0;pointer-events:none;z-index:99;`;
sel.appendChild(box);
} else {
//ie10
sel.style.cssText = `background-image: url(${can.toDataURL(
'image/png'
)});background-repeat:repeat;`;
}
}

//调用
setWaterMarker(
[
state.userInfo.principal.username,
state.userInfo.principal.certNo,
'192.168.1.23',
formatDate(new Date(), 'yyyy-MM-dd HH:mm')
],
'.container',
'rgba(255,255,255,0.2)'
);

(掘金的编辑器真是太烂了,从vscode复制出来就乱成一坨)

效果


如此已完成了所有需求,但还是存在一个问题。假如用户是一个开发人员,他可能会在控制台将轻易水印去除掉,目前我还没有找到相应的解决方案。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值