watermark2.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var vue = require('vue');
  4. var core = require('@vueuse/core');
  5. var watermark = require('./watermark.js');
  6. var utils = require('./utils.js');
  7. var useClips = require('./useClips.js');
  8. var pluginVue_exportHelper = require('../../../_virtual/plugin-vue_export-helper.js');
  9. var shared = require('@vue/shared');
  10. var types = require('../../../utils/types.js');
  11. const __default__ = vue.defineComponent({
  12. name: "ElWatermark"
  13. });
  14. const _sfc_main = /* @__PURE__ */ vue.defineComponent({
  15. ...__default__,
  16. props: watermark.watermarkProps,
  17. setup(__props) {
  18. const props = __props;
  19. const style = {
  20. position: "relative"
  21. };
  22. const color = vue.computed(() => {
  23. var _a, _b;
  24. return (_b = (_a = props.font) == null ? void 0 : _a.color) != null ? _b : "rgba(0,0,0,.15)";
  25. });
  26. const fontSize = vue.computed(() => {
  27. var _a, _b;
  28. return (_b = (_a = props.font) == null ? void 0 : _a.fontSize) != null ? _b : 16;
  29. });
  30. const fontWeight = vue.computed(() => {
  31. var _a, _b;
  32. return (_b = (_a = props.font) == null ? void 0 : _a.fontWeight) != null ? _b : "normal";
  33. });
  34. const fontStyle = vue.computed(() => {
  35. var _a, _b;
  36. return (_b = (_a = props.font) == null ? void 0 : _a.fontStyle) != null ? _b : "normal";
  37. });
  38. const fontFamily = vue.computed(() => {
  39. var _a, _b;
  40. return (_b = (_a = props.font) == null ? void 0 : _a.fontFamily) != null ? _b : "sans-serif";
  41. });
  42. const textAlign = vue.computed(() => {
  43. var _a, _b;
  44. return (_b = (_a = props.font) == null ? void 0 : _a.textAlign) != null ? _b : "center";
  45. });
  46. const textBaseline = vue.computed(() => {
  47. var _a, _b;
  48. return (_b = (_a = props.font) == null ? void 0 : _a.textBaseline) != null ? _b : "hanging";
  49. });
  50. const gapX = vue.computed(() => props.gap[0]);
  51. const gapY = vue.computed(() => props.gap[1]);
  52. const gapXCenter = vue.computed(() => gapX.value / 2);
  53. const gapYCenter = vue.computed(() => gapY.value / 2);
  54. const offsetLeft = vue.computed(() => {
  55. var _a, _b;
  56. return (_b = (_a = props.offset) == null ? void 0 : _a[0]) != null ? _b : gapXCenter.value;
  57. });
  58. const offsetTop = vue.computed(() => {
  59. var _a, _b;
  60. return (_b = (_a = props.offset) == null ? void 0 : _a[1]) != null ? _b : gapYCenter.value;
  61. });
  62. const getMarkStyle = () => {
  63. const markStyle = {
  64. zIndex: props.zIndex,
  65. position: "absolute",
  66. left: 0,
  67. top: 0,
  68. width: "100%",
  69. height: "100%",
  70. pointerEvents: "none",
  71. backgroundRepeat: "repeat"
  72. };
  73. let positionLeft = offsetLeft.value - gapXCenter.value;
  74. let positionTop = offsetTop.value - gapYCenter.value;
  75. if (positionLeft > 0) {
  76. markStyle.left = `${positionLeft}px`;
  77. markStyle.width = `calc(100% - ${positionLeft}px)`;
  78. positionLeft = 0;
  79. }
  80. if (positionTop > 0) {
  81. markStyle.top = `${positionTop}px`;
  82. markStyle.height = `calc(100% - ${positionTop}px)`;
  83. positionTop = 0;
  84. }
  85. markStyle.backgroundPosition = `${positionLeft}px ${positionTop}px`;
  86. return markStyle;
  87. };
  88. const containerRef = vue.shallowRef(null);
  89. const watermarkRef = vue.shallowRef();
  90. const stopObservation = vue.ref(false);
  91. const destroyWatermark = () => {
  92. if (watermarkRef.value) {
  93. watermarkRef.value.remove();
  94. watermarkRef.value = void 0;
  95. }
  96. };
  97. const appendWatermark = (base64Url, markWidth) => {
  98. var _a;
  99. if (containerRef.value && watermarkRef.value) {
  100. stopObservation.value = true;
  101. watermarkRef.value.setAttribute("style", utils.getStyleStr({
  102. ...getMarkStyle(),
  103. backgroundImage: `url('${base64Url}')`,
  104. backgroundSize: `${Math.floor(markWidth)}px`
  105. }));
  106. (_a = containerRef.value) == null ? void 0 : _a.append(watermarkRef.value);
  107. setTimeout(() => {
  108. stopObservation.value = false;
  109. });
  110. }
  111. };
  112. const getMarkSize = (ctx) => {
  113. let defaultWidth = 120;
  114. let defaultHeight = 64;
  115. const { image, content, width, height, rotate } = props;
  116. if (!image && ctx.measureText) {
  117. ctx.font = `${Number(fontSize.value)}px ${fontFamily.value}`;
  118. const contents = shared.isArray(content) ? content : [content];
  119. let maxWidth = 0;
  120. let maxHeight = 0;
  121. contents.forEach((item) => {
  122. const {
  123. width: width2,
  124. fontBoundingBoxAscent,
  125. fontBoundingBoxDescent,
  126. actualBoundingBoxAscent,
  127. actualBoundingBoxDescent
  128. } = ctx.measureText(item);
  129. const height2 = types.isUndefined(fontBoundingBoxAscent) ? actualBoundingBoxAscent + actualBoundingBoxDescent : fontBoundingBoxAscent + fontBoundingBoxDescent;
  130. if (width2 > maxWidth)
  131. maxWidth = Math.ceil(width2);
  132. if (height2 > maxHeight)
  133. maxHeight = Math.ceil(height2);
  134. });
  135. defaultWidth = maxWidth;
  136. defaultHeight = maxHeight * contents.length + (contents.length - 1) * useClips.FontGap;
  137. const angle = Math.PI / 180 * Number(rotate);
  138. const space = Math.ceil(Math.abs(Math.sin(angle) * defaultHeight) / 2);
  139. defaultWidth += space;
  140. }
  141. return [width != null ? width : defaultWidth, height != null ? height : defaultHeight];
  142. };
  143. const getClips = useClips["default"]();
  144. const renderWatermark = () => {
  145. const canvas = document.createElement("canvas");
  146. const ctx = canvas.getContext("2d");
  147. const image = props.image;
  148. const content = props.content;
  149. const rotate = props.rotate;
  150. if (ctx) {
  151. if (!watermarkRef.value) {
  152. watermarkRef.value = document.createElement("div");
  153. }
  154. const ratio = utils.getPixelRatio();
  155. const [markWidth, markHeight] = getMarkSize(ctx);
  156. const drawCanvas = (drawContent) => {
  157. const [textClips, clipWidth] = getClips(drawContent || "", rotate, ratio, markWidth, markHeight, {
  158. color: color.value,
  159. fontSize: fontSize.value,
  160. fontStyle: fontStyle.value,
  161. fontWeight: fontWeight.value,
  162. fontFamily: fontFamily.value,
  163. textAlign: textAlign.value,
  164. textBaseline: textBaseline.value
  165. }, gapX.value, gapY.value);
  166. appendWatermark(textClips, clipWidth);
  167. };
  168. if (image) {
  169. const img = new Image();
  170. img.onload = () => {
  171. drawCanvas(img);
  172. };
  173. img.onerror = () => {
  174. drawCanvas(content);
  175. };
  176. img.crossOrigin = "anonymous";
  177. img.referrerPolicy = "no-referrer";
  178. img.src = image;
  179. } else {
  180. drawCanvas(content);
  181. }
  182. }
  183. };
  184. vue.onMounted(() => {
  185. renderWatermark();
  186. });
  187. vue.watch(() => props, () => {
  188. renderWatermark();
  189. }, {
  190. deep: true,
  191. flush: "post"
  192. });
  193. vue.onBeforeUnmount(() => {
  194. destroyWatermark();
  195. });
  196. const onMutate = (mutations) => {
  197. if (stopObservation.value) {
  198. return;
  199. }
  200. mutations.forEach((mutation) => {
  201. if (utils.reRendering(mutation, watermarkRef.value)) {
  202. destroyWatermark();
  203. renderWatermark();
  204. }
  205. });
  206. };
  207. core.useMutationObserver(containerRef, onMutate, {
  208. attributes: true,
  209. subtree: true,
  210. childList: true
  211. });
  212. return (_ctx, _cache) => {
  213. return vue.openBlock(), vue.createElementBlock("div", {
  214. ref_key: "containerRef",
  215. ref: containerRef,
  216. style: vue.normalizeStyle([style])
  217. }, [
  218. vue.renderSlot(_ctx.$slots, "default")
  219. ], 4);
  220. };
  221. }
  222. });
  223. var Watermark = /* @__PURE__ */ pluginVue_exportHelper["default"](_sfc_main, [["__file", "watermark.vue"]]);
  224. exports["default"] = Watermark;
  225. //# sourceMappingURL=watermark2.js.map