前言
页面水印大家应该都不陌生,它可以用于验证数字媒体的来源和完整性,还可以用于版权保护和信息识别,这些信息可以在不影响媒体质量的情况下嵌入,并在需要时进行提取。本文将介绍如何在 vue 中通过插件和指令两种方式来实现水印效果,帮助大家更好的应用水印效果到你的项目中。
一、watermark-dom 插件
watermark.js 是基于 DOM
对象实现的 BS
系统的水印,确保系统保密性,安全性,降低数据泄密风险,简单轻量,支持多属性配置,动态计算水印,水印防被删(监听水印组件元素删除并重新添加,监听改变水印的属性并重新添加)。
1.1 特性
- 多属性配置,简单易上手;
- 动态计算水印;
- 水印防被删(监听水印组件元素删除并重新添加,监听改变水印的属性并重新添加);
- 支持
2
种导入使用:本地引用,npm
引用; - 水印测试工具:
testTool
工具; - 内置
3
种全局API
方法:init()
,load()
,remove()
; - 原理:
pointer-events
事件穿透属性,Shadow DOM
(影子DOM
),opacity
等。
1.2 安装
npm install watermark-dom
1.3 引入
import watermark from 'watermark-dom'
1.4 内置方法
1. watermark.init(setting)
这个方法用于初始化水印,可以设置水印的样式、内容和位置等参数。
栗子
watermark.init({
watermark_txt: '测试水印',
watermark_color: 'gray',
watermark_fontsize: '24px',
})
2. watermark.load(setting)
用于手动加载水印。
栗子
const options = {
watermark_txt: '测试水印',
watermark_color: 'gray',
watermark_fontsize: '24px',
}
watermark.load(options)
3. watermark.remove()
这个方法用于移除已加载的水印。
栗子
watermark.remove();
1.5 常用的属性和配置
watermark_id: 'wm_div_id', //水印总体的id
watermark_prefix: 'mask_div_id', //小水印的id前缀
watermark_txt:"测试水印", //水印的内容
watermark_x:20, //水印起始位置x轴坐标
watermark_y:20, //水印起始位置Y轴坐标
watermark_rows:0, //水印行数
watermark_cols:0, //水印列数
watermark_x_space:100, //水印x轴间隔
watermark_y_space:50, //水印y轴间隔
watermark_font:'微软雅黑', //水印字体
watermark_color:'black', //水印字体颜色
watermark_fontsize:'18px', //水印字体大小
watermark_alpha:0.15, //水印透明度,要求设置在大于等于0.005
watermark_width:100, //水印宽度
watermark_height:100, //水印长度
watermark_angle:15, //水印倾斜度数
watermark_parent_width:0, //水印的总体宽度(默认值:body的scrollWidth和clientWidth的较大值)
watermark_parent_height:0, //水印的总体高度(默认值:body的scrollHeight和clientHeight的较大值)
watermark_parent_node:null //水印插件挂载的父元素element,不输入则默认挂在body上
1.6 实例代码
<template>
<div style="height:100vh"></div>
</template>
<script>
import watermark from 'watermark-dom'
export default {
mounted() {
const watermarkText = '测试水印内容'
const options = {
watermark_txt: watermarkText,
watermark_color: 'gray',
watermark_fontsize: '14px',
watermark_alpha: 0.5,
watermark_angle: 15,
watermark_width: 100,
watermark_height: 20,
}
watermark.load(options)
},
}
</script>
实现效果
1.7 非全屏展示
watermark_parent_node
属性用于指定水印的父节点,即确定水印应该显示在哪个 DOM
元素的内部。通过设置 watermark_parent_node
属性,可以控制水印的显示位置和范围。例如,如果你想要将水印显示在特定的 div
元素内部,可以将该 div
元素作为 watermark_parent_node
。这样,水印将被限制在该 div
元素的范围内显示。
<template>
<div class="box">
<div class="topBox"></div>
<div id="watermarkId" class="cenBox"></div>
<div class="bomBox"></div>
</div>
</template>
<script>
import watermark from 'watermark-dom'
export default {
mounted() {
const watermarkText = '测试水印内容'
const options = {
watermark_txt: watermarkText,
watermark_color: 'gray',
watermark_fontsize: '14px',
watermark_alpha: 0.5,
watermark_angle: 15,
watermark_width: 100,
watermark_height: 20,
watermark_parent_node: 'watermarkId',
}
watermark.load(options)
},
}
</script>
<style scoped>
.box {
width: 100%;
height: 100vh;
}
.topBox {
height: 30vh;
background: cadetblue;
}
.cenBox {
height: 50vh;
}
.bomBox {
height: 20vh;
background: cornflowerblue;
}
</style>
实现效果
二、自定义指令实现
在处理水印效果时,一些人可能不愿意依赖插件。实际上,我们可以通过编写自定义指令的方法来实现这一效果,而非使用外部插件。
2.1 watermark.js 封装文件
import axios from 'axios'; // 引入axios库
import {API} from '@/apis/system/user'; // 引入用户API接口
import moment from "moment"; // 引入momentJs
// 生成包含水印文本的图片方法
function generateWatermark(text, fontSize, color) {
const canvas = document.createElement('canvas'); // 创建canvas元素
canvas.width = 300; // 设置canvas宽度
canvas.height = 160; // 设置canvas高度
const ctx = canvas.getContext('2d'); // 获取2D绘图上下文
ctx.font = `${fontSize}px Arial`; // 设置字体大小和字体样式
ctx.fillStyle = color; // 设置字体颜色
ctx.translate(20, canvas.height - 20); // 平移坐标原点
ctx.rotate(-Math.PI / 6); // 旋转角度
const currentTime = moment().format("YYYY-MM-DD HH:mm:ss");
const watermarkText = text ? `${text} ${currentTime}` : `Watermark ${currentTime}`;
ctx.fillText(watermarkText, 0, 0); // 绘制文本
return canvas.toDataURL('image/png'); // 将canvas内容转换为base64格式的图片
}
//应用水印到指定元素
// el:要添加水印的元素、color:字体颜色、text:水印文本、fontSize:字体大小
function applyWatermark(el, text, fontSize, color) {
const watermarkUrl = generateWatermark(text, fontSize, color);
const watermarkLayer = document.createElement('div');
watermarkLayer.style.cssText = `
position: absolute;
top: 0;
left: 0;
z-index:9999;
width:100%;
height: 100%;
background-image: url(${watermarkUrl});
background-repeat: repeat;
pointer-events: none;
`;
el.style.position = 'relative'; // 应用样式
el.appendChild(watermarkLayer); // 将水印层添加到元素中
}
export default {
bind(el, binding, vnode) {
const defaultText = '默认水印'; // 默认水印文本
const defaultFontSize = 16; // 默认字体大小
const defaultColor = 'rgba(0, 0, 0, 0.15)'; // 默认字体颜色
const text = binding.value && binding.value.text ? binding.value.text : null; // 获取用户传入的文本内容
const fontSize = binding.value && binding.value.fontSize ? binding.value.fontSize : defaultFontSize; // 获取用户传入的字体大小
const color = binding.value && binding.value.color ? binding.value.color : defaultColor; // 获取用户传入的字体颜色
if (text) {
applyWatermark(el, text, fontSize, color); // 用户传入参数时显示用户传入的参数
} else {
axios.get(API.POST_DEVICE_CONFIG)
.then(res => {
if (res.data.code === '0') {
const userName = res.data.data[0].ii;
const watermarkText = userName ? `${userName}` : defaultText;
applyWatermark(el, watermarkText, defaultFontSize, defaultColor);
} else {
applyWatermark(el, defaultText, defaultFontSize, defaultColor); // 接口请求失败或没有返回数据时使用默认参数
}
})
.catch(error => {
console.error(error);
applyWatermark(el, defaultText, defaultFontSize, defaultColor); // 接口请求失败时使用默认参数
});
}
},
unbind(el) {
el.removeChild(el.lastChild);
}
}
以上这段代码就实现了简单的一个页面水印自定义指令。首先我们定义了 generateWatermark
方法,用于生成包含水印文本和当前时间的图片。然后定义了 applyWatermark
方法,将生成的水印图片作为背景应用到指定元素上。在 vue
自定义指令中,通过 bind
钩子函数实现逻辑:优先显示用户传入的参数作为水印文本,如果用户未传入参数,则通过接口请求获取用户信息,并将用户名作为水印文本显示。如果接口请求失败或没有返回数据,则使用默认的水印文本。最后,在 unbind
钩子函数中实现移除水印效果的逻辑。
2.2 main.js 入口文件
注册水印自定义指令到 vue
实例。
import watermarkFile from './utils/watermark'
Vue.directive('watermark', watermarkFile)
2.3 使用
-
不传参的写法
<div v-watermark>占位内容</div>
实现效果
-
传参的写法
<div v-watermark="{ text: '传入水印', fontSize: 14, color: 'red' }">占位内容</div>
实现效果