vue 常用ui库element-ui是没有水印功能的,下面我们就按照ant design里面水印功能进行开发vue 水印,
关于需求(ant design做到了那些细节):
1.设置的文字最终以图片的形式呈现
2.实现点击穿透(不影响用户正常页面交互)
3.在控制台中不可对水印进行改动和删除
构思
关于设置文字的以图片的形式呈现,我们可以根据传进来的文字进行canvas绘制成图片然后以backgrund-image平铺的形式展示,实现点击穿透可以考css实现,对水印进行防删防篡改的功能需要通过MutationObserver进行监听
废话不多说直接上干货如果你的项目是vue版本是3.x那么小编已经将写好的插件上传到npm上,可以使用插件
属性 | 参数 |
---|---|
font | String(默认20) |
color | String(默认red) |
text | String(默认水印生成) |
npm i t-watermark
// main.js
import Vue, { createApp } from 'vue'
import App from './App.vue'
import TWatermark from 't-watermark'
import 't-watermark/t-watermark.css'
const app = createApp(App)
app.use(TWatermark)
app.mount('#app')
<template>
<div>
<t-watermark text="水印防盗" font="20" color="red">
<p style="width: 1000px;height: 1000px;">ssss</p>
</t-watermark>
</div>
</template>
<script>
export default{
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
来看实际效果图
关于代码
如果说npm的插件不满足你的需求下面就是代码的开源 ,可以根据实际需求进行修改
<template>
<div class="watermark-container" id="watermarkRef">
<canvas ref="canvas" :width="width" :height="height"></canvas>
<slot></slot>
</div>
</template>
<script setup >
import { ref, onMounted, onUnmounted,defineProps } from 'vue';
const props = defineProps({
text:{
type:String,
default:'水印生成'
},
font:{
type:String,
default:'30'
},
color:{
type:String,
default:'red'
},
})
const width = ref(200);
const height = ref(150);
const drawWatermark = () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.font = `${props.font}px Arial`;
ctx.fillStyle = props.color;
ctx.translate(width.value / 2, height.value / 2);
ctx.rotate(Math.PI / 12);
ctx.fillText(props.text, -ctx.measureText(props.text).width / 2, 0);
const img = canvas.toDataURL('image/png');
const div = document.createElement('div');
div.classList.add('Watermark');
div.style.position = 'absolute';
div.style.left = 0;
div.style.right = 0;
div.style.top = 0;
div.style.bottom = 0;
div.style.zIndex = '9999';
div.style.pointerEvents = 'none';
div.style.backgroundRepeat = 'repeat';
div.style.backgroundImage = `url(${img})`;
watermarkRef.value.append(div)
};
const watermarkRef = ref();
const fn = ref(null);
onMounted(() => {
watermarkRef.value = document.getElementById('watermarkRef')
drawWatermark();
fn.value = new MutationObserver((event) => {
for (const entry of event) {
for (const node of entry.removedNodes) {
if (node.className === 'Watermark') {
drawWatermark();
}
}
if (entry.target.className === 'Watermark') {
drawWatermark();
}
}
});
fn.value.observe(watermarkRef.value, {
childList: true,
subtree: true,
attributes: true
});
});
onUnmounted(() => {
fn.value.disconnect();
});
</script>
<script >
export default{
name:'t-watermark'
}
</script>
<style scoped>
.watermark-container {
position: relative;
display: inline-block;
}
</style>