UNPKG

@jkun/watermark

Version:
394 lines (393 loc) 11.8 kB
import { Host, h, writeTask } from '@stencil/core'; import { rotateWatermark, getPixelRatio } from '../../utils/utils'; export class IvyWatermark { constructor() { 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 is() { return "ivy-watermark"; } static get encapsulation() { return "shadow"; } static get originalStyleUrls() { return { "$": ["ivy-watermark.css"] }; } static get styleUrls() { return { "$": ["ivy-watermark.css"] }; } static get properties() { return { "width": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "width", "reflect": false }, "height": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "height", "reflect": false }, "content": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "content", "reflect": false, "defaultValue": "''" }, "rotate": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "rotate", "reflect": false, "defaultValue": "'-22'" }, "zIndex": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "z-index", "reflect": false, "defaultValue": "'1000'" }, "fontSize": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "font-size", "reflect": false, "defaultValue": "'16px'" }, "fontWeight": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "font-weight", "reflect": false, "defaultValue": "'normal'" }, "fontStyle": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "font-style", "reflect": false, "defaultValue": "'normal'" }, "fontColor": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "font-color", "reflect": false, "defaultValue": "'rgba(0,0,0,0.15)'" }, "fontFamily": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "font-family", "reflect": false, "defaultValue": "'PingFang SC, sans-serif'" }, "gapX": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "gap-x", "reflect": false, "defaultValue": "'100'" }, "gapY": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "gap-y", "reflect": false, "defaultValue": "'100'" }, "offsetY": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "offset-y", "reflect": false, "defaultValue": "'0'" }, "offsetX": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "offset-x", "reflect": false, "defaultValue": "'0'" } }; } static get states() { return { "image": {}, "waterSrc": {}, "backgroundSize": {}, "watermarkIndex": {} }; } static get watchers() { return [{ "propName": "zIndex", "methodName": "watchZIndexHandler" }]; } }