700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 前端页面添加全局水印或指定页面添加水印

前端页面添加全局水印或指定页面添加水印

时间:2021-07-21 23:03:39

相关推荐

前端页面添加全局水印或指定页面添加水印

前言

为了防止信息泄露或知识产权被侵犯,在web的世界里,对于图片文档等增加水印处理是十分有必要的。水印的添加根据环境可以分为两大类,前端浏览器环境添加和后端服务环境添加。

今天介绍的就是通过canvas创建一张含有水印信息的背景图片,通过vue指令插入到页面中。

配置

在vue项目中创建waterMark.ts文件

对外接口

清除水印(clear)设置水印(setWatermark)初始化加载水印(loadingWatermark)

核心功能函数

绘制文字背景图(createBase64)绘制水印层(createWatermark)页面随窗口大小调整更新(updateWatermark)初始化加载水印(loadingWatermark)

export function useWatermark(appendEl: Ref<HTMLElement | null> = ref(document.body) as Ref<HTMLElement>) {// 绘制文字背景图function createBase64() {}// 绘制水印层const createWatermark = () => {};// 页面随窗口调整更新水印function updateWatermark(){}// 对外提供的设置水印方法function setWatermark() {}// 清除水印const clear = () => {};//初始化加载水印const loadingWatermark() {}//方便传参预定义一个类型,可自行再扩展type attr = {font?: string;//字体fontSize?: string; //字体大小fillStyle?: string; //水印颜色width?:Number;//宽度height?:Number;//高度fillText?:string; //水印文本};return { setWatermark, clear, loadingWatermark };}

基本代码框架如上,也可自行添加

绘制文字背景图

function createBase64(item?: attr) {const can = document.createElement("canvas");const width = item?.width ?? 300;const height = item?.height ?? 240;const font = attr?.fontSize ?? "12px"+" "+attr?.font ?? "Reggae One";Object.assign(can, { width, height });const cans = can.getContext("2d");if (cans) {cans.rotate((-20 * Math.PI) / 120);cans.font = font;cans.fillStyle = attr?.fillStyle ?? "rgba(0, 0, 0, 0.12)";cans.textAlign = attr?.textAlign ?? "left";cans.textBaseline =attr?.textBaseline ?? "middle";cans.fillText(attr?.fillText, width / 20, height);}return can.toDataURL("image/png");}

绘制水印层

这个函数的主要逻辑是先判断如果已经绘制了水印层,直接调用更新水印方法,如果还没有,先动态创建一个 DIV 层,设置绝对定位,铺满当前整个浏览器窗口。

const id = domSymbol.toString();const watermarkEl = shallowRef<HTMLElement>();const createWatermark = (item?: attr) => {if (unref(watermarkEl)) {updateWatermark({ str, attr });return id;}const div = document.createElement("div");watermarkEl.value = div;div.id = id;div.style.pointerEvents = "none";div.style.top = "0px";div.style.left = "0px";div.style.position = "absolute";div.style.zIndex = "100000";const el = unref(appendEl);if (!el) return id;const { clientHeight: height, clientWidth: width } = el;updateWatermark({ item.fillText, width, height, attr });el.appendChild(div);return id;};

更新水印

因为更新水印方法主要是根据当前窗口高度和宽度来的更新水印背景的设置,利用一张 Base64 格式的图片平铺即可。

function updateWatermark(options: {width?: number;height?: number;item?: attr;} = {}) {const el = unref(watermarkEl);if (!el) return;if (options.width !== "undefined") {el.style.width = `${options.width}px`;}if (ioptions.height !== "undefined") {el.style.height = `${options.height}px`;}if (options.item?.fillText!== "undefined") {el.style.background = `url(${createBase64(options.item)}) left top repeat`;}}

到此,我们实现了主要的三个功能函数,下面就是两个对外接口:

设置水印

这里的主要点是考虑设置页面resize监听,来及时更新水印的位置。还要考虑 Vue 的生命周期,当我们卸载页面的时候要进行清除水印。

function setWatermark(attr?: attr) {createWatermark(attr);addResizeListener(document.documentElement, func);const instance = getCurrentInstance();if (instance) {onBeforeUnmount(() => {clear();});}}const func = throttle(function () {const el = unref(appendEl);if (!el) return;const { clientHeight: height, clientWidth: width } = el;updateWatermark({ height, width });});

清除水印

清除水印的时候顺便移除窗口大小监听函数

const clear = () => {const domId = unref(watermarkEl);watermarkEl.value = undefined;const el = unref(appendEl);if (!el) return;domId && el.removeChild(domId);removeResizeListener(el, func);};//在添加水印后切换页面可能会导致 domId为undefined,这边还提供另外一种清除水印的方法const clear1 = () => {const domId=document.getElementById(id);watermarkEl.value = undefined;const el = unref(appendEl);if (!el) return;domId && el.removeChild(domId);removeResizeListener(el, func);};const clear2 = () => {if (document.getElementById(id) !== null) {document.body.removeChild(document.getElementById(id));}};

全局使用或者指定页面

通过在设置水印的参数的时候预留的路由数组来判断,此方法可预留可不预留。下面提供了两种方式

//怎么保存设置看个人,只要方便操作就可以//watermarkPagesInvolved是我存储路由的数组,dicMenu是调用方法的时候传进来的当前页面路由function LoadingsetWatermark(item?: attr, dicMenu?: string) {if (res.watermarkPagesInvolved.indexOf(dicMenu) != -1) {createWatermark(res as any);} else {clear();}}

水印功能的使用

import { useWatermark } from "/@/hooks/watermark";import { defineComponent } from 'vue';export default defineComponent({components: {useWatermark,},data() {return{/**水印设置 */formWater: {//文本filterText: '',//颜色color: '',//字体font: 'Vedana',//字体大小fontSize: 15,//垂直对齐textBaseline: 'middle',//水平对齐textAlign: 'left',//宽width: 300,//高height: 240,}}},})onMounted(() => {const { setWatermark, clear } = useWatermark();nextTick(() => {setWatermark(formWater);});});onBeforeUnmount(() => {clear();});

指定页面使用

方式1,使用预留的方法

1,在设置水印的时候预留一个数组来存储想要展示页面的路由2,在App.vue或者mian.ts中监听路由的变化,我这边使用的是在App.vue监听

import { useWatermark } from './hooks/web/useWatermark';import { useRouter } from 'vue-router';const { LoadingsetWatermark } = useWatermark();const $router = useRouter();watch(() => $router.currentRoute.value.name,(newValue, oldValue) => {console.log(!newValue ? oldValue.toString() : newValue.toString());LoadingsetWatermark(!newValue ? oldValue.toString() : newValue.toString());},);

方式二,不使用预留的方法

直接在App.vue或者main.ts判断是否创建水印

watch:{$route:{handler (val, oldval) {let paths = ['/login', '/404', '/403', '/500']this.$nextTick(() => {if (paths.includes(val.path)) { //如果是以上url 则 不需要水印let my = document.getElementById("frame")my && my.parentNode.removeChild(my)} else if ((!paths.includes(val.path) && paths.includes(oldval.path)) || (!paths.includes(val.path) && oldval.path === '/')) {this.$nextTick(() => {this.watermark()})} else if (!(paths.includes(val.path) && paths.includes(oldval.path)) && !document.getElementById("frame")) {this.$nextTick(() => {this.watermark()})}})},// 深度观察监听// deep: true}},watermark() {// 认设置let info = getStore({name: 'userInfo'})if (isNull(info)) {return}let defaultSettings = {watermarl_element: "avue-view", // 要绘制元素的容器idwatermark_txt: `${info.userName}-<br/>`,watermark_img: '',watermark_x: 20, // 水印起始位置x轴坐标watermark_y: 50, // 水印起始位置Y轴坐标watermark_rows: 5, // 水印行数watermark_cols: 3, // 水印列数watermark_x_space: 100, // 水印x轴间隔watermark_y_space: 50, // 水印y轴间隔watermark_color: '#3e7ff7', // 水印字体颜色watermark_alpha: 0.2, // 水印透明度watermark_fontsize: '20px', // 水印字体大小watermark_font: '微软雅黑', // 水印字体watermark_width: 350, // 水印宽度watermark_height: 120, // 水印长度watermark_angle: 15 // 水印倾斜度数}let oTemp = document.createDocumentFragment();let maskElement = document.getElementsByClassName(defaultSettings.watermarl_element)[1] || document.body;//获取页面最大宽度let page_width = Math.min(maskElement.scrollWidth, maskElement.clientWidth);//获取页面最大高度let page_height = Math.min(maskElement.scrollHeight, maskElement.clientHeight);//水印数量自适应元素区域尺寸defaultSettings.watermark_cols = Math.ceil(page_width / (defaultSettings.watermark_x_space + defaultSettings.watermark_width));defaultSettings.watermark_rows = Math.ceil(page_height / (defaultSettings.watermark_y_space + defaultSettings.watermark_height));let xlet ylet frame = document.createElement('div')frame.setAttribute('id', 'frame')oTemp.appendChild(frame)for (var i = 0; i < defaultSettings.watermark_rows; i++) {y = defaultSettings.watermark_y + (defaultSettings.watermark_y_space + defaultSettings.watermark_height) * ifor (var j = 0; j < defaultSettings.watermark_cols; j++) {x = defaultSettings.watermark_x + (defaultSettings.watermark_width + defaultSettings.watermark_x_space) * jlet mask_div = document.createElement('div')mask_div.id = 'mask_div' + i + jmask_div.className = 'mask_div';// mask_img.className = 'mask_img';//mask_div.appendChild(document.createTextNode(defaultSettings.watermark_txt));mask_div.innerHTML = (defaultSettings.watermark_txt);// mask_img.src = defaultSettings.watermark_img;// mask_img.style.width = "150px";// mask_img.style.height = "50px";// 空白图片会有占位,判断src为空时移除img标签 不为空时添加img// if(defaultSettings.watermark_img == ""){// mask_div.remove(mask_img);// }else{// mask_div.append(mask_img);// }//设置水印div倾斜显示mask_div.style.transform = "rotate(-" + defaultSettings.watermark_angle + "deg)"mask_div.style.visibility = ""mask_div.style.position = "absolute"mask_div.style.left = x + 'px'mask_div.style.top = y + 'px'mask_div.style.overflow = "hidden"mask_div.style.zIndex = "9999"mask_div.style.pointerEvents = 'none'//pointer-events:none 让水印不遮挡页面的点击事件//mask_div.style.border="solid #eee 1px"//兼容IE9以下的透明度设置// mask_div.style.filter="alpha(opacity=50)";mask_div.style.opacity = defaultSettings.watermark_alphamask_div.style.fontSize = defaultSettings.watermark_fontsizemask_div.style.fontFamily = defaultSettings.watermark_fontmask_div.style.color = defaultSettings.watermark_colormask_div.style.textAlign = "center"mask_div.style.width = defaultSettings.watermark_width + 'px'mask_div.style.height = defaultSettings.watermark_height + 'px'mask_div.style.display = "block"frame.appendChild(mask_div)}}maskElement.appendChild(oTemp)}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。