fix: 水印问题开发

This commit is contained in:
kun 2023-09-21 18:54:18 +08:00
parent f1c3f702e7
commit ce295cc521
4 changed files with 169 additions and 6 deletions

View File

@ -0,0 +1,93 @@
/*
1使 canvas base64
2
使
<div v-waterMarker="{text:'版权所有',textColor:'rgba(180, 180, 180, 0.4)'}"></div>
*/
// watermark 样式
let style = `
display: block;
overflow: hidden;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-repeat: repeat;
pointer-events: none;
`;
let str: string = "";
let font: any = null;
let textColor: string = "";
import type { Directive, DirectiveBinding } from "vue";
const addWaterMarker: Directive = (str: string, parentNode: any, font: any, textColor: string) => {
str = str || "";
font = font || "16px Microsoft JhengHei";
textColor = textColor || "rgba(180, 180, 180, 0.3)";
// 水印文字,父元素,字体,文字颜色
let can: HTMLCanvasElement = document.createElement("canvas");
parentNode.appendChild(can);
can.width = 205;
can.height = 140;
can.style.display = "none";
let cans = can.getContext("2d") as CanvasRenderingContext2D;
cans.rotate((-20 * Math.PI) / 180);
cans.font = font || "16px Microsoft JhengHei";
cans.fillStyle = textColor || "rgba(180, 180, 180, 0.3)";
cans.textAlign = "left";
cans.textBaseline = "Middle" as CanvasTextBaseline;
cans.fillText(str, can.width / 10, can.height / 2);
// 创建waterMark父元素
const waterMark = document.createElement("div");
waterMark.className = `water-mark`; // 方便自定义展示结果
style = `${style}background-image: url(${can.toDataURL("image/png")})`;
waterMark.setAttribute("style", style);
// 将对应图片的父容器作为定位元素
parentNode.setAttribute("style", "position:relative;");
// 将图片元素移动到waterMark中
parentNode.appendChild(waterMark);
// parentNode.style.backgroundImage = "url(" + can.toDataURL("image/png") + ")";
};
const waterMarker = {
mounted(el: DirectiveBinding, binding: DirectiveBinding) {
// addWaterMarker(binding.value.text, el, binding.value.font, binding.value.textColor);
el.onload = init.bind(null, el, binding);
}
};
// 监听DOM变化
const createObserver = (el: HTMLElement, binding: any) => {
const waterMarkEl = el.parentElement?.querySelector(".water-mark");
const observer = new MutationObserver(mutationsList => {
if (mutationsList.length) {
const { removedNodes, type, target } = mutationsList[0];
const currStyle = waterMarkEl?.getAttribute("style");
// 证明被删除了
if (removedNodes[0] === waterMarkEl) {
observer.disconnect();
init(el, binding);
} else if (type === "attributes" && target === waterMarkEl && currStyle !== style) {
waterMarkEl.setAttribute("style", style);
}
}
});
observer.observe(el.parentElement, {
childList: true,
attributes: true,
subtree: true
});
};
const init = (el: HTMLElement, binding: any = {}) => {
// 设置水印
addWaterMarker(binding.value.text, el, binding.value.font, binding.value.textColor);
// 启动监控
createObserver(el, binding.value);
};
export default waterMarker;

View File

@ -8,9 +8,26 @@
使
<div v-waterMarker="{text:'版权所有',textColor:'rgba(180, 180, 180, 0.4)'}"></div>
*/
// watermark 样式
let style = `
display: block;
overflow: hidden;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-repeat: repeat;
pointer-events: none;
`;
let str: string = "";
let font: any = null;
let textColor: string = "";
import type { Directive, DirectiveBinding } from "vue";
const addWaterMarker: Directive = (str: string, parentNode: any, font: any, textColor: string) => {
const addWaterMarker = (parentNode: any, binding: { str: string; font: any; textColor: string }) => {
str = str || "";
font = font || "16px Microsoft JhengHei";
textColor = textColor || "rgba(180, 180, 180, 0.3)";
// 水印文字,父元素,字体,文字颜色
let can: HTMLCanvasElement = document.createElement("canvas");
parentNode.appendChild(can);
@ -24,13 +41,53 @@ const addWaterMarker: Directive = (str: string, parentNode: any, font: any, text
cans.textAlign = "left";
cans.textBaseline = "Middle" as CanvasTextBaseline;
cans.fillText(str, can.width / 10, can.height / 2);
parentNode.style.backgroundImage = "url(" + can.toDataURL("image/png") + ")";
// 创建waterMark父元素
const waterMark = document.createElement("div");
waterMark.className = `water-mark`; // 方便自定义展示结果
style = `${style}background-image: url(${can.toDataURL("image/png")})`;
waterMark.setAttribute("style", style);
// 将对应图片的父容器作为定位元素
parentNode.setAttribute("style", "position:relative;");
// 将图片元素移动到waterMark中
parentNode.appendChild(waterMark);
// parentNode.style.backgroundImage = "url(" + can.toDataURL("image/png") + ")";
};
const waterMarker = {
mounted(el: DirectiveBinding, binding: DirectiveBinding) {
addWaterMarker(binding.value.text, el, binding.value.font, binding.value.textColor);
mounted(el: HTMLElement, binding: any) {
// addWaterMarker(binding.value.text, el, binding.value.font, binding.value.textColor);
el.onload = init.bind(el, binding);
}
};
// 监听DOM变化
const createObserver = (el: HTMLElement, binding: any) => {
const waterMarkEl = el.parentElement?.querySelector(".water-mark");
const observer = new MutationObserver(mutationsList => {
if (mutationsList.length) {
const { removedNodes, type, target } = mutationsList[0];
const currStyle = waterMarkEl?.getAttribute("style");
// 证明被删除了
if (removedNodes[0] === waterMarkEl) {
observer.disconnect();
init(el, binding);
} else if (type === "attributes" && target === waterMarkEl && currStyle !== style) {
waterMarkEl.setAttribute("style", style);
}
}
});
observer.observe(el.parentElement, {
childList: true,
attributes: true,
subtree: true
});
};
const init = (el: HTMLElement, binding: any = {}) => {
// 设置水印
addWaterMarker(el, binding.value);
// 启动监控
createObserver(el, binding.value);
};
export default waterMarker;

View File

@ -3,6 +3,7 @@
display: flex;
width: 100%;
height: 100%;
position: relative;
.leftMenu {
width: 300px;
border-radius: 8px;
@ -92,3 +93,15 @@
width: 300px;
}
}
.water-mark {
display: inline-block;
overflow: hidden;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
pointer-events: none;
background-repeat: repeat;
z-index: 10;
}

View File

@ -1,5 +1,5 @@
<template>
<div class="warning-page">
<div class="warning-page" v-waterMarker="{ text: '版权所有', textColor: 'rgba(180, 180, 180, 0.4)' }">
<LeftMenu
v-model="active"
:tabs="['项目名称', '工程名称']"