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 6 const domSymbol = Symbol('watermark-dom');
4 7  
5 8 export function useWatermark(
6 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 17 const id = domSymbol.toString();
  18 + const watermarkEl = shallowRef<HTMLElement>();
  19 +
10 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 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 35 const cans = can.getContext('2d');
26 36 if (cans) {
... ... @@ -29,30 +39,55 @@ export function useWatermark(
29 39 cans.fillStyle = 'rgba(0, 0, 0, 0.15)';
30 40 cans.textAlign = 'left';
31 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 72 const div = document.createElement('div');
  73 + watermarkEl.value = div;
36 74 div.id = id;
37 75 div.style.pointerEvents = 'none';
38 76 div.style.top = '0px';
39 77 div.style.left = '0px';
40 78 div.style.position = 'absolute';
41 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 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 85 return id;
48 86 };
49 87  
50 88 function setWatermark(str: string) {
51 89 createWatermark(str);
52   - func = () => {
53   - createWatermark(str);
54   - };
55   - window.addEventListener('resize', func);
  90 + addResizeListener(document.documentElement, func);
56 91 const instance = getCurrentInstance();
57 92 if (instance) {
58 93 onBeforeUnmount(() => {
... ...
src/utils/domUtils.ts
  1 +import type { FunctionArgs } from '@vueuse/core';
1 2 import { upperFirst } from 'lodash-es';
2 3  
3 4 export interface ViewportOffsetResult {
... ... @@ -163,3 +164,17 @@ export function once(el: HTMLElement, event: string, fn: EventListener): void {
163 164 };
164 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 +}
... ...