vue实现水印组件
Vue 水印组件的实现方法
使用Canvas绘制水印
在Vue组件中通过Canvas动态生成水印图案,将其作为背景添加到目标元素上。
<template>
<div ref="watermarkContainer" class="watermark-container"></div>
</template>
<script>
export default {
props: {
text: { type: String, default: 'Watermark' },
fontSize: { type: Number, default: 16 },
color: { type: String, default: 'rgba(0, 0, 0, 0.1)' },
angle: { type: Number, default: -20 }
},
mounted() {
this.generateWatermark()
},
methods: {
generateWatermark() {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = 200
canvas.height = 150
ctx.font = `${this.fontSize}px Arial`
ctx.fillStyle = this.color
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.translate(canvas.width / 2, canvas.height / 2)
ctx.rotate((this.angle * Math.PI) / 180)
ctx.fillText(this.text, 0, 0)
const dataURL = canvas.toDataURL()
this.$refs.watermarkContainer.style.backgroundImage = `url(${dataURL})`
this.$refs.watermarkContainer.style.backgroundRepeat = 'repeat'
}
}
}
</script>
<style>
.watermark-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 9999;
}
</style>
使用SVG实现水印
SVG方案更轻量且支持矢量缩放,适合需要清晰显示的场景。
<template>
<div
class="svg-watermark"
:style="{
'background-image': `url('data:image/svg+xml;utf8,${svgWatermark}')`
}"
></div>
</template>
<script>
export default {
props: {
text: { type: String, default: 'Confidential' },
opacity: { type: Number, default: 0.1 }
},
computed: {
svgWatermark() {
return encodeURIComponent(
`<svg xmlns="http://www.w3.org/2000/svg" width="200" height="100" viewBox="0 0 200 100">
<text x="50%" y="50%"
font-family="Arial"
font-size="16"
fill-opacity="${this.opacity}"
fill="#000"
text-anchor="middle"
dominant-baseline="middle"
transform="rotate(-20 100 50)">
${this.text}
</text>
</svg>`
)
}
}
}
</script>
防止水印被删除
通过MutationObserver监测DOM变化,当水印被移除时自动重新添加。
mounted() {
this.generateWatermark()
this.setupObserver()
},
methods: {
setupObserver() {
const targetNode = this.$refs.watermarkContainer.parentElement
const config = { childList: true, subtree: true }
const callback = (mutationsList) => {
for(const mutation of mutationsList) {
if (!document.body.contains(this.$refs.watermarkContainer)) {
document.body.appendChild(this.$refs.watermarkContainer)
}
}
}
this.observer = new MutationObserver(callback)
this.observer.observe(targetNode, config)
},
beforeDestroy() {
this.observer?.disconnect()
}
}
响应式水印方案
结合CSS变量和Vue响应式特性,实现动态调整水印参数。
<template>
<div
:style="{
'--watermark-content': `'${text}'`,
'--watermark-color': color,
'--watermark-opacity': opacity,
'--watermark-size': `${fontSize}px`
}"
class="css-watermark"
></div>
</template>
<style>
.css-watermark {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
background-image: repeating-linear-gradient(
-45deg,
transparent,
transparent 25px,
rgba(0, 0, 0, var(--watermark-opacity)) 25px,
rgba(0, 0, 0, var(--watermark-opacity)) 50px
);
}
.css-watermark::after {
content: var(--watermark-content);
position: absolute;
font-size: var(--watermark-size);
color: var(--watermark-color);
opacity: var(--watermark-opacity);
transform: rotate(-20deg);
}
</style>
服务端生成水印
对于敏感内容,建议结合后端服务生成带水印的图片。
async getProtectedImage(url) {
const response = await axios.get('/api/watermark', {
params: {
imageUrl: url,
text: this.watermarkText
},
responseType: 'blob'
})
return URL.createObjectURL(response.data)
}
以上方案可根据实际需求选择或组合使用,Canvas方案适合复杂水印效果,SVG方案性能更优,CSS方案最简单但功能有限。为防止用户篡改,建议配合MutationObserver和防调试策略。







