前些时候遇到了预览文档或图片加水印的需要,看材料理解到,水印明显水印和暗水印两类,明水印容易实现但也容易破解,暗水印更平安实现也更简单。

需要:在用户预览合同的时候给预览合同图片增加水印,因为是后盾管理系统中的性能,就抉择了明水印来实现。

明水印的实现形式大抵有两种:

  • div实现
  • canvas背景图实现

上面是demo演示

index.html

<div id="app">    <img id="poster" src="./poster.jpeg" alt=""></div>

index.css

#app{    width: 400px;    margin:  0 auto;    position: relative;}#app #poster{    width: 100%;}

成果如下:

首先咱们试试用增加div的形式实现水印
markByDiv.js

function cssHelper(el, prototype) {    for (let i in prototype) {        el.style[i] = prototype[i]    }}function handleWaterMark(waterMkrText, waterMkrWidth, waterMkrHeight, target){    const { clientWidth, clientHeight } = target;    const columns = Math.ceil(clientWidth / waterMkrWidth);    const rows = Math.ceil(clientHeight / waterMkrHeight);    const shadow = document.createElement('div');    cssHelper(shadow, {        position: 'absolute',        fontSize: `16px`,        color: '#ffffff',        opacity: 0.3,        left: '0px',        top: '0px',        bottom: '0px',        right: '0px',        display: 'flex',        flexWrap: 'wrap' //可转行    })    for (let i = 0; i < columns * rows; i++) {        const item = document.createElement('div');        item.innerHTML = waterMkrText        cssHelper(item, {            flexBasis: `1/${columns}`, //几列            width: `${waterMkrWidth}px`,            height: `${waterMkrHeight}px`,            lineHeight: `${waterMkrHeight}px`,            transform: `rotate(-15deg)`,            userSelect: 'none', //禁用框选            whiteSpace: 'nowrap',            overflow: 'hidden',            textAlign: 'center'        });        shadow.appendChild(item)    }        target.parentNode.appendChild(shadow)}handleWaterMark('鬼灭之刃',80,80,document.getElementById('poster'))

成果实现如下:

实现思路:
1.生成和图片尺寸一样的shadow,通过相对定位盖在图片上
2.通过图片的尺寸和水印的尺寸计算出水印有几行几列
3.通过flex布局将水印排列到shadow上


再来试试canvas背景图实现水印

markByCanvas.js

function createWaterMark(waterMkrText, waterMkrWidth, waterMkrHeight) {    const angle = -20;    const canvas = document.createElement('canvas');    canvas.width = waterMkrWidth;    canvas.height = waterMkrHeight;    const ctx = canvas.getContext('2d');    ctx.clearRect(0, 0, waterMkrWidth, waterMkrHeight);    ctx.fillStyle = '#fff';    ctx.globalAlpha = 0.5;    ctx.font = `16px`    ctx.rotate(Math.PI / 180 * angle);    ctx.fillText(waterMkrText, 0, waterMkrHeight/2);    return canvas.toDataURL();}    const watermakr = document.createElement('div');    cssHelper(watermakr, {        position: 'absolute',        left: '0px',        top: '0px',        bottom: '0px',        right: '0px',        pointerEvents: 'none',        backgroundRepeat: 'repeat',        backgroundImage: `url(${createWaterMark('鬼灭之刃', 80, 80)})`    })    document.getElementById('app').appendChild(watermakr);

成果实现如下:

实现思路:
1.利用canvas 绘制一个水印
2.通过canvas.toDataURL() 来拿到文件流的url
3.将url填充在一个元素的背景中,设置背景图片的属性为repeat