useWatermark.ts 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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';
  5. const domSymbol = Symbol('watermark-dom');
  6. export function useWatermark(appendEl: Ref<HTMLElement | null> = ref(document.body) as Ref<HTMLElement>) {
  7. const func = useRafThrottle(function () {
  8. const el = unref(appendEl);
  9. if (!el) return;
  10. const { clientHeight: height, clientWidth: width } = el;
  11. updateWatermark({ height, width });
  12. });
  13. const id = domSymbol.toString();
  14. const watermarkEl = shallowRef<HTMLElement>();
  15. const clear = () => {
  16. const domId = unref(watermarkEl);
  17. watermarkEl.value = undefined;
  18. const el = unref(appendEl);
  19. if (!el) return;
  20. domId && el.removeChild(domId);
  21. removeResizeListener(el, func);
  22. };
  23. function createBase64(str: string) {
  24. const can = document.createElement('canvas');
  25. const width = 300;
  26. const height = 240;
  27. Object.assign(can, { width, height });
  28. const cans = can.getContext('2d');
  29. if (cans) {
  30. cans.rotate((-20 * Math.PI) / 120);
  31. cans.font = '15px Vedana';
  32. cans.fillStyle = 'rgba(0, 0, 0, 0.15)';
  33. cans.textAlign = 'left';
  34. cans.textBaseline = 'middle';
  35. cans.fillText(str, width / 20, height);
  36. }
  37. return can.toDataURL('image/png');
  38. }
  39. function updateWatermark(
  40. options: {
  41. width?: number;
  42. height?: number;
  43. str?: string;
  44. } = {}
  45. ) {
  46. const el = unref(watermarkEl);
  47. if (!el) return;
  48. if (isDef(options.width)) {
  49. el.style.width = `${options.width}px`;
  50. }
  51. if (isDef(options.height)) {
  52. el.style.height = `${options.height}px`;
  53. }
  54. if (isDef(options.str)) {
  55. el.style.background = `url(${createBase64(options.str)}) left top repeat`;
  56. }
  57. }
  58. const createWatermark = (str: string) => {
  59. if (unref(watermarkEl)) {
  60. updateWatermark({ str });
  61. return id;
  62. }
  63. const div = document.createElement('div');
  64. watermarkEl.value = div;
  65. div.id = id;
  66. div.style.pointerEvents = 'none';
  67. div.style.top = '0px';
  68. div.style.left = '0px';
  69. div.style.position = 'absolute';
  70. div.style.zIndex = '100000';
  71. const el = unref(appendEl);
  72. if (!el) return id;
  73. const { clientHeight: height, clientWidth: width } = el;
  74. updateWatermark({ str, width, height });
  75. el.appendChild(div);
  76. return id;
  77. };
  78. function setWatermark(str: string) {
  79. createWatermark(str);
  80. addResizeListener(document.documentElement, func);
  81. const instance = getCurrentInstance();
  82. if (instance) {
  83. onBeforeUnmount(() => {
  84. clear();
  85. });
  86. }
  87. }
  88. return { setWatermark, clear };
  89. }