vue添加水印
# vue添加水印
# WaterMark指令
const watermark = {
text: 'text',
style: {},
isAllowDele: false,
maskDiv: '',
init: (text) => {
const canvas = document.createElement('canvas')
canvas.id = 'canvas'
canvas.width = watermark.style.width // 单个水印的宽高
canvas.height = watermark.style.height
watermark.maskDiv = document.createElement('div')
const ctx = canvas.getContext('2d')
ctx.font = watermark.style.font // 设置样式
ctx.fillStyle = watermark.style.fillStyle // 水印字体颜色
ctx.rotate(watermark.style.rotate) // 水印偏转角度
// convas 设置换行
CanvasRenderingContext2D.prototype.wrapText = function (
text,
x,
y,
maxWidth,
lineHeight
) {
if (
typeof text != 'string' ||
typeof x != 'number' ||
typeof y != 'number'
) {
return
}
const context = this
const canvas = context.canvas
if (typeof maxWidth == 'undefined') {
maxWidth = (canvas && canvas.width) || watermark.style.width
}
if (typeof lineHeight == 'undefined') {
lineHeight =
(canvas && parseInt(window.getComputedStyle(canvas).lineHeight)) ||
parseInt(window.getComputedStyle(document.body).lineHeight)
}
// 字符分隔为数组
const arrText = text.split('')
let line = ''
for (var n = 0; n < arrText.length; n++) {
let testLine = line + arrText[n]
let metrics = context.measureText(testLine)
let testWidth = metrics.width
if (testWidth > maxWidth && n > 0) {
context.fillText(line, x, y)
line = arrText[n]
y += lineHeight
} else {
line = testLine
}
}
context.fillText(line, x, y)
}
ctx.wrapText(watermark.text, 30, 20)
const src = canvas.toDataURL('image/png')
watermark.maskDiv.style.position = 'fixed'
watermark.maskDiv.style.zIndex = '9999'
watermark.maskDiv.id = '_waterMark'
watermark.maskDiv.style.top = '0'
watermark.maskDiv.style.left = '0'
watermark.maskDiv.style.height = '100%'
watermark.maskDiv.style.width = '100%'
watermark.maskDiv.style.pointerEvents = 'none'
watermark.maskDiv.style.backgroundImage = 'URL(' + src + ')'
// 水印节点插到body下
document.body.appendChild(watermark.maskDiv)
},
// 防删机制
monitor: () => {
const body = document.getElementsByTagName('body')[0]
const options = {
childList: true,
attributes: true,
characterData: true,
subtree: true,
attributeOldValue: true,
characterDataOldValue: true
}
const observer = new MutationObserver(watermark.callback)
observer.observe(body, options) // 监听body节点
},
// DOM改变执行callback
callback: (mutations, observer) => {
// 当attribute属性被修改
if (mutations[0].target.id === '_waterMark') {
watermark.removeMaskDiv()
}
// 当id被改变时
if (mutations[0].attributeName === 'id') {
watermark.removeMaskDiv()
watermark.init()
}
// 当节点被删除
if (
mutations[0].removedNodes[0] &&
mutations[0].removedNodes[0].id === '_waterMark'
) {
watermark.init()
}
},
// 手动销毁水印DOM
removeMaskDiv: () => {
document.body.removeChild(watermark.maskDiv)
},
render: () => {
// let maskBox = document.querySelector('#_waterMark');
if (!watermark.maskDiv) {
watermark.init()
// 是否允许通过js或开发者工具等途径修改水印DOM节点(水印的id,attribute属性,节点的删除),true为允许, 默认不允许
if (!watermark.isAllowDele) {
// 设置水印节点修改的DOM事件
watermark.monitor()
}
}
}
}
export default {
bind(el, binding, vnode) {
const options = binding.value
watermark.style = options.style
watermark.text = options.text
watermark.isAllowDele = options.isAllowDele
watermark.render()
},
update(element, data) {
if (data.value.text !== data.oldValue.text) {
watermark.text = data.value.text
watermark.removeMaskDiv()
watermark.render()
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# 使用
<template>
<router-view v-waterMark="waterCode"></router-view>
</template>
<script>
import waterMark from 'common/utils/watermark'
export default {
directives: {
waterMark
},
computed: {
waterCode() {
return {text: `平台机密数据`,
style: {
'width': 700, // 单个水印的宽
'height': 300, // 单个水印的高
'font': 'normal 22px Microsoft Yahei', // 设置样式
'fillStyle': 'rgba(112, 113, 114, 0.1)', // 水印字体颜色
'rotate': (30 * Math.PI / 180) // 水印偏转角度
}
}
}
}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
编辑 (opens new window)
上次更新: 2022/05/26, 11:38:11