一个无法删除的水印组件
完整源码:github.com/wstreet/wat…
查看效果:wstreet.vip
Canvas学习:www.yuque.com/streetex/fb…
Installation
# use npm
npm install @wstreet7/watermark --save
# or use yarn
yarn add @wstreet7/watermark
# or script
<script src="https://unpkg.com/@wstreet7/watermark@latest/lib/watermark.min.js"></script>
Usage
Simple Example
import WaterMark from '@wstreet7/watermark';
const config = {
text: '@wstreet7',
height: 60,
width: 100
}
const waterMark = new WaterMark(config)
Config
| 字段 | 描述 | 默认值 |
|---|---|---|
| id | container的id | water-mark |
| height | 每个repeat单元的height | 100 |
| width | 每个repeat单元的width | 150 |
| font | 字体相关,font-size和font-family必须包含 | 10px sans-serif 其他配置 |
| rotate | 文本倾斜角度 | -30(canvas 正旋转为顺时针) www.yuque.com/streetex/fb… |
| fillStyle | 文本颜色 | #ccc |
| opacity | 透明度 | 1.0 |
| zIndex | z-index | 9999 |
实现思路
1、绘制canvas并将canvas转换成图片设置为背景
2、监听dom水印是否被删除或者修改,如果是,则再执行第1步
生成canvas并转换成图片很好理解,这里讲一下监听dom被修改的逻辑
水印是直接插入在body下的,需要监听watermark dom和body:
监听watermark dom如果被修改(childList,attributes,characterData),直接删除就行
监听body childList的变化,如果是删除了水印,则再绘制一次
const MutationObserver = window.MutationObserver
|| window.WebKitMutationObserver
|| window.MozMutationObserver;
class WaterMark {
defaultOpts = {
id: 'water-mark',
height: 100,
width: 150,
font: '10px sans-serif',
rotate: -30,
fillStyle: '#ccc',
opacity: 1.0,
text: '',
zIndex: 9999
}
constructor(options) {
this._cfg = {...this.defaultOpts, ...options}
this.createObserver()
this.createCanvas()
this.load()
}
set(key, value) {
this._cfg[key] = value
}
get(key) {
return this._cfg[key]
}
createObserver() {
this.createDomObserver()
this.createBodyObserver()
}
// 水印的载体div
createDomObserver() {
this.observer = new MutationObserver(() => {
this.remove()
});
}
createBodyObserver() {
this.bodyObserver = new MutationObserver((mutationList) => {
if (
mutationList[0].removedNodes.length &&
mutationList[0].removedNodes[0].id === this.get('id')
) {
this.load()
}
});
}
createCanvas() {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
const height = this.get('height')
const width = this.get('width')
canvas.height = height
canvas.width = width
const font = this.get('font')
const text = this.get('text')
const rotate = this.get('rotate')
const fillStyle = this.get('fillStyle')
const opacity = this.get('opacity')
ctx.fillStyle = fillStyle
ctx.font = font;
ctx.globalAlpha = opacity;
ctx.rotate(rotate / Math.PI * 2)
ctx.translate(0, height / 2)
ctx.fillText(text, 0, height / 2 )
this.set('canvas', canvas)
this.set('ctx', ctx)
}
observe() {
this.domObserve()
this.bodyObserve()
}
domObserve() {
const dom = this.get('dom');
this.observer.observe(dom, {
childList: true,
attributes: true,
characterData: true,
})
}
bodyObserve() {
const body = document.querySelector('body')
this.bodyObserver.observe(body, {
childList: true
})
}
remove() {
const body = document.querySelector('body')
const dom = this.get('dom')
body.removeChild(dom)
this.set('dom', null)
}
load() {
const canvas = this.get('canvas')
const img = canvas.toDataURL('image/png', 1.0)
const body = document.querySelector('body')
const dom = document.createElement('div')
dom.setAttribute('id', this.get('id'))
dom.setAttribute('style',
`
background-image:url(${img});
height: 100%;
position: fixed;
left: 0;
top: 0;
bottom: 0;
right: 0;
pointer-events: none;
z-index: ${this.get('zIndex')}
`
)
this.set('dom', dom)
body.appendChild(dom)
this.observe()
}
}
export default WaterMark