最近遇到个给页面添加水印的需求(之前没弄过也没见过这种效果),然后组长还要求我使用指令的方式实现,做到水印内容、样式基本可配置,说是以后再有这种需求的话就不用再开发了(嗯,道理我都懂,就是有点儿迷茫…)
先去vue官网看看自定义指令:
有了钩子和钩子参数,具体的就是怎么实现水印效果了。这里采用的是 canvas 的方式,具体的:
'use strict';exports.__esModule = true;/*** 自定义指令'v-watermark'* 可以传入自定义参数(v-watermark="markObj"),参数(markObj)格式为* {*text: '水印内容', // 水印文字内容*angle: 25, // 水印倾斜度*color: 'rgba(0,0,0,.15)', // 水印文字颜色*fontSize: '16px', // 水印文字大小*top: 70 // 水印区域距离浏览器可视区域顶部的距离,单位px* }* 参数是可选的,不传的时候可以直接使用 v-watermark 指令即可*/// 记录上一次生成水印的 div 元素 idlet prevDivId = 0;const number180 = 180;// 生成水印const setWatermark = markObj => {// 默认设置const defaultObj = {text: '水印内容',angle: 25,color: 'rgba(0,0,0,.15)',fontSize: '16px',top: 70}Object.assign(defaultObj, markObj);// 角度转成负数defaultObj.angle = -Math.abs(defaultObj.angle);// 随机生成一个 idconst id = Math.random();// 清除上次的水印 div[解决:窗口大小调整时(onresize方法)水印会叠加,导致颜色加深的问题]if(prevDivId && document.getElementById(prevDivId) !== null) {document.body.removeChild(document.getElementById(prevDivId));}// 记录 idprevDivId = id;// 创建画布const canvas = document.createElement('canvas');// 设置画布的长、宽canvas.width = 240;canvas.height = 180;const context = canvas.getContext('2d');// 旋转角度(以弧度计)context.rotate((defaultObj.angle*Math.PI)/number180);context.font = defaultObj.fontSize + ' 微软雅黑';// 设置填充绘画的颜色、渐变或者模式context.fillStyle = defaultObj.color;context.textAlign = 'left';context.textBaseline = 'middle';context.fillText(defaultObj.text, 0, canvas.height);const div = document.createElement('div');div.id = prevDivId;div.style.pointerEvents = 'none';div.style.position = 'absolute';div.style.top = defaultObj.top + 'px';div.style.left = '0px';div.style.zIndex = '9999';div.style.width = document.documentElement.scrollWidth + 'px';div.style.height = document.documentElement.scrollHeight + 'px';div.style.background = 'url('+canvas.toDataURL('image/png')+') left top repeat';document.body.appendChild(div);return prevDivId;}exports.default = {bind: function bind(binding) {setWatermark(binding.value || {});// 监听窗口变化事件window.onresize = () => {if(prevDivId !== 0) {setWatermark(binding.value || {});}}// 监听页面滚动window.onscroll = () => {if(prevDivId !== 0) {setWatermark(binding.value || {});}}},unbind: function unbind() {document.body.removeChild(document.getElementById(prevDivId));prevDivId = 0;}}
在需要使用指令的页面引入 js 文件,然后在 directive 里注册指令,就可以直接在 dom 元素上使用了(比如:注册的自定义指令名为 watermark ,使用 v-watermark 就可以),如果需要传入参数,可以将参数对象传入自定义指令(比如:v-watermark=“markObj")。