useWatermark.ts 3.0 KB

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