用 Canvas 画出一块文字图片,再把它作为透明图层的重复背景。下面的模块支持添加、替换和移除一个水印,不需要额外依赖。

创建水印模块

保存为 src/utils/watermark.js:

let watermarkElement = null
export const waterMark = {
set({ firText = '', secText = '', thirText = '' }, sourceBody = document.body) {
this.remove()
const canvas = document.createElement('canvas')
canvas.width = 300
canvas.height = 220
const ctx = canvas.getContext('2d')
if (!ctx) throw new Error('当前环境不支持 Canvas 2D')
ctx.translate(30, 110)
ctx.rotate(-20 * Math.PI / 180)
ctx.fillStyle = 'rgba(0, 0, 0, 0.12)'
ctx.textAlign = 'left'
ctx.textBaseline = 'middle'
ctx.font = '20px Verdana, sans-serif'
ctx.fillText(firText, 0, 0)
ctx.font = '16px Verdana, sans-serif'
ctx.fillText(secText, 0, 24)
ctx.fillText(thirText, 0, 48)
const layer = document.createElement('div')
layer.setAttribute('aria-hidden', 'true')
Object.assign(layer.style, {
position: sourceBody === document.body ? 'fixed' : 'absolute',
inset: '0',
zIndex: '1000',
pointerEvents: 'none',
backgroundImage: `url(${canvas.toDataURL('image/png')})`,
backgroundRepeat: 'repeat'
})
sourceBody.appendChild(layer)
watermarkElement = layer
},
remove() {
watermarkElement?.remove()
watermarkElement = null
}
}

textBaseline 的合法值是小写 middle。再次调用 set() 会替换旧图层;remove() 可以重复调用。Canvas 文字基线说明

在 Vue 3 页面中使用

set() 接收一个包含三行文字的对象:

<script setup>
import { onMounted, onBeforeUnmount } from 'vue'
import { waterMark } from '@/utils/watermark'
onMounted(() => {
waterMark.set({
firText: '内部文档',
secText: '演示账号',
thirText: '仅作预览'
})
})
onBeforeUnmount(() => waterMark.remove())
</script>

如果只给某个容器添加水印,把容器元素作为第二个参数传入,并为容器设置 position: relative。图层会覆盖该容器。

这是页面视觉水印,用户可以在开发者工具中移除。需要让下载图片或导出文件也带水印时,应在生成文件时写入。