Commit a1d956d3697cd07e0ba8910768f2a73e55f18491

Authored by yanzhuang
Committed by GitHub
1 parent 35e13470

fix(useWatermark): fix `func` call `createWatermark` call `clear` to resizeEvent removed (#901)

src/hooks/web/useWatermark.ts
1 -import { getCurrentInstance, onBeforeUnmount, ref, Ref, unref } from 'vue'; 1 +import { getCurrentInstance, onBeforeUnmount, ref, Ref, shallowRef, unref } from 'vue';
  2 +import { useRafThrottle } from '/@/utils/domUtils';
  3 +import { addResizeListener, removeResizeListener } from '/@/utils/event';
  4 +import { isDef } from '/@/utils/is';
2 5
3 const domSymbol = Symbol('watermark-dom'); 6 const domSymbol = Symbol('watermark-dom');
4 7
5 export function useWatermark( 8 export function useWatermark(
6 appendEl: Ref<HTMLElement | null> = ref(document.body) as Ref<HTMLElement> 9 appendEl: Ref<HTMLElement | null> = ref(document.body) as Ref<HTMLElement>
7 ) { 10 ) {
8 - let func: Fn = () => {}; 11 + const func = useRafThrottle(function () {
  12 + const el = unref(appendEl);
  13 + if (!el) return;
  14 + const { clientHeight: height, clientWidth: width } = el;
  15 + updateWatermark({ height, width });
  16 + });
9 const id = domSymbol.toString(); 17 const id = domSymbol.toString();
  18 + const watermarkEl = shallowRef<HTMLElement>();
  19 +
10 const clear = () => { 20 const clear = () => {
11 - const domId = document.getElementById(id);  
12 - if (domId) {  
13 - const el = unref(appendEl);  
14 - el && el.removeChild(domId);  
15 - }  
16 - window.removeEventListener('resize', func); 21 + const domId = unref(watermarkEl);
  22 + watermarkEl.value = undefined;
  23 + const el = unref(appendEl);
  24 + if (!el) return;
  25 + domId && el.removeChild(domId);
  26 + removeResizeListener(el, func);
17 }; 27 };
18 - const createWatermark = (str: string) => {  
19 - clear();  
20 28
  29 + function createBase64(str: string) {
21 const can = document.createElement('canvas'); 30 const can = document.createElement('canvas');
22 - can.width = 300;  
23 - can.height = 240; 31 + const width = 300;
  32 + const height = 240;
  33 + Object.assign(can, { width, height });
24 34
25 const cans = can.getContext('2d'); 35 const cans = can.getContext('2d');
26 if (cans) { 36 if (cans) {
@@ -29,30 +39,55 @@ export function useWatermark( @@ -29,30 +39,55 @@ export function useWatermark(
29 cans.fillStyle = 'rgba(0, 0, 0, 0.15)'; 39 cans.fillStyle = 'rgba(0, 0, 0, 0.15)';
30 cans.textAlign = 'left'; 40 cans.textAlign = 'left';
31 cans.textBaseline = 'middle'; 41 cans.textBaseline = 'middle';
32 - cans.fillText(str, can.width / 20, can.height); 42 + cans.fillText(str, width / 20, height);
33 } 43 }
  44 + return can.toDataURL('image/png');
  45 + }
34 46
  47 + function updateWatermark(
  48 + options: {
  49 + width?: number;
  50 + height?: number;
  51 + str?: string;
  52 + } = {}
  53 + ) {
  54 + const el = unref(watermarkEl);
  55 + if (!el) return;
  56 + if (isDef(options.width)) {
  57 + el.style.width = `${options.width}px`;
  58 + }
  59 + if (isDef(options.height)) {
  60 + el.style.height = `${options.height}px`;
  61 + }
  62 + if (isDef(options.str)) {
  63 + el.style.background = `url(${createBase64(options.str)}) left top repeat`;
  64 + }
  65 + }
  66 +
  67 + const createWatermark = (str: string) => {
  68 + if (unref(watermarkEl)) {
  69 + updateWatermark({ str });
  70 + return id;
  71 + }
35 const div = document.createElement('div'); 72 const div = document.createElement('div');
  73 + watermarkEl.value = div;
36 div.id = id; 74 div.id = id;
37 div.style.pointerEvents = 'none'; 75 div.style.pointerEvents = 'none';
38 div.style.top = '0px'; 76 div.style.top = '0px';
39 div.style.left = '0px'; 77 div.style.left = '0px';
40 div.style.position = 'absolute'; 78 div.style.position = 'absolute';
41 div.style.zIndex = '100000'; 79 div.style.zIndex = '100000';
42 - div.style.width = document.documentElement.clientWidth + 'px';  
43 - div.style.height = document.documentElement.clientHeight + 'px';  
44 - div.style.background = 'url(' + can.toDataURL('image/png') + ') left top repeat';  
45 const el = unref(appendEl); 80 const el = unref(appendEl);
46 - el && el.appendChild(div); 81 + if (!el) return id;
  82 + const { clientHeight: height, clientWidth: width } = el;
  83 + updateWatermark({ str, width, height });
  84 + el.appendChild(div);
47 return id; 85 return id;
48 }; 86 };
49 87
50 function setWatermark(str: string) { 88 function setWatermark(str: string) {
51 createWatermark(str); 89 createWatermark(str);
52 - func = () => {  
53 - createWatermark(str);  
54 - };  
55 - window.addEventListener('resize', func); 90 + addResizeListener(document.documentElement, func);
56 const instance = getCurrentInstance(); 91 const instance = getCurrentInstance();
57 if (instance) { 92 if (instance) {
58 onBeforeUnmount(() => { 93 onBeforeUnmount(() => {
src/utils/domUtils.ts
  1 +import type { FunctionArgs } from '@vueuse/core';
1 import { upperFirst } from 'lodash-es'; 2 import { upperFirst } from 'lodash-es';
2 3
3 export interface ViewportOffsetResult { 4 export interface ViewportOffsetResult {
@@ -163,3 +164,17 @@ export function once(el: HTMLElement, event: string, fn: EventListener): void { @@ -163,3 +164,17 @@ export function once(el: HTMLElement, event: string, fn: EventListener): void {
163 }; 164 };
164 on(el, event, listener); 165 on(el, event, listener);
165 } 166 }
  167 +
  168 +export function useRafThrottle<T extends FunctionArgs>(fn: T): T {
  169 + let locked = false;
  170 + // @ts-ignore
  171 + return function (...args: any[]) {
  172 + if (locked) return;
  173 + locked = true;
  174 + window.requestAnimationFrame(() => {
  175 + // @ts-ignore
  176 + fn.apply(this, args);
  177 + locked = false;
  178 + });
  179 + };
  180 +}