日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

Vue3問題:如何在頁面上添加水印?

來源: 責編: 時間:2024-03-19 09:24:20 260觀看
導讀1. 需求分析為了防止網站信息被盜用,以及維護版權標識,常常需要在頁面、圖片或視頻上添加獨特水印,以作區分。同時,水印的添加不僅僅滿足于添加,有時候還要能防止用戶惡意篡改,時刻保證水印的功效。所以,這次問題我分為了兩

Url28資訊網——每日最新資訊28at.com

1. 需求分析

為了防止網站信息被盜用,以及維護版權標識,常常需要在頁面、圖片或視頻上添加獨特水印,以作區分。Url28資訊網——每日最新資訊28at.com

同時,水印的添加不僅僅滿足于添加,有時候還要能防止用戶惡意篡改,時刻保證水印的功效。Url28資訊網——每日最新資訊28at.com

所以,這次問題我分為了兩種情況:一種是僅添加水印僅可,另一種是添加水印且要防篡改。Url28資訊網——每日最新資訊28at.com

下面我將把實現一一列出。Url28資訊網——每日最新資訊28at.com

Url28資訊網——每日最新資訊28at.com

2. 實現步驟

(1)僅添加水印情況

對于僅需要添加水印的情況,直接使用第三方UI庫中的水印組件即可,簡單快速。Url28資訊網——每日最新資訊28at.com

當然,我們也可以選擇自己造輪子,用Canvas來畫,但是對于工作而言,我覺得這樣應該盡量避免。Url28資訊網——每日最新資訊28at.com

這里我使用ElementPlus 2.4.0中,新出的Watermark水印組件作為例子。Url28資訊網——每日最新資訊28at.com

實現代碼:Url28資訊網——每日最新資訊28at.com

<template><el-watermark:width="130":height="30"image="https://element-plus.org/images/element-plus-logo.svg"><div style="height: 500px" /></el-watermark></template>

效果如下:Url28資訊網——每日最新資訊28at.com

Url28資訊網——每日最新資訊28at.com

當然要注意的是,ElementPlus的依賴版本一定要是2.4.0之后的。Url28資訊網——每日最新資訊28at.com

(2)添加水印且要防篡改情況

像ElementPlus提供的水印組件,是不支持防篡改功能的。Url28資訊網——每日最新資訊28at.com

也就是說,如果有用戶通過瀏覽器的控制臺進行元素屬性的修改,是可以把頁面中的水印隱藏的。所以為了安全起見,是很需要做防篡改處理的。Url28資訊網——每日最新資訊28at.com

為了保證自定義水印的靈活性,這里我使用了原生js的寫法,并且代碼參考了渡一官方大佬的文章。Url28資訊網——每日最新資訊28at.com

簡言之,就是利用Canvas繪制水印圖像,以及利用MutationObserver對象來監聽Dom節點或其子節點的變化以實現防篡改處理。Url28資訊網——每日最新資訊28at.com

代碼實現如下:Url28資訊網——每日最新資訊28at.com

先寫一個hook函數useWatermarkBg,在其中用Canvas繪制水印圖像。Url28資訊網——每日最新資訊28at.com

import { computed } from 'vue';export default function useWatermarkBg (props) {return computed(() => {// 創建一個 canvasconst canvas = document.createElement('canvas');const devicePixelRatio = window.devicePixelRatio || 1;// 設置字體大小const fontSize = props.fontSize * devicePixelRatio;const font = fontSize + 'px serif';const ctx = canvas.getContext('2d');// 獲取文字寬度ctx.font = font;const { width } = ctx.measureText(props.text);const canvasSize = Math.max(100, width) + props.gap * devicePixelRatio;canvas.width = canvasSize;canvas.height = canvasSize;ctx.translate(canvas.width / 2, canvas.height / 2);// 旋轉 45 度讓文字變傾斜ctx.rotate((Math.PI / 180) * -45);ctx.fillStyle = 'rgba(0, 0, 0, 0.3)';ctx.font = font;ctx.textAlign = 'center';ctx.textBaseline = 'middle';// 將文字畫出來ctx.fillText(props.text, 0, 0);return {base64: canvas.toDataURL(),size: canvasSize,styleSize: canvasSize / devicePixelRatio,};});}

再封裝一個水印公共組件WaterMark,在其中調用useWatermarkBg函數生成水印圖像,以及添加水印、做防篡改處理。Url28資訊網——每日最新資訊28at.com

在mounted中,創建MutationObserver實例,監聽水印DOM節點的變化,在節點刪除或屬性修改時設置依賴,發出重新添加水印的通知。Url28資訊網——每日最新資訊28at.com

在watchEffect中,進行收集依賴,只要依賴變化了,它就會重新添加水印圖像,達到防篡改效果。Url28資訊網——每日最新資訊28at.com

值得一提的是,因為添加水印的原理是給頁面添加一個絕對定位的重復水印背景的div,但是,如果這樣我們就不能點擊div下層的元素了。Url28資訊網——每日最新資訊28at.com

所以,這里還用了一個叫pointerEvents的css屬性,設置值為none,從而使元素不會接收鼠標事件,鼠標事件會透過元素傳遞到下層的元素上。Url28資訊網——每日最新資訊28at.com

<template><div class="watermark-container" ref="parentRef"><slot></slot></div></template><script setup>import { onMounted, onUnmounted, ref, watchEffect } from 'vue';import useWatermarkBg from '@/hooks/useWatermarkBg.js';const props = defineProps({text: {type: String,required: true,default: 'watermark',},fontSize: {type: Number,default: 40,},gap: {type: Number,default: 20,},});const bg = useWatermarkBg(props);const parentRef = ref(null);const flag = ref(0); // 聲明一個依賴let div;watchEffect(() => {flag.value; // 將依賴放在 watchEffect 里if (!parentRef.value) {return;}if (div) {div.remove();}const { base64, styleSize } = bg.value;div = document.createElement('div');div.style.backgroundImage = `url(${base64})`;div.style.backgroundSize = `${styleSize}px ${styleSize}px`;div.style.backgroundRepeat = 'repeat';div.style.zIndex = 9999;div.style.position = 'absolute';div.style.inset = 0;// 元素不會接收鼠標事件,鼠標事件會透過元素傳遞到下層的元素上div.style.pointerEvents = 'none';parentRef.value.appendChild(div);});// 防篡改處理let ob;onMounted(() => {ob = new MutationObserver((records) => {for (const record of records) {for (const dom of record.removedNodes) {if (dom === div) {flag.value++; // 刪除節點的時候更新依賴return;}}if (record.target === div) {flag.value++; // 修改屬性的時候更新依賴return;}}});ob.observe(parentRef.value, {childList: true,attributes: true,subtree: true,});});onUnmounted(() => {ob && ob.disconnect();div = null;});</script>

最后,在需要添加水印的頁面直接使用即可。Url28資訊網——每日最新資訊28at.com

<template><water-mark><video src="@/assets/a.mp4" controls width="500" height="500"></video></water-mark></template><script setup>import WaterMark from "@/components/WaterMark.vue"</script>

3. 問題詳解

(1)關于MutationObserver總結

MutationObserver 是 JavaScript 中的一個內置對象,它提供了一種監視 DOM(文檔對象模型)樹變化的能力。Url28資訊網——每日最新資訊28at.com

MutationObserver 允許開發者注冊一個回調函數,當觀察的 DOM 節點或子節點發生變化時,會觸發這個回調函數。這些變化可以包括節點的添加、移除、屬性的變化、文本內容的改變等。Url28資訊網——每日最新資訊28at.com

使用 MutationObserver 可以監視特定的 DOM 元素或整個文檔,并在相關變化發生時執行相應的操作。這對于實時監測頁面變化、自動化測試、實現響應式 UI 等場景非常有用。Url28資訊網——每日最新資訊28at.com

下面是一個簡單的示例,演示如何使用 MutationObserver 監測某個元素的子節點變化:Url28資訊網——每日最新資訊28at.com

// 目標元素var targetElement = document.getElementById('target-element');// 創建一個 MutationObserver 實例var observer = new MutationObserver(function(mutationsList, observer) {// 當變化發生時執行的回調函數for (var mutation of mutationsList) {if (mutation.type === 'childList') {console.log('子節點發生變化');console.log(mutation.addedNodes); // 添加的節點列表console.log(mutation.removedNodes); // 移除的節點列表}}});// 配置觀察選項var config = { childList: true };// 開始觀察目標元素observer.observe(targetElement, config);

在上述示例中,我們首先通過 getElementById 獲取目標元素,然后創建一個 MutationObserver 實例,傳入一個回調函數作為參數。回調函數會在目標元素的子節點發生變化時被調用。我們可以在回調函數中根據 mutationsList 的內容進行相應的處理。在這個示例中,我們只關注子節點的變化,并打印相關信息到控制臺。Url28資訊網——每日最新資訊28at.com

最后,我們通過調用 observe 方法來開始觀察目標元素的變化。在 config 對象中,我們將 childList 屬性設置為 true,表示我們要監測子節點的變化。Url28資訊網——每日最新資訊28at.com

需要注意的是,MutationObserver 是一個異步的機制,它會在變化發生后才觸發回調函數。這意味著在開始觀察之前的變化可能不會被捕獲到。如果需要在開始觀察之前立即獲取當前狀態的變化,可以在創建 MutationObserver 實例后,使用 observer.takeRecords() 方法來獲取當前的變化記錄。Url28資訊網——每日最新資訊28at.com

(2)關于pointer-events的總結

pointer-events 是一種 CSS 屬性,它控制元素對鼠標事件的響應方式。它可以設置在任何 HTML 元素上,并具有以下幾個可能的取值:Url28資訊網——每日最新資訊28at.com

  • auto:元素對鼠標事件作出默認的響應。即元素會根據自身的樣式和內容對鼠標事件做出適當的響應。
  • none:元素對鼠標事件不做出響應。即元素不會接收鼠標事件,鼠標事件會透過元素傳遞到下層的元素上。這相當于將元素變為不可點擊,即使它位于頁面上方或遮擋其他元素。
  • visiblePainted:元素對鼠標事件做出響應,但鼠標事件不會穿透元素,而是傳遞到下層的元素上。這意味著元素會接收鼠標事件,但不會阻止下層元素對鼠標事件的響應。
  • visibleFill:元素對鼠標事件做出響應,并會阻止鼠標事件傳遞到下層的元素上。這意味著元素會完全接收鼠標事件,并阻止下層元素對鼠標事件的響應。

pointer-events 屬性對于創建交互式的頁面元素非常有用,可以控制元素是否能夠接收和響應鼠標事件。通過將其設置為 none,可以使元素在外觀上可見,但不會干擾下層元素的交互。Url28資訊網——每日最新資訊28at.com

需要注意的是,pointer-events 屬性的兼容性有限,可能不支持所有瀏覽器或舊版本的瀏覽器。在使用時,建議先檢查兼容性并提供備用方案或降級策略。Url28資訊網——每日最新資訊28at.com

本文鏈接:http://m.www897cc.com/showinfo-26-77681-0.htmlVue3問題:如何在頁面上添加水印?

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 詳解基于SpringBoot的WebSocket應用開發

下一篇: C# WinForm程序中讀寫INI配置文件的技術詳解

標簽:
  • 熱門焦點
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
精品福利免费观看| 欧美日韩ab片| 国产精品99久久久久久人| av成人免费在线| 亚洲一区二区黄色| 亚洲欧美亚洲| 久久久.com| 欧美大片在线看| 国产精品v日韩精品| 国产亚洲一区精品| 亚洲精品一区二区三| 亚洲婷婷综合色高清在线| 欧美一区在线直播| 欧美高清在线一区二区| 国产精品久久中文| 精品不卡在线| 亚洲视频精品| 久久久亚洲一区| 欧美日韩精品久久久| 国产精品视频自拍| 亚洲成人在线| 亚洲手机在线| 久久综合久久综合这里只有精品| 欧美人成在线| 国产亚洲免费的视频看| 亚洲免费av观看| 久久精品亚洲乱码伦伦中文 | 亚洲一区中文| 久久裸体艺术| 国产精品二区二区三区| 亚洲二区三区四区| 午夜激情综合网| 91久久极品少妇xxxxⅹ软件| 一本色道88久久加勒比精品| 久久婷婷国产综合精品青草| 国产精品极品美女粉嫩高清在线| 精品96久久久久久中文字幕无| 亚洲视频网站在线观看| 裸体歌舞表演一区二区| 国产精品美女| 日韩午夜黄色| 老色鬼精品视频在线观看播放| 国产精品免费观看视频| 亚洲精品欧美一区二区三区| 久久久免费精品视频| 国产精品羞羞答答| 99精品久久久| 免费成人av资源网| 国产有码一区二区| 亚洲欧美变态国产另类| 欧美日韩高清不卡| 亚洲国产精品女人久久久| 久久精品国产77777蜜臀| 国产精品v一区二区三区| 亚洲日韩中文字幕在线播放| 久久一区视频| 国产一区高清视频| 午夜欧美不卡精品aaaaa| 欧美视频第二页| 亚洲精品精选| 久久精品欧美日韩精品| 国产精品五区| 亚洲一区国产视频| 欧美日韩精品一区二区在线播放| 黄色小说综合网站| 欧美中文字幕在线| 国产欧美日韩专区发布| 亚洲午夜精品在线| 欧美色精品在线视频| 亚洲精品日韩在线| 欧美sm视频| 亚洲成在人线av| 久久先锋影音| 精品白丝av| 浪潮色综合久久天堂| 一区二区三区在线看| 久久久久久久综合狠狠综合| 国产亚洲人成a一在线v站| 欧美亚洲一区二区三区| 国产精品制服诱惑| 亚洲自拍三区| 国产精品日韩欧美| 午夜欧美精品| 国产一二三精品| 久久久久久久波多野高潮日日 | 国产精品免费看| 午夜久久福利| 国产一二精品视频| 久久国内精品自在自线400部| 国产一区91精品张津瑜| 久久精品亚洲精品| 黄色小说综合网站| 每日更新成人在线视频| 亚洲电影免费观看高清完整版在线| 免费观看日韩av| 亚洲国产美女精品久久久久∴| 猛干欧美女孩| 亚洲精品永久免费| 国产精品免费观看视频| 欧美系列亚洲系列| 在线精品观看| 欧美不卡在线视频| 久久九九免费视频| 久久久精品tv| 久久国产精品网站| 日韩一区二区免费高清| 欧美精品一线| 欧美精彩视频一区二区三区| 欧美成在线视频| 欧美日韩dvd在线观看| 欧美精品一区二区三区很污很色的 | 欧美一区二区三区视频在线| 亚洲精品一区二区三区婷婷月| 久久久久久91香蕉国产| 国产日韩欧美高清| 久久精品国产免费看久久精品| 国产视频丨精品|在线观看| 欧美亚洲综合另类| 国产亚洲人成网站在线观看| 久久av在线看| 国产精品久99| 国产午夜精品在线观看| 一区二区三区成人| 乱中年女人伦av一区二区| 蜜臀久久99精品久久久久久9| 国产精品视频一区二区三区 | 欧美激情免费在线| 国产精品久久久久一区二区| 欧美一级视频精品观看| 伊人色综合久久天天五月婷| 欧美日韩国产综合网| 欧美一级播放| 日韩视频精品在线观看| 亚洲欧美日韩综合aⅴ视频| 亚洲综合不卡| 欧美区日韩区| 亚洲一区二区三区四区中文 | 国产精品男人爽免费视频1| 亚洲砖区区免费| 美女网站久久| 亚洲欧美日韩视频一区| 一区二区三区亚洲| 欧美性猛交xxxx乱大交蜜桃| 久久久久网址| 亚洲天堂偷拍| 亚洲电影av在线| 国产精品永久免费| 欧美精品xxxxbbbb| 久久精品国产综合| 亚洲图片在线观看| 亚洲第一级黄色片| 国产乱子伦一区二区三区国色天香 | 国产精品夜色7777狼人| 麻豆精品精品国产自在97香蕉| 亚洲视频在线观看网站| 亚洲国产成人在线播放| 国产精品亚洲片夜色在线| 欧美激情一区二区三区全黄| 久久久91精品国产| 亚洲综合激情| 亚洲开发第一视频在线播放| 狠狠色狠狠色综合| 国产精品久久久久久妇女6080| 欧美大片第1页| 久久久久国产一区二区三区四区 | 国产一区二区久久精品| 欧美午夜精品久久久久免费视| 男人插女人欧美| 久久九九精品99国产精品| 亚洲一区二区三区乱码aⅴ| 亚洲精品国久久99热| 永久久久久久| 国产一区二区三区不卡在线观看| 欧美视频在线视频| 欧美精品一区二区精品网| 免费观看一级特黄欧美大片| 久久久国产午夜精品| 羞羞答答国产精品www一本| 亚洲一级影院| 中文av字幕一区| 日韩午夜中文字幕| 亚洲精品久久久久久久久久久久久| 激情综合色综合久久| 国产一区二区三区日韩| 国产精品日日做人人爱| 国产精品爱久久久久久久| 欧美三级韩国三级日本三斤| 欧美激情导航| 欧美大片第1页| 蜜桃av综合| 久久综合色影院| 久久人人精品| 久久在线视频| 美女精品一区| 欧美成年人视频网站| 乱人伦精品视频在线观看| 美国三级日本三级久久99| 久久亚洲一区二区| 久久综合综合久久综合| 久久综合网hezyo| 美女网站在线免费欧美精品| 美女图片一区二区| 欧美黑人在线播放| 欧美激情小视频|