今天分享一个使用JavaScript原生编写的水印背景的效果
实现思路
首先动态创建一个div,通过绝对或相对定位的方式将div放在需要添加水印的元素上。随后动态创建一个canvas,在里面绘制自定义的字体,并倾斜45度,然后通过canvas.toDataURL()方法导出base64码图。最后将此图片放在元素遮罩层上做背景即可。
具体实现
基本工作,准备好相关html代码
<style>
#container{
width: 700px;
height: 700px;
display: flex;
margin: auto;
align-items: center;
border: 1px solid #ccc;
position: relative;
}
#container button{
margin: auto;
}
</style>
<div id="container">
<button>大家好,我是水印底下的按钮,你们点不到我,嘻嘻</button>
</div>
1、首先编写动态创建canvas的方法,并将canvas的相关内容返回
/**
* 创建canvas并绘制相关字体
* @params {*} text 自定义的字体
* @returns {*} canvas宽 - canvas的base64
*/
function MakeWaterMark(text){
const canvas = document.createElement("canvas");
// devicePixelRatio:查看浏览器设备的缩放比例
const Pixel = window.devicePixelRatio || 1;
const fontsize = 18 * Pixel;
const ctx = canvas.getContext("2d");
// 通过字体的多少动态计算宽高
const { width } = ctx.measureText(text);
// 取最大值
const canvasWidth = Math.max(100,width) * Pixel;
canvas.width = canvasWidth;
canvas.height = canvasWidth;
ctx.translate(canvasWidth / 2 , canvasWidth / 2);
// 旋转45度
ctx.rotate(45);
ctx.font = `${fontsize}px 宋体`;
ctx.fillStyle = "rgba(0,0,0,0.3)";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(text,0,0)
return{
base64:canvas.toDataURL(),
size:canvasWidth
}
}
2、然后创建遮罩层div元素,并将此div放在需要添加水印的元素上
/**
* 创建加载水印
* @params {*} parentNode:需要添加水印的元素
*/
function loadMark(parentNode){
let {base64,size} = MakeWaterMark("峰少1618");
const div = document.createElement("div");
div.style.backgroundImage = `url(${base64})`;
div.style.backgroundSize = `${size}px,${size}px`;
div.style.backgroundRepeat = "repeat";
div.style.position = "absolute"
div.style.zIndex = '9999';
div.style.inset = 0;
div.id = "watermark";
parentNode.appendChild(div);
}
此时,水印已经创建成功了,但是有时候,我们遇到同行时难免会有打开控制台删除元素的操作,因此,可以使用MutationObserver监听器来将水印元素实时监听起来,查看他的元素在每个时刻发生的变化。
在刚才的loadMark方法中添加如下代码:
// 声明一个监听器
let ob = null;
ob = new MutationObserver((recodrs)=>{
if(recodrs[0].type == "attributes"){
alert("当前元素属性发生变化")
}
if(recodrs[0].type == "childList"){
for (const key of recodrs[0].removedNodes) {
if(key.id == 'watermark'){
alert("水印被删除")
//解除监听绑定,此处必须解除绑定,不然会陷入死循环
ob.disconnect()
ob = null;
loadMark(parentNode)
}
}
}
})
// parentNode要添加水印的父节点,就是loadMark()方法传来的参数
ob.observe(parentNode,{
childList : true, //监听元素的内容是否有变化
attributes : true, //监听元素的属性有没有变化
subtree : true //监听元素的字树有没有变化
})
此时水印才算真正安全了,当有人从控制台删除水印时,MutationObserver监听器监听的元素属性发生的变化时,就会迅速做出反应。
实现效果
好了,水印这块就分享这些了
如果看到的小伙伴有新的需求,还没什么思路,但是和这里的效果有关系,可以私信我,咱们一起想办法总比一个人想要好很多吧
当然大家有更好的实现水印逻辑,可以提出来,大家一起进步喽!!!