From a1d956d3697cd07e0ba8910768f2a73e55f18491 Mon Sep 17 00:00:00 2001 From: yanzhuang Date: Tue, 13 Jul 2021 22:23:11 +0800 Subject: [PATCH] fix(useWatermark): fix `func` call `createWatermark` call `clear` to resizeEvent removed (#901) --- src/hooks/web/useWatermark.ts | 77 +++++++++++++++++++++++++---------- src/utils/domUtils.ts | 15 +++++++ 2 files changed, 71 insertions(+), 21 deletions(-) diff --git a/src/hooks/web/useWatermark.ts b/src/hooks/web/useWatermark.ts index 6bc32059..54823ba8 100644 --- a/src/hooks/web/useWatermark.ts +++ b/src/hooks/web/useWatermark.ts @@ -1,26 +1,36 @@ -import { getCurrentInstance, onBeforeUnmount, ref, Ref, unref } from 'vue'; +import { getCurrentInstance, onBeforeUnmount, ref, Ref, shallowRef, unref } from 'vue'; +import { useRafThrottle } from '/@/utils/domUtils'; +import { addResizeListener, removeResizeListener } from '/@/utils/event'; +import { isDef } from '/@/utils/is'; const domSymbol = Symbol('watermark-dom'); export function useWatermark( appendEl: Ref = ref(document.body) as Ref ) { - let func: Fn = () => {}; + const func = useRafThrottle(function () { + const el = unref(appendEl); + if (!el) return; + const { clientHeight: height, clientWidth: width } = el; + updateWatermark({ height, width }); + }); const id = domSymbol.toString(); + const watermarkEl = shallowRef(); + const clear = () => { - const domId = document.getElementById(id); - if (domId) { - const el = unref(appendEl); - el && el.removeChild(domId); - } - window.removeEventListener('resize', func); + const domId = unref(watermarkEl); + watermarkEl.value = undefined; + const el = unref(appendEl); + if (!el) return; + domId && el.removeChild(domId); + removeResizeListener(el, func); }; - const createWatermark = (str: string) => { - clear(); + function createBase64(str: string) { const can = document.createElement('canvas'); - can.width = 300; - can.height = 240; + const width = 300; + const height = 240; + Object.assign(can, { width, height }); const cans = can.getContext('2d'); if (cans) { @@ -29,30 +39,55 @@ export function useWatermark( cans.fillStyle = 'rgba(0, 0, 0, 0.15)'; cans.textAlign = 'left'; cans.textBaseline = 'middle'; - cans.fillText(str, can.width / 20, can.height); + cans.fillText(str, width / 20, height); } + return can.toDataURL('image/png'); + } + function updateWatermark( + options: { + width?: number; + height?: number; + str?: string; + } = {} + ) { + const el = unref(watermarkEl); + if (!el) return; + if (isDef(options.width)) { + el.style.width = `${options.width}px`; + } + if (isDef(options.height)) { + el.style.height = `${options.height}px`; + } + if (isDef(options.str)) { + el.style.background = `url(${createBase64(options.str)}) left top repeat`; + } + } + + const createWatermark = (str: string) => { + if (unref(watermarkEl)) { + updateWatermark({ str }); + return id; + } const div = document.createElement('div'); + watermarkEl.value = div; div.id = id; div.style.pointerEvents = 'none'; div.style.top = '0px'; div.style.left = '0px'; div.style.position = 'absolute'; div.style.zIndex = '100000'; - div.style.width = document.documentElement.clientWidth + 'px'; - div.style.height = document.documentElement.clientHeight + 'px'; - div.style.background = 'url(' + can.toDataURL('image/png') + ') left top repeat'; const el = unref(appendEl); - el && el.appendChild(div); + if (!el) return id; + const { clientHeight: height, clientWidth: width } = el; + updateWatermark({ str, width, height }); + el.appendChild(div); return id; }; function setWatermark(str: string) { createWatermark(str); - func = () => { - createWatermark(str); - }; - window.addEventListener('resize', func); + addResizeListener(document.documentElement, func); const instance = getCurrentInstance(); if (instance) { onBeforeUnmount(() => { diff --git a/src/utils/domUtils.ts b/src/utils/domUtils.ts index 80a77a57..126a1147 100644 --- a/src/utils/domUtils.ts +++ b/src/utils/domUtils.ts @@ -1,3 +1,4 @@ +import type { FunctionArgs } from '@vueuse/core'; import { upperFirst } from 'lodash-es'; export interface ViewportOffsetResult { @@ -163,3 +164,17 @@ export function once(el: HTMLElement, event: string, fn: EventListener): void { }; on(el, event, listener); } + +export function useRafThrottle(fn: T): T { + let locked = false; + // @ts-ignore + return function (...args: any[]) { + if (locked) return; + locked = true; + window.requestAnimationFrame(() => { + // @ts-ignore + fn.apply(this, args); + locked = false; + }); + }; +} -- GitLab