Vue3?實(shí)現(xiàn)網(wǎng)頁背景水印功能的示例代碼
經(jīng)常有一些公司和組織出于系統(tǒng)文件或信息安全保密的需要,需要在系統(tǒng)網(wǎng)頁上增加帶有個(gè)人標(biāo)識(shí)(系統(tǒng)賬號(hào)或個(gè)人信息)的水印,可以簡(jiǎn)單防止截圖外傳
首先我們來看這樣一個(gè)水印功能的實(shí)現(xiàn)思路,通常是在我們?cè)械木W(wǎng)頁上附上一個(gè) DIV 層,將它設(shè)置絕對(duì)定位鋪滿整個(gè)窗口,然后 z-index 值盡量往大了設(shè),保證讓水印層處于當(dāng)前網(wǎng)頁所有元素的上面,又不影響當(dāng)前網(wǎng)頁的操作。
水印上的字體有兩種方式添加:
- 第一種直接將字體用塊元素包裹,動(dòng)態(tài)設(shè)置絕對(duì)定位,然后通過 transform 屬性旋轉(zhuǎn);
- 第二種通過在 canvas 上繪制出字體,設(shè)置好樣式,然后以圖片的樣式導(dǎo)出,最后用圖片作為水印層的背景圖。
處于性能方面考慮,第二種方式最優(yōu)。我們來看具體怎么實(shí)現(xiàn)?
作為一塊獨(dú)立的功能,我們?cè)?Vue3 中常用 hooks 來實(shí)現(xiàn),通過分析我們概括出實(shí)現(xiàn)水印需要的幾個(gè)功能函數(shù)和對(duì)外接口:
對(duì)外接口
- 清除水印(clear)
- 設(shè)置水?。╯etWatermark)
核心功能函數(shù)
- 繪制文字背景圖(createBase64)
- 繪制水印層(createWatermark)
- 頁面隨窗口大小調(diào)整更新(updateWatermark)
export function useWatermark( appendEl: Ref<HTMLElement | null> = ref(document.body) as Ref<HTMLElement> ) { // 繪制文字背景圖 function createBase64() {} // 繪制水印層 const createWatermark = () => {}; // 頁面隨窗口調(diào)整更新水印 function updateWatermark(){} // 對(duì)外提供的設(shè)置水印方法 function setWatermark() {} // 清除水印 const clear = () => {}; return { setWatermark, clear }; }
有了代碼框架,就只需要實(shí)現(xiàn)函數(shù)和接口的內(nèi)部實(shí)現(xiàn)了,另外還要考慮傳參,來實(shí)現(xiàn)代碼復(fù)用的靈活度和接口參數(shù)的可配置。
我們從具體的功能函數(shù)開始:
繪制文字背景圖
這里的參數(shù) str
就是要添加的水印文字,attr
為文字樣式的屬性,我們定義了屬性的類型為 attr
,它包含文字的字體和大小以及顏色等值
function createBase64(str: string, attr?: attr) { const can = document.createElement("canvas"); const width = 200; const height = 140; Object.assign(can, { width, height }); const cans = can.getContext("2d"); if (cans) { cans.rotate((-20 * Math.PI) / 120); cans.font = attr?.font ?? "12px Reggae One"; cans.fillStyle = attr?.fillStyle ?? "rgba(0, 0, 0, 0.12)"; cans.textAlign = "left"; cans.textBaseline = "middle"; cans.fillText(str, width / 20, height); } return can.toDataURL("image/png"); }
type attr = { font?: string; fillStyle?: string; };
繪制水印層
這個(gè)函數(shù)的主要邏輯是先判斷如果已經(jīng)繪制了水印層,直接調(diào)用更新水印方法,如果還沒有,先動(dòng)態(tài)創(chuàng)建一個(gè) DIV 層,設(shè)置絕對(duì)定位,鋪滿當(dāng)前整個(gè)瀏覽器窗口。
const id = domSymbol.toString(); const watermarkEl = shallowRef<HTMLElement>(); const createWatermark = (str: string, attr?: 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({ str, width, height, attr }); el.appendChild(div); return id; };
更新水印
因?yàn)楦滤》椒ㄖ饕歉鶕?jù)當(dāng)前窗口高度和寬度來的更新水印背景的設(shè)置,利用一張 Base64 格式的圖片平鋪即可。
function updateWatermark( options: { width?: number; height?: number; str?: string; attr?: 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.str !== "undefined") { el.style.background = `url(${createBase64( options.str, options.attr )}) left top repeat`; } }
到此,我們實(shí)現(xiàn)了主要的三個(gè)功能函數(shù),下面就是兩個(gè)對(duì)外接口:
設(shè)置水印
這里的主要點(diǎn)是考慮設(shè)置頁面resize監(jiān)聽,來及時(shí)更新水印的位置。還要考慮 Vue 的生命周期,當(dāng)我們卸載頁面的時(shí)候要進(jìn)行清除水印。
function setWatermark(str: string, attr?: attr) { createWatermark(str, 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 }); });
清除水印
清除水印的時(shí)候順便移除窗口大小監(jiān)聽函數(shù)
const clear = () => { const domId = unref(watermarkEl); watermarkEl.value = undefined; const el = unref(appendEl); if (!el) return; domId && el.removeChild(domId); removeResizeListener(el, func); };
水印功能 hooks 的使用
import { useWatermark } from "/@/hooks/watermark"; const { setWatermark, clear } = useWatermark(); onMounted(() => { nextTick(() => { setWatermark(watermarkText.value); }); }); onBeforeUnmount(() => { clear(); });
至此,Vue3 版的網(wǎng)頁水印功能實(shí)現(xiàn)全部完成。這里水印的字體大小、顏色和排布參考了企業(yè)微信的背景水印,使得看起來不那么突兀。
到此這篇關(guān)于Vue3 實(shí)現(xiàn)網(wǎng)頁背景水印功能的文章就介紹到這了,更多相關(guān)vue網(wǎng)頁水印內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用mint-ui開發(fā)項(xiàng)目的一些心得(分享)
下面小編就為大家?guī)硪黄褂胢int-ui開發(fā)項(xiàng)目的一些心得(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09vue和react的區(qū)別及優(yōu)缺點(diǎn)解讀
這篇文章主要介紹了vue和react的區(qū)別及優(yōu)缺點(diǎn)說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03antd?Vue實(shí)現(xiàn)Login登錄頁面布局案例詳解?附帶驗(yàn)證碼驗(yàn)證功能
這篇文章主要介紹了antd?Vue實(shí)現(xiàn)Login登錄頁面布局案例詳解附帶驗(yàn)證碼驗(yàn)證功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05vue中選項(xiàng)卡點(diǎn)擊切換且能滑動(dòng)切換功能的實(shí)現(xiàn)代碼
本文通過實(shí)例代碼給大家介紹了vue中選項(xiàng)卡點(diǎn)擊切換且能滑動(dòng)切換功能,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下2018-11-11VueJs單頁應(yīng)用實(shí)現(xiàn)微信網(wǎng)頁授權(quán)及微信分享功能示例
本篇文章主要介紹了VueJs單頁應(yīng)用實(shí)現(xiàn)微信網(wǎng)頁授權(quán)及微信分享功能示例,具有一定的參考價(jià)值,有興趣的可以了解一下2017-07-07在Vue中使用scoped屬性實(shí)現(xiàn)樣式隔離的原因解析
scoped是Vue的一個(gè)特殊屬性,可以應(yīng)用于<style>標(biāo)簽中的樣式,這篇文章給大家介紹在Vue中,使用scoped屬性為什么可以實(shí)現(xiàn)樣式隔離,感興趣的朋友一起看看吧2023-12-12