UNPKG

@jkun/watermark

Version:
178 lines (172 loc) 7 kB
import { proxyCustomElement, HTMLElement, h, Host, writeTask } from '@stencil/core/internal/client'; /**获取缩放 */ function getPixelRatio() { return window.devicePixelRatio || 1; } /** * 旋转水印 * @param ctx canvas对象 * @param translateX x轴的偏移量 * @param translateY y轴偏移量 * @param rotate 旋转角度 */ function rotateWatermark(ctx, translateX, translateY, rotate) { ctx.translate(translateX, translateY); ctx.rotate((Math.PI / 180) * Number(rotate)); ctx.translate(-translateX, -translateY); } const ivyWatermarkCss = ":host{display:block;position:relative}.watermark{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;background-repeat:repeat}"; const IvyWatermark$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement { constructor() { super(); this.__registerHost(); this.__attachShadow(); this.BaseSize = 2; this.FontGap = 3; this.getMarkSize = (ctx) => { let defaultWidth = 120; let defaultHeight = 64; if (!this.image && ctx.measureText) { ctx.font = `${parseFloat(this.fontSize)}px ${this.fontFamily}`; const contents = [this.content]; const widths = contents.map(item => ctx.measureText(item).width); defaultWidth = Math.ceil(Math.max(...widths)); defaultHeight = parseFloat(this.fontSize) * contents.length + (contents.length - 1) * this.FontGap; } return [this.width ? parseFloat(this.width) : defaultWidth, this.height ? parseFloat(this.height) : defaultHeight]; }; this.fillTexts = (ctx, drawX, drawY, drawWidth, drawHeight) => { const ratio = getPixelRatio(); const mergedFontSize = parseFloat(this.fontSize) * ratio; ctx.font = `${this.fontStyle} normal ${this.fontWeight} ${mergedFontSize}px/${drawHeight}px ${this.fontFamily}`; ctx.fillStyle = this.fontColor; ctx.textAlign = 'center'; ctx.textBaseline = 'top'; ctx.translate(drawWidth / 2, 0); const contents = [this.content]; contents === null || contents === void 0 ? void 0 : contents.forEach((item, index) => { const y = drawY + index * (mergedFontSize + this.FontGap * ratio); ctx.fillText(item !== null && item !== void 0 ? item : '', drawX, y); }); }; this.appendWatermark = (base64Url, markWidth) => { if (this.watermarkRef) { this.waterSrc = base64Url; this.backgroundSize = `${(parseFloat(this.gapX) + markWidth) * this.BaseSize}px`; } }; this.renderWatermark = () => { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); if (ctx) { const ratio = getPixelRatio(); const [markWidth, markHeight] = this.getMarkSize(ctx); const canvasWidth = (parseFloat(this.gapX) + markWidth) * ratio; const canvasHeight = (parseFloat(this.gapY) + markHeight) * ratio; canvas.setAttribute('width', `${canvasWidth * this.BaseSize}px`); canvas.setAttribute('height', `${canvasHeight * this.BaseSize}px`); const drawX = (parseFloat(this.gapX) * ratio) / 2; const drawY = (parseFloat(this.gapY) * ratio) / 2; const drawWidth = markWidth * ratio; const drawHeight = markHeight * ratio; const rotateX = (drawWidth + parseFloat(this.gapX) * ratio) / 2; const rotateY = (drawHeight + parseFloat(this.gapY) * ratio) / 2; const alternateDrawX = drawX + canvasWidth; const alternateDrawY = drawY + canvasHeight; const alternateRotateX = rotateX + canvasWidth; const alternateRotateY = rotateY + canvasHeight; ctx.save(); rotateWatermark(ctx, rotateX, rotateY, parseFloat(this.rotate)); if (this.image) { const img = new Image(); img.onload = () => { ctx.drawImage(img, drawX, drawY, drawWidth, drawHeight); ctx.restore(); rotateWatermark(ctx, alternateRotateX, alternateRotateY, parseFloat(this.rotate)); ctx.drawImage(img, alternateDrawX, alternateDrawY, drawWidth, drawHeight); this.appendWatermark(canvas.toDataURL('image/png'), markWidth); }; img.crossOrigin = 'anonymous'; img.referrerPolicy = 'no-referrer'; img.src = this.image; } else { this.fillTexts(ctx, drawX, drawY, drawWidth, drawHeight); ctx.restore(); rotateWatermark(ctx, alternateRotateX, alternateRotateY, parseFloat(this.rotate)); this.fillTexts(ctx, alternateDrawX, alternateDrawY, drawWidth, drawHeight); this.appendWatermark(canvas.toDataURL('image/png'), markWidth); } } }; this.image = null; this.waterSrc = ''; this.backgroundSize = null; this.width = undefined; this.height = undefined; this.content = ''; this.rotate = '-22'; this.zIndex = '1000'; this.fontSize = '16px'; this.fontWeight = 'normal'; this.fontStyle = 'normal'; this.fontColor = 'rgba(0,0,0,0.15)'; this.fontFamily = 'PingFang SC, sans-serif'; this.gapX = '100'; this.gapY = '100'; this.offsetY = '0'; this.offsetX = '0'; this.watermarkIndex = '1000'; } watchZIndexHandler(val) { this.watermarkIndex = parseInt(val).toFixed(0); } render() { return (h(Host, null, h("div", { class: "watermark", ref: el => (this.watermarkRef = el), tabindex: "-1", style: { zIndex: this.watermarkIndex, backgroundImage: `url(${this.waterSrc})`, backgroundSize: this.backgroundSize } }), h("slot", null))); } componentDidLoad() { writeTask(() => { this.renderWatermark(); }); } static get watchers() { return { "zIndex": ["watchZIndexHandler"] }; } static get style() { return ivyWatermarkCss; } }, [1, "ivy-watermark", { "width": [1], "height": [1], "content": [1], "rotate": [1], "zIndex": [1, "z-index"], "fontSize": [1, "font-size"], "fontWeight": [1, "font-weight"], "fontStyle": [1, "font-style"], "fontColor": [1, "font-color"], "fontFamily": [1, "font-family"], "gapX": [1, "gap-x"], "gapY": [1, "gap-y"], "offsetY": [1, "offset-y"], "offsetX": [1, "offset-x"], "image": [32], "waterSrc": [32], "backgroundSize": [32], "watermarkIndex": [32] }]); function defineCustomElement$1() { if (typeof customElements === "undefined") { return; } const components = ["ivy-watermark"]; components.forEach(tagName => { switch (tagName) { case "ivy-watermark": if (!customElements.get(tagName)) { customElements.define(tagName, IvyWatermark$1); } break; } }); } defineCustomElement$1(); const IvyWatermark = IvyWatermark$1; const defineCustomElement = defineCustomElement$1; export { IvyWatermark, defineCustomElement };