vue3 實現前端生成水印效果
首先一點哈,就是單純web前端生成水印只能作為警示使用,如果享徹底防住幾乎是不可能的,有無數種方式去掉web前端生成的水印,所以這種方式只當是一個君子協議吧。
編寫水印組件
首先直接把這部分封裝成一個組件吧,我這邊直接上代碼了。
創建一個 waterMark.vue
文件,用來編寫水印組件:
<template><div class="watermark-container" ref="parentRef"><slot></slot></div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import useWaterMarkBg from './waterMarkBg';
const props = defineProps({text: {type: String,default: "版權所有"},fontSize: {type: Number,default: 25,},gap: {type: Number,default: 20,},color: {type: String,default: 'rgba(201, 35, 35, 0.5)'}
})let div;
const bg = useWaterMarkBg(props);
const parentRef = ref();const ob = new MutationObserver((entries) => {for (const entry of entries) {for (const node of entry.removedNodes) {if (node === div) {resetWatermark();return;}}if (entry.target === div) {resetWatermark();}}
})onMounted(() => {resetWatermark();ob.observe(parentRef.value, {childList: true,subtree: true,attributes: true,})
})onUnmounted(() => {ob.disconnect();
})// 重置水印
const resetWatermark = () => {if (!parentRef.value) { return }if (div) {div.remove();}const { base64, size } = bg.value.value;div = document.createElement('div');div.style.position = 'absolute';div.style.backgroundImage = `url(${base64})`;div.style.backgroundSize = `${size.width}px ${size.height}px`;div.style.backgroundRepeat = "repeat";div.style.pointerEvents = 'none';div.style.zIndex = '9999';div.style.inset = 0;parentRef.value.appendChild(div);
}</script>
<style scoped lang="scss">
.watermark-container {position: relative;
}
</style>
可以接受四個參數,如果不夠可以自己加,分別是 text 水印文本內容
、fontSize 水印文本大小
、gap 水印文本間隔
、color 水印文本顏色
。
然后在水印組件加載完成的時候調用 resetWatermark
重置水印方法實現添加水印。
水印是動態生成的圖片,最后創建了一個動態的div
加上頁面的,因為還想盡可能的防止一下水印刪除,所以說在中途檢測了一下dom
修改情況,如果修改了,比如刪除了div
,或者是修改了div
的樣式,那么就重置水印,重新添加一遍。
其中在組件中還是用了 useWaterMarkBg
方法,下面代碼是 waterMarkBg.js
文件的內容,可以根據自己的業務需求適當的修改:
import { ref, computed } from 'vue';/*** 創建水印背景圖片的 composable 函數* @param {Object} options - 水印配置選項* @param {string} options.text - 水印文字內容* @param {number} options.fontSize - 字體大小* @param {number} options.gap - 水印間隔* @param {string} options.color - 文字顏色,默認為半透明灰色* @param {number} options.rotate - 旋轉角度,默認為 -15 度* @param {string} options.fontFamily - 字體,默認為 Arial* @returns {Object} 返回包含 base64 和 size 的響應式對象*/
function useWaterMarkBg(options = {}) {// 默認參數const defaultOptions = {text: '版權所有',fontSize: 25,gap: 20,color: 'rgba(201, 35, 35, 0.5)',rotate: -15,fontFamily: 'Arial, sans-serif'};// 合并用戶參數和默認參數const waterMarkOptions = ref({ ...defaultOptions, ...options });// 計算水印尺寸和 base64 圖片const waterMarkInfo = computed(() => {const { text, fontSize, gap, color, rotate, fontFamily } = waterMarkOptions.value;// 創建 canvas 元素const canvas = document.createElement('canvas');const ctx = canvas.getContext('2d');if (!ctx) {throw new Error('無法獲取 canvas 上下文');}// 設置字體ctx.font = `${fontSize}px ${fontFamily}`;// 獲取文字寬度const textWidth = ctx.measureText(text).width;// 計算 canvas 尺寸(包含文字和間隙)const width = textWidth + gap * 2;const height = fontSize * 2 + gap * 2;canvas.width = width;canvas.height = height;// 重置上下文(因為 canvas 尺寸改變了)ctx.font = `${fontSize}px ${fontFamily}`;ctx.fillStyle = color;ctx.textAlign = 'center';ctx.textBaseline = 'middle';// 保存當前狀態ctx.save();// 移動到 canvas 中心并旋轉ctx.translate(width / 2, height / 2);ctx.rotate((Math.PI / 180) * rotate);// 繪制文字ctx.fillText(text, 0, 0);// 恢復之前的狀態ctx.restore();// 轉換為 base64const base64 = canvas.toDataURL('image/png');return {base64,size: {width,height}};});// 如果傳入的 options 發生變化,可以更新水印function updateOptions(newOptions) {waterMarkOptions.value = { ...waterMarkOptions.value, ...newOptions };}return {value: waterMarkInfo,updateOptions};
}export default useWaterMarkBg;
水印組件的使用
使用的時候就很簡單了,引入一下,然后包裹一下需要添加水印的dom
就可以了:
<!-- 默認紅色水印 --><water-mark text="嚴禁傳播"><div class="img-con"><img src="../../assets/imgs/watermark/1.jpg" alt="圖片1"></div></water-mark><!-- 藍色水印 --><water-mark text="禁止復制" :fontSize="25" color="rgba(30, 144, 255, 0.3)"><div class="img-con"><img src="../../assets/imgs/watermark/2.jpg" alt="圖片2"></div></water-mark><!-- 綠色水印 --><water-mark text="測試水印" :fontSize="25" color="rgba(50, 205, 50, 0.4)"><div class="img-con"><img src="../../assets/imgs/watermark/1.jpg" alt="圖片3"></div></water-mark>
效果
好了,大體就這個樣子,還是,水印這個很容易刪除,懂得人,刪的很快,最好從源頭解決,只要后端返回前端的是原文件,那么就可以從瀏覽器獲取到沒有水印的內容。