Commit a1d956d3697cd07e0ba8910768f2a73e55f18491
Committed by
GitHub
1 parent
35e13470
fix(useWatermark): fix `func` call `createWatermark` call `clear` to resizeEvent removed (#901)
Showing
2 changed files
with
71 additions
and
21 deletions
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 | +} |