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'); const sourceMap = new WeakMap(); export function useWatermark( appendEl: Ref = ref(document.body) as Ref, ) { const appendElRaw = unref(appendEl); if (appendElRaw && sourceMap.has(appendElRaw)) { return sourceMap.get(appendElRaw); } 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 = unref(watermarkEl); watermarkEl.value = undefined; const el = unref(appendEl); if (!el) return; domId && el.removeChild(domId); removeResizeListener(el, func); }; function createBase64(str: string) { const can = document.createElement('canvas'); const width = 300; const height = 240; Object.assign(can, { width, height }); const cans = can.getContext('2d'); if (cans) { cans.rotate((-20 * Math.PI) / 120); cans.font = '15px Vedana'; cans.fillStyle = 'rgba(0, 0, 0, 0.15)'; cans.textAlign = 'left'; cans.textBaseline = 'middle'; 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'; const el = unref(appendEl); if (!el) return id; const { clientHeight: height, clientWidth: width } = el; updateWatermark({ str, width, height }); el.appendChild(div); sourceMap.set(el, { setWatermark, clear }); return id; }; function setWatermark(str: string) { createWatermark(str); addResizeListener(document.documentElement, func); const instance = getCurrentInstance(); if (instance) { onBeforeUnmount(() => { clear(); }); } } return { setWatermark, clear }; }