@idraw/renderer
Advanced tools
Comparing version 0.3.1 to 0.4.0-alpha.2
@@ -1,26 +0,11 @@ | ||
import { IDrawData, IDrawContext } from '@idraw/types'; | ||
import { RendererEvent } from './lib/renderer-event'; | ||
type Options = { | ||
width: number; | ||
height: number; | ||
contextWidth?: number; | ||
contextHeight?: number; | ||
devicePixelRatio: number; | ||
}; | ||
export default class Renderer extends RendererEvent { | ||
private _queue; | ||
private _ctx; | ||
private _status; | ||
import { EventEmitter } from '@idraw/util'; | ||
import type { Data, BoardRenderer, RendererOptions, RendererEventMap, RendererDrawOptions } from '@idraw/types'; | ||
export declare class Renderer extends EventEmitter<RendererEventMap> implements BoardRenderer { | ||
private _opts; | ||
private _loader; | ||
private _opts?; | ||
constructor(opts?: Options); | ||
render(target: HTMLCanvasElement | IDrawContext, originData: IDrawData, opts?: { | ||
changeResourceUUIDs?: string[]; | ||
}): void; | ||
getContext(): IDrawContext | null; | ||
thaw(): void; | ||
private _freeze; | ||
private _drawFrame; | ||
private _retainQueueOneItem; | ||
constructor(opts: RendererOptions); | ||
private _init; | ||
updateOptions(opts: RendererOptions): void; | ||
drawData(data: Data, opts: RendererDrawOptions): void; | ||
scale(num: number): void; | ||
} | ||
export {}; |
@@ -1,137 +0,59 @@ | ||
import { createUUID, deepClone, Context } from '@idraw/util'; | ||
import { drawContext } from './lib/draw'; | ||
import Loader from './lib/loader'; | ||
import { RendererEvent } from './lib/renderer-event'; | ||
const { requestAnimationFrame } = window; | ||
var DrawStatus; | ||
(function (DrawStatus) { | ||
DrawStatus["NULL"] = "null"; | ||
DrawStatus["FREE"] = "free"; | ||
DrawStatus["DRAWING"] = "drawing"; | ||
DrawStatus["FREEZE"] = "freeze"; | ||
})(DrawStatus || (DrawStatus = {})); | ||
export default class Renderer extends RendererEvent { | ||
import { EventEmitter } from '@idraw/util'; | ||
import { drawElementList } from './draw/index'; | ||
import { Loader } from './loader'; | ||
export class Renderer extends EventEmitter { | ||
constructor(opts) { | ||
super(); | ||
this._queue = []; | ||
this._ctx = null; | ||
this._status = DrawStatus.NULL; | ||
this._loader = new Loader(); | ||
this._opts = opts; | ||
this._loader = new Loader({ | ||
maxParallelNum: 6 | ||
this._init(); | ||
} | ||
_init() { | ||
const { _loader: loader } = this; | ||
loader.on('load', (e) => { | ||
this.trigger('load', e); | ||
}); | ||
this._loader.on('load', (res) => { | ||
this._drawFrame(); | ||
this.trigger('load', { element: res.element }); | ||
loader.on('error', () => { | ||
}); | ||
this._loader.on('error', (res) => { | ||
this.trigger('error', { element: res.element, error: res.error }); | ||
}); | ||
this._loader.on('complete', () => { | ||
this.trigger('loadComplete', { t: Date.now() }); | ||
}); | ||
} | ||
render(target, originData, opts) { | ||
const { changeResourceUUIDs = [] } = opts || {}; | ||
this._status = DrawStatus.FREE; | ||
const data = deepClone(originData); | ||
if (Array.isArray(data.elements)) { | ||
data.elements.forEach((elem) => { | ||
if (!(typeof elem.uuid === 'string' && elem.uuid)) { | ||
elem.uuid = createUUID(); | ||
} | ||
}); | ||
} | ||
if (!this._ctx) { | ||
if (this._opts && | ||
Object.prototype.toString.call(target) === '[object HTMLCanvasElement]') { | ||
const { width, height, contextWidth, contextHeight, devicePixelRatio } = this._opts; | ||
const canvas = target; | ||
canvas.width = width * devicePixelRatio; | ||
canvas.height = height * devicePixelRatio; | ||
const ctx2d = canvas.getContext('2d'); | ||
this._ctx = new Context(ctx2d, { | ||
updateOptions(opts) { | ||
this._opts = opts; | ||
} | ||
drawData(data, opts) { | ||
const { _loader: loader } = this; | ||
const { calculator } = this._opts; | ||
const { viewContext } = this._opts.viewContent; | ||
viewContext.clearRect(0, 0, viewContext.canvas.width, viewContext.canvas.height); | ||
const parentElementSize = { | ||
x: 0, | ||
y: 0, | ||
w: opts.viewSizeInfo.width, | ||
h: opts.viewSizeInfo.height | ||
}; | ||
drawElementList(viewContext, data, Object.assign({ loader, | ||
calculator, | ||
parentElementSize, elementAssets: data.assets }, opts)); | ||
} | ||
scale(num) { | ||
const { sharer } = this._opts; | ||
const { data, offsetTop, offsetBottom, offsetLeft, offsetRight, width, height, contextHeight, contextWidth, devicePixelRatio } = sharer.getActiveStoreSnapshot(); | ||
if (data) { | ||
this.drawData(data, { | ||
viewScaleInfo: { | ||
scale: num, | ||
offsetTop, | ||
offsetBottom, | ||
offsetLeft, | ||
offsetRight | ||
}, | ||
viewSizeInfo: { | ||
width, | ||
height, | ||
contextWidth: contextWidth || width, | ||
contextHeight: contextHeight || height, | ||
contextHeight, | ||
contextWidth, | ||
devicePixelRatio | ||
}); | ||
} | ||
else if (target) { | ||
this._ctx = target; | ||
} | ||
} | ||
if ([DrawStatus.FREEZE].includes(this._status)) { | ||
return; | ||
} | ||
const _data = deepClone({ data }); | ||
this._queue.push(_data); | ||
this._drawFrame(); | ||
this._loader.load(data, changeResourceUUIDs || []); | ||
} | ||
getContext() { | ||
return this._ctx; | ||
} | ||
thaw() { | ||
this._status = DrawStatus.FREE; | ||
} | ||
_freeze() { | ||
this._status = DrawStatus.FREEZE; | ||
} | ||
_drawFrame() { | ||
if (this._status === DrawStatus.FREEZE) { | ||
return; | ||
} | ||
requestAnimationFrame(() => { | ||
if (this._status === DrawStatus.FREEZE) { | ||
return; | ||
} | ||
const ctx = this._ctx; | ||
let item = this._queue[0]; | ||
let isLastFrame = false; | ||
if (this._queue.length > 1) { | ||
item = this._queue.shift(); | ||
} | ||
else { | ||
isLastFrame = true; | ||
} | ||
if (this._loader.isComplete() !== true) { | ||
this._drawFrame(); | ||
if (item && ctx) { | ||
drawContext(ctx, item.data, this._loader); | ||
} | ||
} | ||
else if (item && ctx) { | ||
drawContext(ctx, item.data, this._loader); | ||
this._retainQueueOneItem(); | ||
if (!isLastFrame) { | ||
this._drawFrame(); | ||
} | ||
else { | ||
this._status = DrawStatus.FREE; | ||
} | ||
} | ||
else { | ||
this._status = DrawStatus.FREE; | ||
} | ||
this.trigger('drawFrame', { t: Date.now() }); | ||
if (this._loader.isComplete() === true && | ||
this._queue.length === 1 && | ||
this._status === DrawStatus.FREE) { | ||
if (ctx && this._queue[0] && this._queue[0].data) { | ||
drawContext(ctx, this._queue[0].data, this._loader); | ||
} | ||
this.trigger('drawFrameComplete', { t: Date.now() }); | ||
this._freeze(); | ||
} | ||
}); | ||
} | ||
_retainQueueOneItem() { | ||
if (this._queue.length <= 1) { | ||
return; | ||
}); | ||
} | ||
const lastOne = deepClone(this._queue[this._queue.length - 1]); | ||
this._queue = [lastOne]; | ||
} | ||
} |
@@ -1,12 +0,6 @@ | ||
var iDrawRenderer = function() { | ||
var iDrawRenderer = function(exports) { | ||
"use strict"; | ||
function isColorStr(color2) { | ||
return typeof color2 === "string" && /^\#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(color2); | ||
return typeof color2 === "string" && (/^\#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(color2) || /^[a-z]{1,}$/i.test(color2)); | ||
} | ||
function createUUID() { | ||
function str4() { | ||
return ((1 + Math.random()) * 65536 | 0).toString(16).substring(1); | ||
} | ||
return `${str4()}${str4()}-${str4()}-${str4()}-${str4()}-${str4()}${str4()}${str4()}`; | ||
} | ||
function deepClone(target) { | ||
@@ -29,2 +23,6 @@ function _clone(t) { | ||
}); | ||
const symbolKeys = Object.getOwnPropertySymbols(t); | ||
symbolKeys.forEach((key) => { | ||
obj[key] = _clone(t[key]); | ||
}); | ||
return obj; | ||
@@ -35,8 +33,8 @@ } | ||
} | ||
function is$1(data) { | ||
return Object.prototype.toString.call(data).replace(/[\]|\[]{1,1}/ig, "").split(" ")[1]; | ||
function is$1(target) { | ||
return Object.prototype.toString.call(target).replace(/[\]|\[]{1,1}/gi, "").split(" ")[1]; | ||
} | ||
function parsePrototype(data) { | ||
const typeStr = Object.prototype.toString.call(data) || ""; | ||
const result = typeStr.replace(/(\[object|\])/ig, "").trim(); | ||
const result = typeStr.replace(/(\[object|\])/gi, "").trim(); | ||
return result; | ||
@@ -81,3 +79,6 @@ } | ||
const _svg = ` | ||
<svg xmlns="http://www.w3.org/2000/svg" width="${width || ""}" height = "${height || ""}"> | ||
<svg | ||
xmlns="http://www.w3.org/2000/svg" | ||
width="${width || ""}" | ||
height = "${height || ""}"> | ||
<foreignObject width="100%" height="100%"> | ||
@@ -167,3 +168,3 @@ <div xmlns = "http://www.w3.org/1999/xhtml"> | ||
function filterAmpersand(str) { | ||
return str.replace(/\&/ig, "&"); | ||
return str.replace(/\&/gi, "&"); | ||
} | ||
@@ -178,192 +179,2 @@ function loadHTML(html2, opts) { | ||
} | ||
class Context { | ||
constructor(ctx, opts) { | ||
this._opts = opts; | ||
this._ctx = ctx; | ||
this._transform = { | ||
scale: 1, | ||
scrollX: 0, | ||
scrollY: 0 | ||
}; | ||
} | ||
getContext() { | ||
return this._ctx; | ||
} | ||
resetSize(opts) { | ||
this._opts = Object.assign(Object.assign({}, this._opts), opts); | ||
} | ||
calcDeviceNum(num) { | ||
return num * this._opts.devicePixelRatio; | ||
} | ||
calcScreenNum(num) { | ||
return num / this._opts.devicePixelRatio; | ||
} | ||
getSize() { | ||
return { | ||
width: this._opts.width, | ||
height: this._opts.height, | ||
contextWidth: this._opts.contextWidth, | ||
contextHeight: this._opts.contextHeight, | ||
devicePixelRatio: this._opts.devicePixelRatio | ||
}; | ||
} | ||
setTransform(config) { | ||
this._transform = Object.assign(Object.assign({}, this._transform), config); | ||
} | ||
getTransform() { | ||
return { | ||
scale: this._transform.scale, | ||
scrollX: this._transform.scrollX, | ||
scrollY: this._transform.scrollY | ||
}; | ||
} | ||
setFillStyle(color2) { | ||
this._ctx.fillStyle = color2; | ||
} | ||
fill(fillRule) { | ||
return this._ctx.fill(fillRule || "nonzero"); | ||
} | ||
arc(x2, y2, radius, startAngle, endAngle, anticlockwise) { | ||
return this._ctx.arc(this._doSize(x2), this._doSize(y2), this._doSize(radius), startAngle, endAngle, anticlockwise); | ||
} | ||
rect(x2, y2, w2, h2) { | ||
return this._ctx.rect(this._doSize(x2), this._doSize(y2), this._doSize(w2), this._doSize(h2)); | ||
} | ||
fillRect(x2, y2, w2, h2) { | ||
return this._ctx.fillRect(this._doSize(x2), this._doSize(y2), this._doSize(w2), this._doSize(h2)); | ||
} | ||
clearRect(x2, y2, w2, h2) { | ||
return this._ctx.clearRect(this._doSize(x2), this._doSize(y2), this._doSize(w2), this._doSize(h2)); | ||
} | ||
beginPath() { | ||
return this._ctx.beginPath(); | ||
} | ||
closePath() { | ||
return this._ctx.closePath(); | ||
} | ||
lineTo(x2, y2) { | ||
return this._ctx.lineTo(this._doSize(x2), this._doSize(y2)); | ||
} | ||
moveTo(x2, y2) { | ||
return this._ctx.moveTo(this._doSize(x2), this._doSize(y2)); | ||
} | ||
arcTo(x1, y1, x2, y2, radius) { | ||
return this._ctx.arcTo(this._doSize(x1), this._doSize(y1), this._doSize(x2), this._doSize(y2), this._doSize(radius)); | ||
} | ||
setLineWidth(w2) { | ||
return this._ctx.lineWidth = this._doSize(w2); | ||
} | ||
setLineDash(nums) { | ||
return this._ctx.setLineDash(nums.map((n) => this._doSize(n))); | ||
} | ||
isPointInPath(x2, y2) { | ||
return this._ctx.isPointInPath(this._doX(x2), this._doY(y2)); | ||
} | ||
isPointInPathWithoutScroll(x2, y2) { | ||
return this._ctx.isPointInPath(this._doSize(x2), this._doSize(y2)); | ||
} | ||
setStrokeStyle(color2) { | ||
this._ctx.strokeStyle = color2; | ||
} | ||
stroke() { | ||
return this._ctx.stroke(); | ||
} | ||
translate(x2, y2) { | ||
return this._ctx.translate(this._doSize(x2), this._doSize(y2)); | ||
} | ||
rotate(angle2) { | ||
return this._ctx.rotate(angle2); | ||
} | ||
drawImage(...args) { | ||
const image = args[0]; | ||
const sx = args[1]; | ||
const sy = args[2]; | ||
const sw = args[3]; | ||
const sh = args[4]; | ||
const dx = args[args.length - 4]; | ||
const dy = args[args.length - 3]; | ||
const dw = args[args.length - 2]; | ||
const dh = args[args.length - 1]; | ||
if (args.length === 9) { | ||
return this._ctx.drawImage(image, this._doSize(sx), this._doSize(sy), this._doSize(sw), this._doSize(sh), this._doSize(dx), this._doSize(dy), this._doSize(dw), this._doSize(dh)); | ||
} else { | ||
return this._ctx.drawImage(image, this._doSize(dx), this._doSize(dy), this._doSize(dw), this._doSize(dh)); | ||
} | ||
} | ||
createPattern(image, repetition) { | ||
return this._ctx.createPattern(image, repetition); | ||
} | ||
measureText(text2) { | ||
return this._ctx.measureText(text2); | ||
} | ||
setTextAlign(align) { | ||
this._ctx.textAlign = align; | ||
} | ||
fillText(text2, x2, y2, maxWidth) { | ||
if (maxWidth !== void 0) { | ||
return this._ctx.fillText(text2, this._doSize(x2), this._doSize(y2), this._doSize(maxWidth)); | ||
} else { | ||
return this._ctx.fillText(text2, this._doSize(x2), this._doSize(y2)); | ||
} | ||
} | ||
strokeText(text2, x2, y2, maxWidth) { | ||
if (maxWidth !== void 0) { | ||
return this._ctx.strokeText(text2, this._doSize(x2), this._doSize(y2), this._doSize(maxWidth)); | ||
} else { | ||
return this._ctx.strokeText(text2, this._doSize(x2), this._doSize(y2)); | ||
} | ||
} | ||
setFont(opts) { | ||
const strList = []; | ||
if (opts.fontWeight === "bold") { | ||
strList.push(`${opts.fontWeight}`); | ||
} | ||
strList.push(`${this._doSize(opts.fontSize || 12)}px`); | ||
strList.push(`${opts.fontFamily || "sans-serif"}`); | ||
this._ctx.font = `${strList.join(" ")}`; | ||
} | ||
setTextBaseline(baseline) { | ||
this._ctx.textBaseline = baseline; | ||
} | ||
setGlobalAlpha(alpha) { | ||
this._ctx.globalAlpha = alpha; | ||
} | ||
save() { | ||
this._ctx.save(); | ||
} | ||
restore() { | ||
this._ctx.restore(); | ||
} | ||
scale(ratioX, ratioY) { | ||
this._ctx.scale(ratioX, ratioY); | ||
} | ||
setShadowColor(color2) { | ||
this._ctx.shadowColor = color2; | ||
} | ||
setShadowOffsetX(offsetX) { | ||
this._ctx.shadowOffsetX = this._doSize(offsetX); | ||
} | ||
setShadowOffsetY(offsetY) { | ||
this._ctx.shadowOffsetY = this._doSize(offsetY); | ||
} | ||
setShadowBlur(blur) { | ||
this._ctx.shadowBlur = this._doSize(blur); | ||
} | ||
ellipse(x2, y2, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise) { | ||
this._ctx.ellipse(this._doSize(x2), this._doSize(y2), this._doSize(radiusX), this._doSize(radiusY), rotation, startAngle, endAngle, counterclockwise); | ||
} | ||
_doSize(num) { | ||
return this._opts.devicePixelRatio * num; | ||
} | ||
_doX(x2) { | ||
const { scale, scrollX } = this._transform; | ||
const _x = (x2 - scrollX) / scale; | ||
return this._doSize(_x); | ||
} | ||
_doY(y2) { | ||
const { scale, scrollY } = this._transform; | ||
const _y = (y2 - scrollY) / scale; | ||
return this._doSize(_y); | ||
} | ||
} | ||
function number(value) { | ||
@@ -441,2 +252,5 @@ return typeof value === "number" && (value > 0 || value <= 0); | ||
} | ||
function numberStr(value) { | ||
return /^(-?\d+(?:\.\d+)?)$/.test(`${value}`); | ||
} | ||
const is = { | ||
@@ -449,2 +263,3 @@ x, | ||
number, | ||
numberStr, | ||
borderWidth, | ||
@@ -466,18 +281,56 @@ borderRadius, | ||
}; | ||
class EventEmitter { | ||
constructor() { | ||
this._listeners = /* @__PURE__ */ new Map(); | ||
} | ||
on(eventKey, callback) { | ||
if (this._listeners.has(eventKey)) { | ||
const callbacks = this._listeners.get(eventKey) || []; | ||
callbacks === null || callbacks === void 0 ? void 0 : callbacks.push(callback); | ||
this._listeners.set(eventKey, callbacks); | ||
} else { | ||
this._listeners.set(eventKey, [callback]); | ||
} | ||
} | ||
off(eventKey, callback) { | ||
if (this._listeners.has(eventKey)) { | ||
const callbacks = this._listeners.get(eventKey); | ||
if (Array.isArray(callbacks)) { | ||
for (let i = 0; i < (callbacks === null || callbacks === void 0 ? void 0 : callbacks.length); i++) { | ||
if (callbacks[i] === callback) { | ||
callbacks.splice(i, 1); | ||
break; | ||
} | ||
} | ||
} | ||
this._listeners.set(eventKey, callbacks || []); | ||
} | ||
} | ||
trigger(eventKey, e) { | ||
const callbacks = this._listeners.get(eventKey); | ||
if (Array.isArray(callbacks)) { | ||
callbacks.forEach((cb) => { | ||
cb(e); | ||
}); | ||
return true; | ||
} else { | ||
return false; | ||
} | ||
} | ||
has(name) { | ||
if (this._listeners.has(name)) { | ||
const list = this._listeners.get(name); | ||
if (Array.isArray(list) && list.length > 0) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
} | ||
function parseAngleToRadian(angle2) { | ||
return angle2 / 180 * Math.PI; | ||
} | ||
function calcElementCenter(elem) { | ||
const p = { | ||
x: elem.x + elem.w / 2, | ||
y: elem.y + elem.h / 2 | ||
}; | ||
return p; | ||
} | ||
function rotateElement(ctx, elem, callback) { | ||
const center = calcElementCenter(elem); | ||
const radian = parseAngleToRadian(elem.angle || 0); | ||
return rotateContext(ctx, center, radian || 0, callback); | ||
} | ||
function rotateContext(ctx, center, radian, callback) { | ||
function rotateElement(ctx, elemSize, callback) { | ||
const center = calcElementCenter(elemSize); | ||
const radian = parseAngleToRadian(elemSize.angle || 0); | ||
if (center && (radian > 0 || radian < 0)) { | ||
@@ -495,24 +348,100 @@ ctx.translate(center.x, center.y); | ||
} | ||
function clearContext(ctx) { | ||
ctx.setFillStyle("#000000"); | ||
ctx.setStrokeStyle("#000000"); | ||
ctx.setLineDash([]); | ||
ctx.setGlobalAlpha(1); | ||
ctx.setShadowColor("#00000000"); | ||
ctx.setShadowOffsetX(0); | ||
ctx.setShadowOffsetY(0); | ||
ctx.setShadowBlur(0); | ||
function calcElementCenter(elem) { | ||
const p = { | ||
x: elem.x + elem.w / 2, | ||
y: elem.y + elem.h / 2 | ||
}; | ||
return p; | ||
} | ||
function drawBgColor(ctx, color2) { | ||
const size = ctx.getSize(); | ||
ctx.setFillStyle(color2); | ||
ctx.fillRect(0, 0, size.contextWidth, size.contextHeight); | ||
function generateSVGPath(commands) { | ||
let path = ""; | ||
commands.forEach((item) => { | ||
path += item.type + item.params.join(" "); | ||
}); | ||
return path; | ||
} | ||
function drawBox(ctx, elem, pattern) { | ||
clearContext(ctx); | ||
drawBoxBorder(ctx, elem); | ||
clearContext(ctx); | ||
rotateElement(ctx, elem, () => { | ||
const { x: x2, y: y2, w: w2, h: h2 } = elem; | ||
let r = elem.desc.borderRadius || 0; | ||
function drawCircle(ctx, elem, opts) { | ||
const { detail, angle: angle2 } = elem; | ||
const { background = "#000000", borderColor = "#000000", borderWidth: borderWidth2 = 0 } = detail; | ||
const { calculator, viewScaleInfo, viewSizeInfo } = opts; | ||
const { x: x2, y: y2, w: w2, h: h2 } = calculator.elementSize({ x: elem.x, y: elem.y, w: elem.w, h: elem.h }, viewScaleInfo, viewSizeInfo); | ||
rotateElement(ctx, { x: x2, y: y2, w: w2, h: h2, angle: angle2 }, () => { | ||
const a = w2 / 2; | ||
const b = h2 / 2; | ||
const centerX = x2 + a; | ||
const centerY = y2 + b; | ||
if (borderWidth2 && borderWidth2 > 0) { | ||
const ba = borderWidth2 / 2 + a; | ||
const bb = borderWidth2 / 2 + b; | ||
ctx.beginPath(); | ||
ctx.strokeStyle = borderColor; | ||
ctx.lineWidth = borderWidth2; | ||
ctx.circle(centerX, centerY, ba, bb, 0, 0, 2 * Math.PI); | ||
ctx.closePath(); | ||
ctx.stroke(); | ||
} | ||
ctx.beginPath(); | ||
ctx.fillStyle = background; | ||
ctx.circle(centerX, centerY, a, b, 0, 0, 2 * Math.PI); | ||
ctx.closePath(); | ||
ctx.fill(); | ||
}); | ||
} | ||
function drawBox(ctx, viewElem, opts) { | ||
var _a, _b; | ||
if (((_a = viewElem == null ? void 0 : viewElem.detail) == null ? void 0 : _a.opacity) !== void 0 && ((_b = viewElem == null ? void 0 : viewElem.detail) == null ? void 0 : _b.opacity) > 0) { | ||
ctx.globalAlpha = viewElem.detail.opacity; | ||
} else { | ||
ctx.globalAlpha = 1; | ||
} | ||
const { pattern, renderContent, originElem, calcElemSize, viewScaleInfo, viewSizeInfo } = opts || {}; | ||
drawClipPath(ctx, viewElem, { | ||
originElem, | ||
calcElemSize, | ||
viewScaleInfo, | ||
viewSizeInfo, | ||
renderContent: () => { | ||
drawBoxBorder(ctx, viewElem, { viewScaleInfo, viewSizeInfo }); | ||
drawBoxBackground(ctx, viewElem, { pattern, viewScaleInfo, viewSizeInfo }); | ||
renderContent == null ? void 0 : renderContent(); | ||
} | ||
}); | ||
ctx.globalAlpha = 1; | ||
} | ||
function drawClipPath(ctx, viewElem, opts) { | ||
const { renderContent, originElem, calcElemSize, viewScaleInfo, viewSizeInfo } = opts; | ||
const totalScale = viewScaleInfo.scale * viewSizeInfo.devicePixelRatio; | ||
const { clipPath } = (originElem == null ? void 0 : originElem.detail) || {}; | ||
if (clipPath && calcElemSize && clipPath.commands) { | ||
const { x: x2, y: y2, w: w2, h: h2 } = calcElemSize; | ||
const { originW, originH, originX, originY } = clipPath; | ||
const scaleW = w2 / originW; | ||
const scaleH = h2 / originH; | ||
const viewOriginX = originX * scaleW; | ||
const viewOriginY = originY * scaleH; | ||
let internalX = x2 - viewOriginX; | ||
let internalY = y2 - viewOriginY; | ||
ctx.save(); | ||
ctx.translate(internalX, internalY); | ||
ctx.scale(totalScale * scaleW, totalScale * scaleH); | ||
const pathStr = generateSVGPath(clipPath.commands || []); | ||
const path2d = new Path2D(pathStr); | ||
ctx.clip(path2d); | ||
ctx.translate(0 - internalX, 0 - internalY); | ||
ctx.setTransform(1, 0, 0, 1, 0, 0); | ||
rotateElement(ctx, { ...viewElem }, () => { | ||
renderContent == null ? void 0 : renderContent(); | ||
}); | ||
ctx.restore(); | ||
} else { | ||
renderContent == null ? void 0 : renderContent(); | ||
} | ||
} | ||
function drawBoxBackground(ctx, viewElem, opts) { | ||
var _a, _b; | ||
const { pattern, viewScaleInfo } = opts; | ||
let transform = []; | ||
if (viewElem.detail.background || pattern) { | ||
const { x: x2, y: y2, w: w2, h: h2 } = viewElem; | ||
let r = (viewElem.detail.borderRadius || 0) * viewScaleInfo.scale; | ||
r = Math.min(r, w2 / 2, h2 / 2); | ||
@@ -530,25 +459,135 @@ if (w2 < r * 2 || h2 < r * 2) { | ||
if (typeof pattern === "string") { | ||
ctx.setFillStyle(pattern); | ||
ctx.fillStyle = pattern; | ||
} else if (["CanvasPattern"].includes(istype.type(pattern))) { | ||
ctx.setFillStyle(pattern); | ||
ctx.fillStyle = pattern; | ||
} else if (typeof viewElem.detail.background === "string") { | ||
ctx.fillStyle = viewElem.detail.background; | ||
} else if (((_a = viewElem.detail.background) == null ? void 0 : _a.type) === "linearGradient") { | ||
const { start, end, stops } = viewElem.detail.background; | ||
const viewStart = { | ||
x: start.x + x2, | ||
y: start.y + y2 | ||
}; | ||
const viewEnd = { | ||
x: end.x + x2, | ||
y: end.y + y2 | ||
}; | ||
const linearGradient = ctx.createLinearGradient(viewStart.x, viewStart.y, viewEnd.x, viewEnd.y); | ||
stops.forEach((stop) => { | ||
linearGradient.addColorStop(stop.offset, stop.color); | ||
}); | ||
ctx.fillStyle = linearGradient; | ||
} else if (((_b = viewElem.detail.background) == null ? void 0 : _b.type) === "radialGradient") { | ||
const { inner, outer, stops } = viewElem.detail.background; | ||
transform = viewElem.detail.background.transform || []; | ||
const viewInner = { | ||
x: inner.x, | ||
y: inner.y, | ||
radius: inner.radius * viewScaleInfo.scale | ||
}; | ||
const viewOuter = { | ||
x: outer.x, | ||
y: outer.y, | ||
radius: outer.radius * viewScaleInfo.scale | ||
}; | ||
const radialGradient = ctx.createRadialGradient(viewInner.x, viewInner.y, viewInner.radius, viewOuter.x, viewOuter.y, viewOuter.radius); | ||
stops.forEach((stop) => { | ||
radialGradient.addColorStop(stop.offset, stop.color); | ||
}); | ||
ctx.fillStyle = radialGradient; | ||
if (transform && transform.length > 0) { | ||
for (let i = 0; i < (transform == null ? void 0 : transform.length); i++) { | ||
const action = transform[i]; | ||
if (action.method === "translate") { | ||
ctx.translate(action.args[0] + x2, action.args[1] + y2); | ||
} else if (action.method === "rotate") { | ||
ctx.rotate(...action.args); | ||
} else if (action.method === "scale") { | ||
ctx.scale(...action.args); | ||
} | ||
} | ||
} | ||
} | ||
ctx.fill(); | ||
}); | ||
if (transform && transform.length > 0) { | ||
ctx.setTransform(1, 0, 0, 1, 0, 0); | ||
} | ||
} | ||
} | ||
function drawBoxBorder(ctx, elem) { | ||
clearContext(ctx); | ||
rotateElement(ctx, elem, () => { | ||
if (!(elem.desc.borderWidth && elem.desc.borderWidth > 0)) { | ||
return; | ||
function drawBoxBorder(ctx, viewElem, opts) { | ||
if (!isColorStr(viewElem.detail.borderColor)) { | ||
return; | ||
} | ||
const { viewScaleInfo } = opts; | ||
let borderColor = "#000000"; | ||
if (isColorStr(viewElem.detail.borderColor) === true) { | ||
borderColor = viewElem.detail.borderColor; | ||
} | ||
const { borderWidth: borderWidth2, borderRadius: borderRadius2, borderDash } = viewElem.detail; | ||
let bw = 0; | ||
if (typeof borderWidth2 === "number") { | ||
bw = borderWidth2 || 1; | ||
} | ||
bw = bw * viewScaleInfo.scale; | ||
let r = borderRadius2 || 0; | ||
ctx.strokeStyle = borderColor; | ||
ctx.setLineDash(borderDash || []); | ||
let borderTop = 0; | ||
let borderRight = 0; | ||
let borderBottom = 0; | ||
let borderLeft = 0; | ||
if (Array.isArray(borderWidth2)) { | ||
borderTop = borderWidth2[0] || 0; | ||
borderRight = borderWidth2[1] || 0; | ||
borderBottom = borderWidth2[2] || 0; | ||
borderLeft = borderWidth2[3] || 0; | ||
} | ||
if (borderLeft || borderRight || borderTop || borderBottom) { | ||
const { x: x2, y: y2, w: w2, h: h2 } = viewElem; | ||
if (borderLeft) { | ||
ctx.beginPath(); | ||
ctx.lineWidth = borderLeft * viewScaleInfo.scale; | ||
ctx.moveTo(x2, y2); | ||
ctx.lineTo(x2, y2 + h2); | ||
ctx.closePath(); | ||
ctx.stroke(); | ||
} | ||
const bw = elem.desc.borderWidth; | ||
let borderColor = "#000000"; | ||
if (isColorStr(elem.desc.borderColor) === true) { | ||
borderColor = elem.desc.borderColor; | ||
if (borderRight) { | ||
ctx.beginPath(); | ||
ctx.lineWidth = borderRight * viewScaleInfo.scale; | ||
ctx.moveTo(x2 + w2, y2); | ||
ctx.lineTo(x2 + w2, y2 + h2); | ||
ctx.closePath(); | ||
ctx.stroke(); | ||
} | ||
const x2 = elem.x - bw / 2; | ||
const y2 = elem.y - bw / 2; | ||
const w2 = elem.w + bw; | ||
const h2 = elem.h + bw; | ||
let r = elem.desc.borderRadius || 0; | ||
if (borderTop) { | ||
ctx.beginPath(); | ||
ctx.lineWidth = borderTop * viewScaleInfo.scale; | ||
ctx.moveTo(x2, y2); | ||
ctx.lineTo(x2 + w2, y2); | ||
ctx.closePath(); | ||
ctx.stroke(); | ||
} | ||
if (borderBottom) { | ||
ctx.beginPath(); | ||
ctx.lineWidth = borderBottom * viewScaleInfo.scale; | ||
ctx.moveTo(x2, y2 + h2); | ||
ctx.lineTo(x2 + w2, y2 + h2); | ||
ctx.closePath(); | ||
ctx.stroke(); | ||
} | ||
} else { | ||
let { x: x2, y: y2, w: w2, h: h2 } = viewElem; | ||
const { boxSizing } = viewElem.detail; | ||
if (boxSizing === "border-box") { | ||
x2 = viewElem.x; | ||
y2 = viewElem.y; | ||
w2 = viewElem.w; | ||
h2 = viewElem.h; | ||
} else { | ||
x2 = viewElem.x - bw; | ||
y2 = viewElem.y - bw; | ||
w2 = viewElem.w + bw * 2; | ||
h2 = viewElem.h + bw * 2; | ||
} | ||
r = Math.min(r, w2 / 2, h2 / 2); | ||
@@ -558,18 +597,4 @@ if (r < w2 / 2 && r < h2 / 2) { | ||
} | ||
const { desc } = elem; | ||
if (desc.shadowColor !== void 0 && isColorStr(desc.shadowColor)) { | ||
ctx.setShadowColor(desc.shadowColor); | ||
} | ||
if (desc.shadowOffsetX !== void 0 && is.number(desc.shadowOffsetX)) { | ||
ctx.setShadowOffsetX(desc.shadowOffsetX); | ||
} | ||
if (desc.shadowOffsetY !== void 0 && is.number(desc.shadowOffsetY)) { | ||
ctx.setShadowOffsetY(desc.shadowOffsetY); | ||
} | ||
if (desc.shadowBlur !== void 0 && is.number(desc.shadowBlur)) { | ||
ctx.setShadowBlur(desc.shadowBlur); | ||
} | ||
ctx.beginPath(); | ||
ctx.setLineWidth(bw); | ||
ctx.setStrokeStyle(borderColor); | ||
ctx.lineWidth = bw; | ||
ctx.moveTo(x2 + r, y2); | ||
@@ -582,681 +607,567 @@ ctx.arcTo(x2 + w2, y2, x2 + w2, y2 + h2, r); | ||
ctx.stroke(); | ||
} | ||
} | ||
function drawBoxShadow(ctx, viewElem, opts) { | ||
const { detail } = viewElem; | ||
const { viewScaleInfo, renderContent } = opts; | ||
const { shadowColor, shadowOffsetX, shadowOffsetY, shadowBlur } = detail; | ||
if (is.number(shadowBlur)) { | ||
ctx.save(); | ||
ctx.shadowColor = shadowColor || "#000000"; | ||
ctx.shadowOffsetX = (shadowOffsetX || 0) * viewScaleInfo.scale; | ||
ctx.shadowOffsetY = (shadowOffsetY || 0) * viewScaleInfo.scale; | ||
ctx.shadowBlur = (shadowBlur || 0) * viewScaleInfo.scale; | ||
renderContent(); | ||
ctx.restore(); | ||
} else { | ||
renderContent(); | ||
} | ||
} | ||
function drawRect(ctx, elem, opts) { | ||
const { calculator, viewScaleInfo, viewSizeInfo } = opts; | ||
let { x: x2, y: y2, w: w2, h: h2, angle: angle2 } = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo); | ||
const viewElem = { ...elem, ...{ x: x2, y: y2, w: w2, h: h2, angle: angle2 } }; | ||
rotateElement(ctx, { x: x2, y: y2, w: w2, h: h2, angle: angle2 }, () => { | ||
drawBoxShadow(ctx, viewElem, { | ||
viewScaleInfo, | ||
viewSizeInfo, | ||
renderContent: () => { | ||
drawBox(ctx, viewElem, { | ||
originElem: elem, | ||
calcElemSize: { x: x2, y: y2, w: w2, h: h2, angle: angle2 }, | ||
viewScaleInfo, | ||
viewSizeInfo, | ||
renderContent: () => { | ||
} | ||
}); | ||
} | ||
}); | ||
}); | ||
} | ||
function drawRect(ctx, elem) { | ||
drawBox(ctx, elem, elem.desc.bgColor); | ||
} | ||
function drawImage(ctx, elem, loader) { | ||
const content = loader.getContent(elem.uuid); | ||
rotateElement(ctx, elem, () => { | ||
if (content) { | ||
ctx.drawImage(content, elem.x, elem.y, elem.w, elem.h); | ||
function drawImage(ctx, elem, opts) { | ||
const content = opts.loader.getContent(elem.uuid); | ||
const { calculator, viewScaleInfo, viewSizeInfo } = opts; | ||
const { x: x2, y: y2, w: w2, h: h2, angle: angle2 } = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo); | ||
rotateElement(ctx, { x: x2, y: y2, w: w2, h: h2, angle: angle2 }, () => { | ||
if (!content) { | ||
opts.loader.load(elem, opts.elementAssets || {}); | ||
} | ||
if (elem.type === "image" && content) { | ||
ctx.drawImage(content, x2, y2, w2, h2); | ||
} | ||
}); | ||
} | ||
function drawSVG(ctx, elem, loader) { | ||
const content = loader.getContent(elem.uuid); | ||
rotateElement(ctx, elem, () => { | ||
if (content) { | ||
ctx.drawImage(content, elem.x, elem.y, elem.w, elem.h); | ||
function drawSVG(ctx, elem, opts) { | ||
const content = opts.loader.getContent(elem.uuid); | ||
const { calculator, viewScaleInfo, viewSizeInfo } = opts; | ||
const { x: x2, y: y2, w: w2, h: h2, angle: angle2 } = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo); | ||
rotateElement(ctx, { x: x2, y: y2, w: w2, h: h2, angle: angle2 }, () => { | ||
if (!content) { | ||
opts.loader.load(elem, opts.elementAssets || {}); | ||
} | ||
if (elem.type === "svg" && content) { | ||
ctx.drawImage(content, x2, y2, w2, h2); | ||
} | ||
}); | ||
} | ||
function drawHTML(ctx, elem, loader) { | ||
const content = loader.getContent(elem.uuid); | ||
rotateElement(ctx, elem, () => { | ||
if (content) { | ||
ctx.drawImage(content, elem.x, elem.y, elem.w, elem.h); | ||
function drawHTML(ctx, elem, opts) { | ||
const content = opts.loader.getContent(elem.uuid); | ||
const { calculator, viewScaleInfo, viewSizeInfo } = opts; | ||
const { x: x2, y: y2, w: w2, h: h2, angle: angle2 } = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo); | ||
rotateElement(ctx, { x: x2, y: y2, w: w2, h: h2, angle: angle2 }, () => { | ||
if (!content) { | ||
opts.loader.load(elem); | ||
} | ||
if (elem.type === "html" && content) { | ||
ctx.drawImage(content, x2, y2, w2, h2); | ||
} | ||
}); | ||
} | ||
function drawText(ctx, elem, loader) { | ||
clearContext(ctx); | ||
drawBox(ctx, elem, elem.desc.bgColor || "transparent"); | ||
rotateElement(ctx, elem, () => { | ||
const desc = { | ||
...{ | ||
fontSize: 12, | ||
fontFamily: "sans-serif", | ||
textAlign: "center" | ||
}, | ||
...elem.desc | ||
}; | ||
ctx.setFillStyle(elem.desc.color); | ||
ctx.setTextBaseline("top"); | ||
ctx.setFont({ | ||
fontWeight: desc.fontWeight, | ||
fontSize: desc.fontSize, | ||
fontFamily: desc.fontFamily | ||
}); | ||
const descText = desc.text.replace(/\r\n/gi, "\n"); | ||
const fontHeight = desc.lineHeight || desc.fontSize; | ||
const descTextList = descText.split("\n"); | ||
const lines = []; | ||
let lineNum = 0; | ||
descTextList.forEach((tempText, idx) => { | ||
let lineText = ""; | ||
if (tempText.length > 0) { | ||
for (let i = 0; i < tempText.length; i++) { | ||
if (ctx.measureText(lineText + (tempText[i] || "")).width < ctx.calcDeviceNum(elem.w)) { | ||
lineText += tempText[i] || ""; | ||
function drawText(ctx, elem, opts) { | ||
const { calculator, viewScaleInfo, viewSizeInfo } = opts; | ||
const { x: x2, y: y2, w: w2, h: h2, angle: angle2 } = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo); | ||
const viewElem = { ...elem, ...{ x: x2, y: y2, w: w2, h: h2, angle: angle2 } }; | ||
rotateElement(ctx, { x: x2, y: y2, w: w2, h: h2, angle: angle2 }, () => { | ||
drawBox(ctx, viewElem, { | ||
originElem: elem, | ||
calcElemSize: { x: x2, y: y2, w: w2, h: h2, angle: angle2 }, | ||
viewScaleInfo, | ||
viewSizeInfo, | ||
renderContent: () => { | ||
const detail = { | ||
...{ | ||
fontSize: 12, | ||
fontFamily: "sans-serif", | ||
textAlign: "center" | ||
}, | ||
...elem.detail | ||
}; | ||
const fontSize2 = detail.fontSize * viewScaleInfo.scale; | ||
const lineHeight2 = detail.lineHeight ? detail.lineHeight * viewScaleInfo.scale : fontSize2; | ||
ctx.fillStyle = elem.detail.color; | ||
ctx.textBaseline = "top"; | ||
ctx.$setFont({ | ||
fontWeight: detail.fontWeight, | ||
fontSize: fontSize2, | ||
fontFamily: detail.fontFamily | ||
}); | ||
const detailText = detail.text.replace(/\r\n/gi, "\n"); | ||
const fontHeight = lineHeight2; | ||
const detailTextList = detailText.split("\n"); | ||
const lines = []; | ||
let lineNum = 0; | ||
detailTextList.forEach((tempText, idx) => { | ||
let lineText = ""; | ||
if (tempText.length > 0) { | ||
for (let i = 0; i < tempText.length; i++) { | ||
if (ctx.measureText(lineText + (tempText[i] || "")).width < ctx.$doPixelRatio(w2)) { | ||
lineText += tempText[i] || ""; | ||
} else { | ||
lines.push({ | ||
text: lineText, | ||
width: ctx.$undoPixelRatio(ctx.measureText(lineText).width) | ||
}); | ||
lineText = tempText[i] || ""; | ||
lineNum++; | ||
} | ||
if ((lineNum + 1) * fontHeight > h2) { | ||
break; | ||
} | ||
if (tempText.length - 1 === i) { | ||
if ((lineNum + 1) * fontHeight < h2) { | ||
lines.push({ | ||
text: lineText, | ||
width: ctx.$undoPixelRatio(ctx.measureText(lineText).width) | ||
}); | ||
if (idx < detailTextList.length - 1) { | ||
lineNum++; | ||
} | ||
break; | ||
} | ||
} | ||
} | ||
} else { | ||
lines.push({ | ||
text: lineText, | ||
width: ctx.calcScreenNum(ctx.measureText(lineText).width) | ||
text: "", | ||
width: 0 | ||
}); | ||
lineText = tempText[i] || ""; | ||
lineNum++; | ||
} | ||
if ((lineNum + 1) * fontHeight > elem.h) { | ||
break; | ||
}); | ||
let startY = 0; | ||
if (lines.length * fontHeight < h2) { | ||
if (elem.detail.verticalAlign === "top") { | ||
startY = 0; | ||
} else if (elem.detail.verticalAlign === "bottom") { | ||
startY += h2 - lines.length * fontHeight; | ||
} else { | ||
startY += (h2 - lines.length * fontHeight) / 2; | ||
} | ||
if (tempText.length - 1 === i) { | ||
if ((lineNum + 1) * fontHeight < elem.h) { | ||
lines.push({ | ||
text: lineText, | ||
width: ctx.calcScreenNum(ctx.measureText(lineText).width) | ||
}); | ||
if (idx < descTextList.length - 1) { | ||
lineNum++; | ||
} | ||
break; | ||
} | ||
{ | ||
const _y = y2 + startY; | ||
if (detail.textShadowColor !== void 0 && isColorStr(detail.textShadowColor)) { | ||
ctx.shadowColor = detail.textShadowColor; | ||
} | ||
if (detail.textShadowOffsetX !== void 0 && is.number(detail.textShadowOffsetX)) { | ||
ctx.shadowOffsetX = detail.textShadowOffsetX; | ||
} | ||
if (detail.textShadowOffsetY !== void 0 && is.number(detail.textShadowOffsetY)) { | ||
ctx.shadowOffsetY = detail.textShadowOffsetY; | ||
} | ||
if (detail.textShadowBlur !== void 0 && is.number(detail.textShadowBlur)) { | ||
ctx.shadowBlur = detail.textShadowBlur; | ||
} | ||
lines.forEach((line, i) => { | ||
let _x = x2; | ||
if (detail.textAlign === "center") { | ||
_x = x2 + (w2 - line.width) / 2; | ||
} else if (detail.textAlign === "right") { | ||
_x = x2 + (w2 - line.width); | ||
} | ||
} | ||
ctx.fillText(line.text, _x, _y + fontHeight * i); | ||
}); | ||
} | ||
} else { | ||
lines.push({ | ||
text: "", | ||
width: 0 | ||
}); | ||
} | ||
}); | ||
let startY = 0; | ||
if (lines.length * fontHeight < elem.h) { | ||
if (elem.desc.verticalAlign === "top") { | ||
startY = 0; | ||
} else if (elem.desc.verticalAlign === "bottom") { | ||
startY += elem.h - lines.length * fontHeight; | ||
} else { | ||
startY += (elem.h - lines.length * fontHeight) / 2; | ||
} | ||
} | ||
{ | ||
const _y = elem.y + startY; | ||
if (desc.textShadowColor !== void 0 && isColorStr(desc.textShadowColor)) { | ||
ctx.setShadowColor(desc.textShadowColor); | ||
} | ||
if (desc.textShadowOffsetX !== void 0 && is.number(desc.textShadowOffsetX)) { | ||
ctx.setShadowOffsetX(desc.textShadowOffsetX); | ||
} | ||
if (desc.textShadowOffsetY !== void 0 && is.number(desc.textShadowOffsetY)) { | ||
ctx.setShadowOffsetY(desc.textShadowOffsetY); | ||
} | ||
if (desc.textShadowBlur !== void 0 && is.number(desc.textShadowBlur)) { | ||
ctx.setShadowBlur(desc.textShadowBlur); | ||
} | ||
lines.forEach((line, i) => { | ||
let _x = elem.x; | ||
if (desc.textAlign === "center") { | ||
_x = elem.x + (elem.w - line.width) / 2; | ||
} else if (desc.textAlign === "right") { | ||
_x = elem.x + (elem.w - line.width); | ||
} | ||
ctx.fillText(line.text, _x, _y + fontHeight * i); | ||
}); | ||
clearContext(ctx); | ||
} | ||
if (isColorStr(desc.strokeColor) && desc.strokeWidth !== void 0 && desc.strokeWidth > 0) { | ||
const _y = elem.y + startY; | ||
lines.forEach((line, i) => { | ||
let _x = elem.x; | ||
if (desc.textAlign === "center") { | ||
_x = elem.x + (elem.w - line.width) / 2; | ||
} else if (desc.textAlign === "right") { | ||
_x = elem.x + (elem.w - line.width); | ||
} | ||
if (desc.strokeColor !== void 0) { | ||
ctx.setStrokeStyle(desc.strokeColor); | ||
} | ||
if (desc.strokeWidth !== void 0 && desc.strokeWidth > 0) { | ||
ctx.setLineWidth(desc.strokeWidth); | ||
} | ||
ctx.strokeText(line.text, _x, _y + fontHeight * i); | ||
}); | ||
} | ||
}); | ||
} | ||
function drawCircle(ctx, elem) { | ||
clearContext(ctx); | ||
rotateElement(ctx, elem, (ctx2) => { | ||
const { x: x2, y: y2, w: w2, h: h2, desc } = elem; | ||
const { | ||
bgColor = "#000000", | ||
borderColor = "#000000", | ||
borderWidth: borderWidth2 = 0 | ||
} = desc; | ||
const a = w2 / 2; | ||
const b = h2 / 2; | ||
const centerX = x2 + a; | ||
const centerY = y2 + b; | ||
if (borderWidth2 && borderWidth2 > 0) { | ||
const ba = borderWidth2 / 2 + a; | ||
const bb = borderWidth2 / 2 + b; | ||
ctx2.beginPath(); | ||
ctx2.setStrokeStyle(borderColor); | ||
ctx2.setLineWidth(borderWidth2); | ||
ctx2.ellipse(centerX, centerY, ba, bb, 0, 0, 2 * Math.PI); | ||
ctx2.closePath(); | ||
ctx2.stroke(); | ||
} | ||
ctx2.beginPath(); | ||
ctx2.setFillStyle(bgColor); | ||
ctx2.ellipse(centerX, centerY, a, b, 0, 0, 2 * Math.PI); | ||
ctx2.closePath(); | ||
ctx2.fill(); | ||
function drawPath(ctx, elem, opts) { | ||
const { detail } = elem; | ||
const { originX, originY, originW, originH } = detail; | ||
const { calculator, viewScaleInfo, viewSizeInfo } = opts; | ||
const { x: x2, y: y2, w: w2, h: h2, angle: angle2 } = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo); | ||
const scaleW = w2 / originW; | ||
const scaleH = h2 / originH; | ||
const viewOriginX = originX * scaleW; | ||
const viewOriginY = originY * scaleH; | ||
const internalX = x2 - viewOriginX; | ||
const internalY = y2 - viewOriginY; | ||
const scaleNum = viewScaleInfo.scale * viewSizeInfo.devicePixelRatio; | ||
const viewElem = { ...elem, ...{ x: x2, y: y2, w: w2, h: h2, angle: angle2 } }; | ||
rotateElement(ctx, { x: x2, y: y2, w: w2, h: h2, angle: angle2 }, () => { | ||
drawBox(ctx, viewElem, { | ||
originElem: elem, | ||
calcElemSize: { x: x2, y: y2, w: w2, h: h2, angle: angle2 }, | ||
viewScaleInfo, | ||
viewSizeInfo, | ||
renderContent: () => { | ||
drawBoxShadow(ctx, viewElem, { | ||
viewScaleInfo, | ||
viewSizeInfo, | ||
renderContent: () => { | ||
ctx.save(); | ||
ctx.translate(internalX, internalY); | ||
ctx.scale(scaleNum * scaleW / viewScaleInfo.scale, scaleNum * scaleH / viewScaleInfo.scale); | ||
const pathStr = generateSVGPath(detail.commands || []); | ||
const path2d = new Path2D(pathStr); | ||
if (detail.fill) { | ||
ctx.fillStyle = detail.fill; | ||
ctx.fill(path2d); | ||
} | ||
if (detail.stroke && detail.strokeWidth !== 0) { | ||
ctx.strokeStyle = detail.stroke; | ||
ctx.lineWidth = (detail.strokeWidth || 1) / viewSizeInfo.devicePixelRatio; | ||
ctx.lineCap = detail.strokeLineCap || "square"; | ||
ctx.stroke(path2d); | ||
} | ||
ctx.translate(-internalX, -internalY); | ||
ctx.restore(); | ||
} | ||
}); | ||
} | ||
}); | ||
}); | ||
} | ||
function drawContext(ctx, data, loader) { | ||
function drawElement(ctx, elem, opts) { | ||
var _a; | ||
clearContext(ctx); | ||
const size = ctx.getSize(); | ||
ctx.clearRect(0, 0, size.contextWidth, size.contextHeight); | ||
if (typeof data.bgColor === "string" && isColorStr(data.bgColor)) { | ||
drawBgColor(ctx, data.bgColor); | ||
} | ||
if (!(data.elements.length > 0)) { | ||
if (((_a = elem == null ? void 0 : elem.operations) == null ? void 0 : _a.invisible) === true) { | ||
return; | ||
} | ||
for (let i = 0; i < data.elements.length; i++) { | ||
const elem = data.elements[i]; | ||
if (((_a = elem == null ? void 0 : elem.operation) == null ? void 0 : _a.invisible) === true) { | ||
continue; | ||
} | ||
try { | ||
switch (elem.type) { | ||
case "rect": { | ||
drawRect(ctx, elem); | ||
drawRect(ctx, elem, opts); | ||
break; | ||
} | ||
case "circle": { | ||
drawCircle(ctx, elem, opts); | ||
break; | ||
} | ||
case "text": { | ||
drawText(ctx, elem); | ||
drawText(ctx, elem, opts); | ||
break; | ||
} | ||
case "image": { | ||
drawImage(ctx, elem, loader); | ||
drawImage(ctx, elem, opts); | ||
break; | ||
} | ||
case "svg": { | ||
drawSVG(ctx, elem, loader); | ||
drawSVG(ctx, elem, opts); | ||
break; | ||
} | ||
case "html": { | ||
drawHTML(ctx, elem, loader); | ||
drawHTML(ctx, elem, opts); | ||
break; | ||
} | ||
case "circle": { | ||
drawCircle(ctx, elem); | ||
case "path": { | ||
drawPath(ctx, elem, opts); | ||
break; | ||
} | ||
case "group": { | ||
drawGroup(ctx, elem, opts); | ||
break; | ||
} | ||
default: { | ||
break; | ||
} | ||
} | ||
} catch (err) { | ||
console.error(err); | ||
} | ||
} | ||
class LoaderEvent { | ||
constructor() { | ||
this._listeners = /* @__PURE__ */ new Map(); | ||
} | ||
on(eventKey, callback) { | ||
if (this._listeners.has(eventKey)) { | ||
const callbacks = this._listeners.get(eventKey); | ||
callbacks == null ? void 0 : callbacks.push(callback); | ||
this._listeners.set(eventKey, callbacks || []); | ||
} else { | ||
this._listeners.set(eventKey, [callback]); | ||
} | ||
} | ||
off(eventKey, callback) { | ||
if (this._listeners.has(eventKey)) { | ||
const callbacks = this._listeners.get(eventKey); | ||
if (Array.isArray(callbacks)) { | ||
for (let i = 0; i < (callbacks == null ? void 0 : callbacks.length); i++) { | ||
if (callbacks[i] === callback) { | ||
callbacks.splice(i, 1); | ||
break; | ||
function drawGroup(ctx, elem, opts) { | ||
const { calculator, viewScaleInfo, viewSizeInfo } = opts; | ||
const { x: x2, y: y2, w: w2, h: h2, angle: angle2 } = calculator.elementSize({ x: elem.x, y: elem.y, w: elem.w, h: elem.h, angle: elem.angle }, viewScaleInfo, viewSizeInfo); | ||
const viewElem = { ...elem, ...{ x: x2, y: y2, w: w2, h: h2, angle: angle2 } }; | ||
rotateElement(ctx, { x: x2, y: y2, w: w2, h: h2, angle: angle2 }, () => { | ||
drawBox(ctx, viewElem, { | ||
originElem: elem, | ||
calcElemSize: { x: x2, y: y2, w: w2, h: h2, angle: angle2 }, | ||
viewScaleInfo, | ||
viewSizeInfo, | ||
renderContent: () => { | ||
if (Array.isArray(elem.detail.children)) { | ||
const { parentElementSize: parentSize } = opts; | ||
const newParentSize = { | ||
x: parentSize.x + elem.x, | ||
y: parentSize.y + elem.y, | ||
w: elem.w || parentSize.w, | ||
h: elem.h || parentSize.h, | ||
angle: elem.angle | ||
}; | ||
const { calculator: calculator2 } = opts; | ||
if (elem.detail.overflow === "hidden") { | ||
ctx.save(); | ||
ctx.beginPath(); | ||
ctx.moveTo(x2, y2); | ||
ctx.lineTo(x2 + w2, y2); | ||
ctx.lineTo(x2 + w2, y2 + h2); | ||
ctx.lineTo(x2, y2 + h2); | ||
ctx.closePath(); | ||
ctx.clip(); | ||
} | ||
for (let i = 0; i < elem.detail.children.length; i++) { | ||
let child = elem.detail.children[i]; | ||
child = { | ||
...child, | ||
...{ | ||
x: newParentSize.x + child.x, | ||
y: newParentSize.y + child.y | ||
} | ||
}; | ||
if (!calculator2.isElementInView(child, opts.viewScaleInfo, opts.viewSizeInfo)) { | ||
continue; | ||
} | ||
try { | ||
drawElement(ctx, child, { ...opts }); | ||
} catch (err) { | ||
console.error(err); | ||
} | ||
} | ||
ctx.restore(); | ||
} | ||
} | ||
this._listeners.set(eventKey, callbacks || []); | ||
}); | ||
}); | ||
} | ||
function drawElementList(ctx, data, opts) { | ||
const { elements = [] } = data; | ||
for (let i = 0; i < elements.length; i++) { | ||
const elem = elements[i]; | ||
if (!opts.calculator.isElementInView(elem, opts.viewScaleInfo, opts.viewSizeInfo)) { | ||
continue; | ||
} | ||
} | ||
trigger(eventKey, arg) { | ||
const callbacks = this._listeners.get(eventKey); | ||
if (Array.isArray(callbacks)) { | ||
callbacks.forEach((cb) => { | ||
cb(arg); | ||
}); | ||
return true; | ||
} else { | ||
return false; | ||
try { | ||
drawElement(ctx, elem, opts); | ||
} catch (err) { | ||
console.error(err); | ||
} | ||
} | ||
has(name) { | ||
if (this._listeners.has(name)) { | ||
const list = this._listeners.get(name); | ||
if (Array.isArray(list) && list.length > 0) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
} | ||
function filterScript(html2) { | ||
return html2.replace(/<script[\s\S]*?<\/script>/ig, ""); | ||
} | ||
class Loader { | ||
constructor(opts) { | ||
this._currentLoadData = {}; | ||
this._currentUUIDQueue = []; | ||
this._storageLoadData = {}; | ||
this._status = "free"; | ||
this._waitingLoadQueue = []; | ||
this._opts = opts; | ||
this._event = new LoaderEvent(); | ||
this._waitingLoadQueue = []; | ||
} | ||
load(data, changeResourceUUIDs) { | ||
const [uuidQueue, loadData] = this._resetLoadData( | ||
data, | ||
changeResourceUUIDs | ||
); | ||
if (this._status === "free" || this._status === "complete") { | ||
this._currentUUIDQueue = uuidQueue; | ||
this._currentLoadData = loadData; | ||
this._loadTask(); | ||
} else if (this._status === "loading" && uuidQueue.length > 0) { | ||
this._waitingLoadQueue.push({ | ||
uuidQueue, | ||
loadData | ||
const supportElementTypes = ["image", "svg", "html"]; | ||
class Loader extends EventEmitter { | ||
constructor() { | ||
super(); | ||
this._loadFuncMap = {}; | ||
this._currentLoadItemMap = {}; | ||
this._storageLoadItemMap = {}; | ||
this._registerLoadFunc("image", async (elem, assets) => { | ||
var _a; | ||
const src = ((_a = assets[elem.detail.src]) == null ? void 0 : _a.value) || elem.detail.src; | ||
const content = await loadImage(src); | ||
return { | ||
uuid: elem.uuid, | ||
lastModified: Date.now(), | ||
content | ||
}; | ||
}); | ||
this._registerLoadFunc("html", async (elem, assets) => { | ||
var _a; | ||
const html2 = ((_a = assets[elem.detail.html]) == null ? void 0 : _a.value) || elem.detail.html; | ||
const content = await loadHTML(html2, { | ||
width: elem.detail.width || elem.w, | ||
height: elem.detail.height || elem.h | ||
}); | ||
} | ||
return { | ||
uuid: elem.uuid, | ||
lastModified: Date.now(), | ||
content | ||
}; | ||
}); | ||
this._registerLoadFunc("svg", async (elem, assets) => { | ||
var _a; | ||
const svg2 = ((_a = assets[elem.detail.svg]) == null ? void 0 : _a.value) || elem.detail.svg; | ||
const content = await loadSVG(svg2); | ||
return { | ||
uuid: elem.uuid, | ||
lastModified: Date.now(), | ||
content | ||
}; | ||
}); | ||
} | ||
on(name, callback) { | ||
this._event.on(name, callback); | ||
_registerLoadFunc(type, func) { | ||
this._loadFuncMap[type] = func; | ||
} | ||
off(name, callback) { | ||
this._event.off(name, callback); | ||
} | ||
isComplete() { | ||
return this._status === "complete"; | ||
} | ||
getContent(uuid) { | ||
var _a; | ||
if (((_a = this._storageLoadData[uuid]) == null ? void 0 : _a.status) === "loaded") { | ||
return this._storageLoadData[uuid].content; | ||
_getLoadElementSource(element) { | ||
var _a, _b, _c; | ||
let source = null; | ||
if (element.type === "image") { | ||
source = ((_a = element == null ? void 0 : element.detail) == null ? void 0 : _a.src) || null; | ||
} else if (element.type === "svg") { | ||
source = ((_b = element == null ? void 0 : element.detail) == null ? void 0 : _b.svg) || null; | ||
} else if (element.type === "html") { | ||
source = ((_c = element == null ? void 0 : element.detail) == null ? void 0 : _c.html) || null; | ||
} | ||
return null; | ||
return source; | ||
} | ||
// getPattern( | ||
// elem: DataElement<keyof DataElemDesc>, | ||
// opts?: { | ||
// forceUpdate: boolean | ||
// } | ||
// ): null | CanvasPattern { | ||
// if (this._patternMap[elem.uuid] ) { | ||
// if (!(opts && opts.forceUpdate === true)) { | ||
// return this._patternMap[elem.uuid]; | ||
// } | ||
// } | ||
// const item = this._currentLoadData[elem.uuid]; | ||
// if (item?.status === 'loaded') { | ||
// const board = this._opts.board; | ||
// const tempCanvas = board.createCanvas(); | ||
// const tempCtx = board.createContext(tempCanvas); | ||
// const image = this.getContent(elem.uuid); | ||
// tempCtx.drawImage(image, elem.x, elem.y, elem.w, elem.h); | ||
// const canvas = board.createCanvas(); | ||
// const ctx = board.createContext(canvas); | ||
// const pattern = ctx.createPattern(tempCanvas, 'no-repeat'); | ||
// if (pattern) this._patternMap[elem.uuid] = pattern; | ||
// return pattern; | ||
// } | ||
// return null; | ||
// } | ||
_resetLoadData(data, changeResourceUUIDs) { | ||
const loadData = {}; | ||
const uuidQueue = []; | ||
const storageLoadData = this._storageLoadData; | ||
for (let i = data.elements.length - 1; i >= 0; i--) { | ||
const elem = data.elements[i]; | ||
if (["image", "svg", "html"].includes(elem.type)) { | ||
if (!storageLoadData[elem.uuid]) { | ||
loadData[elem.uuid] = this._createEmptyLoadItem(elem); | ||
uuidQueue.push(elem.uuid); | ||
} else { | ||
if (changeResourceUUIDs.includes(elem.uuid)) { | ||
loadData[elem.uuid] = this._createEmptyLoadItem(elem); | ||
uuidQueue.push(elem.uuid); | ||
} | ||
} | ||
} | ||
} | ||
return [uuidQueue, loadData]; | ||
} | ||
_createEmptyLoadItem(elem) { | ||
let source = ""; | ||
const type = elem.type; | ||
let elemW = elem.w; | ||
let elemH = elem.h; | ||
if (elem.type === "image") { | ||
const _elem = elem; | ||
source = _elem.desc.src || ""; | ||
} else if (elem.type === "svg") { | ||
const _elem = elem; | ||
source = _elem.desc.svg || ""; | ||
} else if (elem.type === "html") { | ||
const _elem = elem; | ||
source = filterScript(_elem.desc.html || ""); | ||
elemW = _elem.desc.width || elem.w; | ||
elemH = _elem.desc.height || elem.h; | ||
} | ||
_createLoadItem(element) { | ||
return { | ||
uuid: elem.uuid, | ||
type, | ||
element, | ||
status: "null", | ||
content: null, | ||
source, | ||
elemW, | ||
elemH, | ||
element: deepClone(elem) | ||
error: null, | ||
startTime: -1, | ||
endTime: -1, | ||
source: this._getLoadElementSource(element) | ||
}; | ||
} | ||
_loadTask() { | ||
if (this._status === "loading") { | ||
return; | ||
} | ||
this._status = "loading"; | ||
if (this._currentUUIDQueue.length === 0) { | ||
if (this._waitingLoadQueue.length === 0) { | ||
this._status = "complete"; | ||
this._event.trigger("complete", void 0); | ||
return; | ||
} else { | ||
const waitingItem = this._waitingLoadQueue.shift(); | ||
if (waitingItem) { | ||
const { uuidQueue, loadData } = waitingItem; | ||
this._currentLoadData = loadData; | ||
this._currentUUIDQueue = uuidQueue; | ||
} | ||
_emitLoad(item) { | ||
const uuid = item.element.uuid; | ||
const storageItem = this._storageLoadItemMap[uuid]; | ||
if (storageItem) { | ||
if (storageItem.startTime < item.startTime) { | ||
this._storageLoadItemMap[uuid] = item; | ||
this.trigger("load", { ...item, countTime: item.endTime - item.startTime }); | ||
} | ||
} | ||
const { maxParallelNum } = this._opts; | ||
const uuids = this._currentUUIDQueue.splice(0, maxParallelNum); | ||
uuids.forEach((url, i) => { | ||
}); | ||
const loadUUIDList = []; | ||
const _loadAction = () => { | ||
if (loadUUIDList.length >= maxParallelNum) { | ||
return false; | ||
} | ||
if (uuids.length === 0) { | ||
return true; | ||
} | ||
for (let i = loadUUIDList.length; i < maxParallelNum; i++) { | ||
const uuid = uuids.shift(); | ||
if (uuid === void 0) { | ||
break; | ||
} | ||
loadUUIDList.push(uuid); | ||
this._loadElementSource(this._currentLoadData[uuid]).then((image) => { | ||
var _a, _b; | ||
loadUUIDList.splice(loadUUIDList.indexOf(uuid), 1); | ||
const status = _loadAction(); | ||
this._storageLoadData[uuid] = { | ||
uuid, | ||
type: this._currentLoadData[uuid].type, | ||
status: "loaded", | ||
content: image, | ||
source: this._currentLoadData[uuid].source, | ||
elemW: this._currentLoadData[uuid].elemW, | ||
elemH: this._currentLoadData[uuid].elemH, | ||
element: this._currentLoadData[uuid].element | ||
}; | ||
if (loadUUIDList.length === 0 && uuids.length === 0 && status === true) { | ||
this._status = "free"; | ||
this._loadTask(); | ||
} | ||
this._event.trigger("load", { | ||
uuid: (_a = this._storageLoadData[uuid]) == null ? void 0 : _a.uuid, | ||
type: this._storageLoadData[uuid].type, | ||
status: this._storageLoadData[uuid].status, | ||
content: this._storageLoadData[uuid].content, | ||
source: this._storageLoadData[uuid].source, | ||
elemW: this._storageLoadData[uuid].elemW, | ||
elemH: this._storageLoadData[uuid].elemH, | ||
element: (_b = this._storageLoadData[uuid]) == null ? void 0 : _b.element | ||
}); | ||
}).catch((err) => { | ||
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l; | ||
console.warn(err); | ||
loadUUIDList.splice(loadUUIDList.indexOf(uuid), 1); | ||
const status = _loadAction(); | ||
if (this._currentLoadData[uuid]) { | ||
this._storageLoadData[uuid] = { | ||
uuid, | ||
type: (_a = this._currentLoadData[uuid]) == null ? void 0 : _a.type, | ||
status: "fail", | ||
content: null, | ||
error: err, | ||
source: (_b = this._currentLoadData[uuid]) == null ? void 0 : _b.source, | ||
elemW: (_c = this._currentLoadData[uuid]) == null ? void 0 : _c.elemW, | ||
elemH: (_d = this._currentLoadData[uuid]) == null ? void 0 : _d.elemH, | ||
element: (_e = this._currentLoadData[uuid]) == null ? void 0 : _e.element | ||
}; | ||
} | ||
if (loadUUIDList.length === 0 && uuids.length === 0 && status === true) { | ||
this._status = "free"; | ||
this._loadTask(); | ||
} | ||
if (this._currentLoadData[uuid]) { | ||
this._event.trigger("error", { | ||
uuid, | ||
type: (_f = this._storageLoadData[uuid]) == null ? void 0 : _f.type, | ||
status: (_g = this._storageLoadData[uuid]) == null ? void 0 : _g.status, | ||
content: (_h = this._storageLoadData[uuid]) == null ? void 0 : _h.content, | ||
source: (_i = this._storageLoadData[uuid]) == null ? void 0 : _i.source, | ||
elemW: (_j = this._storageLoadData[uuid]) == null ? void 0 : _j.elemW, | ||
elemH: (_k = this._storageLoadData[uuid]) == null ? void 0 : _k.elemH, | ||
element: (_l = this._storageLoadData[uuid]) == null ? void 0 : _l.element | ||
}); | ||
} | ||
}); | ||
} | ||
return false; | ||
}; | ||
_loadAction(); | ||
} | ||
async _loadElementSource(params) { | ||
if (params && params.type === "image") { | ||
const image = await loadImage(params.source); | ||
return image; | ||
} else if (params && params.type === "svg") { | ||
const image = await loadSVG(params.source); | ||
return image; | ||
} else if (params && params.type === "html") { | ||
const image = await loadHTML(params.source, { | ||
width: params.elemW, | ||
height: params.elemH | ||
}); | ||
return image; | ||
} | ||
throw Error("Element's source is not support!"); | ||
} | ||
} | ||
class RendererEvent { | ||
constructor() { | ||
this._listeners = /* @__PURE__ */ new Map(); | ||
} | ||
on(eventKey, callback) { | ||
if (this._listeners.has(eventKey)) { | ||
const callbacks = this._listeners.get(eventKey); | ||
callbacks == null ? void 0 : callbacks.push(callback); | ||
this._listeners.set(eventKey, callbacks || []); | ||
} else { | ||
this._listeners.set(eventKey, [callback]); | ||
this._storageLoadItemMap[uuid] = item; | ||
this.trigger("load", { ...item, countTime: item.endTime - item.startTime }); | ||
} | ||
} | ||
off(eventKey, callback) { | ||
if (this._listeners.has(eventKey)) { | ||
const callbacks = this._listeners.get(eventKey); | ||
if (Array.isArray(callbacks)) { | ||
for (let i = 0; i < (callbacks == null ? void 0 : callbacks.length); i++) { | ||
if (callbacks[i] === callback) { | ||
callbacks.splice(i, 1); | ||
break; | ||
} | ||
} | ||
_emitError(item) { | ||
const uuid = item.element.uuid; | ||
const storageItem = this._storageLoadItemMap[uuid]; | ||
if (storageItem) { | ||
if (storageItem.startTime < item.startTime) { | ||
this._storageLoadItemMap[uuid] = item; | ||
this.trigger("error", { ...item, countTime: item.endTime - item.startTime }); | ||
} | ||
this._listeners.set(eventKey, callbacks || []); | ||
} else { | ||
this._storageLoadItemMap[uuid] = item; | ||
this.trigger("error", { ...item, countTime: item.endTime - item.startTime }); | ||
} | ||
} | ||
trigger(eventKey, arg) { | ||
const callbacks = this._listeners.get(eventKey); | ||
if (Array.isArray(callbacks)) { | ||
callbacks.forEach((cb) => { | ||
cb(arg); | ||
_loadResource(element, assets) { | ||
const item = this._createLoadItem(element); | ||
this._currentLoadItemMap[element.uuid] = item; | ||
const loadFunc = this._loadFuncMap[element.type]; | ||
if (typeof loadFunc === "function") { | ||
item.startTime = Date.now(); | ||
loadFunc(element, assets).then((result) => { | ||
item.content = result.content; | ||
item.endTime = Date.now(); | ||
item.status = "load"; | ||
this._emitLoad(item); | ||
}).catch((err) => { | ||
console.warn(`Load element source "${item.source}" fail`, err, element); | ||
item.endTime = Date.now(); | ||
item.status = "error"; | ||
item.error = err; | ||
this._emitError(item); | ||
}); | ||
return true; | ||
} else { | ||
return false; | ||
} | ||
} | ||
has(name) { | ||
if (this._listeners.has(name)) { | ||
const list = this._listeners.get(name); | ||
if (Array.isArray(list) && list.length > 0) { | ||
return true; | ||
} | ||
_isExistingErrorStorage(element) { | ||
var _a; | ||
const existItem = (_a = this._currentLoadItemMap) == null ? void 0 : _a[element == null ? void 0 : element.uuid]; | ||
if (existItem && existItem.status === "error" && existItem.source && existItem.source === this._getLoadElementSource(element)) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
load(element, assets) { | ||
if (this._isExistingErrorStorage(element)) { | ||
return; | ||
} | ||
if (supportElementTypes.includes(element.type)) { | ||
const elem = deepClone(element); | ||
this._loadResource(elem, assets); | ||
} | ||
} | ||
getContent(uuid) { | ||
var _a, _b; | ||
return ((_b = (_a = this._storageLoadItemMap) == null ? void 0 : _a[uuid]) == null ? void 0 : _b.content) || null; | ||
} | ||
} | ||
const { requestAnimationFrame } = window; | ||
class Renderer extends RendererEvent { | ||
class Renderer extends EventEmitter { | ||
// private _draftContextTop: CanvasRenderingContext2D; | ||
// private _draftContextMiddle: CanvasRenderingContext2D; | ||
// private _draftContextBottom: CanvasRenderingContext2D; | ||
constructor(opts) { | ||
super(); | ||
this._queue = []; | ||
this._ctx = null; | ||
this._status = "null"; | ||
this._loader = new Loader(); | ||
this._opts = opts; | ||
this._loader = new Loader({ | ||
maxParallelNum: 6 | ||
this._init(); | ||
} | ||
_init() { | ||
const { _loader: loader } = this; | ||
loader.on("load", (e) => { | ||
this.trigger("load", e); | ||
}); | ||
this._loader.on("load", (res) => { | ||
this._drawFrame(); | ||
this.trigger("load", { element: res.element }); | ||
loader.on("error", () => { | ||
}); | ||
this._loader.on("error", (res) => { | ||
this.trigger("error", { element: res.element, error: res.error }); | ||
} | ||
updateOptions(opts) { | ||
this._opts = opts; | ||
} | ||
drawData(data, opts) { | ||
const { _loader: loader } = this; | ||
const { calculator } = this._opts; | ||
const { viewContext } = this._opts.viewContent; | ||
viewContext.clearRect(0, 0, viewContext.canvas.width, viewContext.canvas.height); | ||
const parentElementSize = { | ||
x: 0, | ||
y: 0, | ||
w: opts.viewSizeInfo.width, | ||
h: opts.viewSizeInfo.height | ||
}; | ||
drawElementList(viewContext, data, { | ||
loader, | ||
calculator, | ||
parentElementSize, | ||
elementAssets: data.assets, | ||
...opts | ||
}); | ||
this._loader.on("complete", () => { | ||
this.trigger("loadComplete", { t: Date.now() }); | ||
}); | ||
} | ||
render(target, originData, opts) { | ||
const { changeResourceUUIDs = [] } = opts || {}; | ||
this._status = "free"; | ||
const data = deepClone(originData); | ||
if (Array.isArray(data.elements)) { | ||
data.elements.forEach((elem) => { | ||
if (!(typeof elem.uuid === "string" && elem.uuid)) { | ||
elem.uuid = createUUID(); | ||
} | ||
}); | ||
} | ||
if (!this._ctx) { | ||
if (this._opts && Object.prototype.toString.call(target) === "[object HTMLCanvasElement]") { | ||
const { width, height, contextWidth, contextHeight, devicePixelRatio } = this._opts; | ||
const canvas = target; | ||
canvas.width = width * devicePixelRatio; | ||
canvas.height = height * devicePixelRatio; | ||
const ctx2d = canvas.getContext("2d"); | ||
this._ctx = new Context(ctx2d, { | ||
scale(num) { | ||
const { sharer } = this._opts; | ||
const { data, offsetTop, offsetBottom, offsetLeft, offsetRight, width, height, contextHeight, contextWidth, devicePixelRatio } = sharer.getActiveStoreSnapshot(); | ||
if (data) { | ||
this.drawData(data, { | ||
viewScaleInfo: { | ||
scale: num, | ||
offsetTop, | ||
offsetBottom, | ||
offsetLeft, | ||
offsetRight | ||
}, | ||
viewSizeInfo: { | ||
width, | ||
height, | ||
contextWidth: contextWidth || width, | ||
contextHeight: contextHeight || height, | ||
contextHeight, | ||
contextWidth, | ||
devicePixelRatio | ||
}); | ||
} else if (target) { | ||
this._ctx = target; | ||
} | ||
} | ||
if ([ | ||
"freeze" | ||
/* FREEZE */ | ||
].includes(this._status)) { | ||
return; | ||
} | ||
const _data = deepClone({ data }); | ||
this._queue.push(_data); | ||
this._drawFrame(); | ||
this._loader.load(data, changeResourceUUIDs || []); | ||
} | ||
getContext() { | ||
return this._ctx; | ||
} | ||
thaw() { | ||
this._status = "free"; | ||
} | ||
_freeze() { | ||
this._status = "freeze"; | ||
} | ||
_drawFrame() { | ||
if (this._status === "freeze") { | ||
return; | ||
} | ||
requestAnimationFrame(() => { | ||
if (this._status === "freeze") { | ||
return; | ||
} | ||
const ctx = this._ctx; | ||
let item = this._queue[0]; | ||
let isLastFrame = false; | ||
if (this._queue.length > 1) { | ||
item = this._queue.shift(); | ||
} else { | ||
isLastFrame = true; | ||
} | ||
if (this._loader.isComplete() !== true) { | ||
this._drawFrame(); | ||
if (item && ctx) { | ||
drawContext(ctx, item.data, this._loader); | ||
} | ||
} else if (item && ctx) { | ||
drawContext(ctx, item.data, this._loader); | ||
this._retainQueueOneItem(); | ||
if (!isLastFrame) { | ||
this._drawFrame(); | ||
} else { | ||
this._status = "free"; | ||
} | ||
} else { | ||
this._status = "free"; | ||
} | ||
this.trigger("drawFrame", { t: Date.now() }); | ||
if (this._loader.isComplete() === true && this._queue.length === 1 && this._status === "free") { | ||
if (ctx && this._queue[0] && this._queue[0].data) { | ||
drawContext(ctx, this._queue[0].data, this._loader); | ||
} | ||
this.trigger("drawFrameComplete", { t: Date.now() }); | ||
this._freeze(); | ||
} | ||
}); | ||
} | ||
_retainQueueOneItem() { | ||
if (this._queue.length <= 1) { | ||
return; | ||
}); | ||
} | ||
const lastOne = deepClone(this._queue[this._queue.length - 1]); | ||
this._queue = [lastOne]; | ||
} | ||
// scroll(opts: { offsetTop?: number; offsetLeft?: number }) { | ||
// const { sharer } = this._opts; | ||
// const { data, scale, offsetTop, offsetBottom, offsetLeft, offsetRight } = sharer.getActiveStoreSnapshot(); | ||
// // TODO calc offset data | ||
// if (data) { | ||
// this.drawData(data, { | ||
// scale, | ||
// offsetTop, | ||
// offsetBottom, | ||
// offsetLeft, | ||
// offsetRight | ||
// }); | ||
// } | ||
// // sharer.setActiveStorage('scale', num); | ||
// } | ||
} | ||
return Renderer; | ||
}(); | ||
exports.Renderer = Renderer; | ||
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); | ||
return exports; | ||
}({}); |
@@ -1,1 +0,1 @@ | ||
var iDrawRenderer=function(){"use strict";function t(t){return"string"==typeof t&&/^\#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(t)}function e(t){return function t(e){const s=(i=e,Object.prototype.toString.call(i).replace(/[\]|\[]{1,1}/gi,"").split(" ")[1]);var i;if(["Null","Number","String","Boolean","Undefined"].indexOf(s)>=0)return e;if("Array"===s){const s=[];return e.forEach((e=>{s.push(t(e))})),s}if("Object"===s){const s={};return Object.keys(e).forEach((i=>{s[i]=t(e[i])})),s}}(t)}function s(t){return(Object.prototype.toString.call(t)||"").replace(/(\[object|\])/gi,"").trim()}const i={type(t,e){const i=s(t);return!0===e?i.toLocaleLowerCase():i},array:t=>"Array"===s(t),json:t=>"Object"===s(t),function:t=>"Function"===s(t),asyncFunction:t=>"AsyncFunction"===s(t),string:t=>"String"===s(t),number:t=>"Number"===s(t),undefined:t=>"Undefined"===s(t),null:t=>"Null"===s(t),promise:t=>"Promise"===s(t)};var o=globalThis&&globalThis.__awaiter||function(t,e,s,i){return new(s||(s=Promise))((function(o,r){function n(t){try{h(i.next(t))}catch(t){r(t)}}function a(t){try{h(i.throw(t))}catch(t){r(t)}}function h(t){var e;t.done?o(t.value):(e=t.value,e instanceof s?e:new s((function(t){t(e)}))).then(n,a)}h((i=i.apply(t,e||[])).next())}))};const{Image:r}=window;function n(t){return new Promise(((e,s)=>{const i=new r;i.crossOrigin="anonymous",i.onload=function(){e(i)},i.onabort=s,i.onerror=s,i.src=t}))}function a(t){return o(this,void 0,void 0,(function*(){const e=yield function(t){return new Promise(((e,s)=>{const i=new Blob([t],{type:"image/svg+xml;charset=utf-8"}),o=new FileReader;o.readAsDataURL(i),o.onload=function(t){var s;const i=null===(s=null==t?void 0:t.target)||void 0===s?void 0:s.result;e(i)},o.onerror=function(t){s(t)}}))}(t);return yield n(e)}))}function h(t,e){return o(this,void 0,void 0,(function*(){t=t.replace(/\&/gi,"&");const s=yield function(t,e){const{width:s,height:i}=e;return new Promise(((e,o)=>{const r=new Blob([`\n <svg xmlns="http://www.w3.org/2000/svg" width="${s||""}" height = "${i||""}">\n <foreignObject width="100%" height="100%">\n <div xmlns = "http://www.w3.org/1999/xhtml">\n ${t}\n </div>\n </foreignObject>\n </svg>\n `],{type:"image/svg+xml;charset=utf-8"}),n=new FileReader;n.readAsDataURL(r),n.onload=function(t){var s;const i=null===(s=null==t?void 0:t.target)||void 0===s?void 0:s.result;e(i)},n.onerror=function(t){o(t)}}))}(t,e);return yield n(s)}))}class l{constructor(t,e){this._opts=e,this._ctx=t,this._transform={scale:1,scrollX:0,scrollY:0}}getContext(){return this._ctx}resetSize(t){this._opts=Object.assign(Object.assign({},this._opts),t)}calcDeviceNum(t){return t*this._opts.devicePixelRatio}calcScreenNum(t){return t/this._opts.devicePixelRatio}getSize(){return{width:this._opts.width,height:this._opts.height,contextWidth:this._opts.contextWidth,contextHeight:this._opts.contextHeight,devicePixelRatio:this._opts.devicePixelRatio}}setTransform(t){this._transform=Object.assign(Object.assign({},this._transform),t)}getTransform(){return{scale:this._transform.scale,scrollX:this._transform.scrollX,scrollY:this._transform.scrollY}}setFillStyle(t){this._ctx.fillStyle=t}fill(t){return this._ctx.fill(t||"nonzero")}arc(t,e,s,i,o,r){return this._ctx.arc(this._doSize(t),this._doSize(e),this._doSize(s),i,o,r)}rect(t,e,s,i){return this._ctx.rect(this._doSize(t),this._doSize(e),this._doSize(s),this._doSize(i))}fillRect(t,e,s,i){return this._ctx.fillRect(this._doSize(t),this._doSize(e),this._doSize(s),this._doSize(i))}clearRect(t,e,s,i){return this._ctx.clearRect(this._doSize(t),this._doSize(e),this._doSize(s),this._doSize(i))}beginPath(){return this._ctx.beginPath()}closePath(){return this._ctx.closePath()}lineTo(t,e){return this._ctx.lineTo(this._doSize(t),this._doSize(e))}moveTo(t,e){return this._ctx.moveTo(this._doSize(t),this._doSize(e))}arcTo(t,e,s,i,o){return this._ctx.arcTo(this._doSize(t),this._doSize(e),this._doSize(s),this._doSize(i),this._doSize(o))}setLineWidth(t){return this._ctx.lineWidth=this._doSize(t)}setLineDash(t){return this._ctx.setLineDash(t.map((t=>this._doSize(t))))}isPointInPath(t,e){return this._ctx.isPointInPath(this._doX(t),this._doY(e))}isPointInPathWithoutScroll(t,e){return this._ctx.isPointInPath(this._doSize(t),this._doSize(e))}setStrokeStyle(t){this._ctx.strokeStyle=t}stroke(){return this._ctx.stroke()}translate(t,e){return this._ctx.translate(this._doSize(t),this._doSize(e))}rotate(t){return this._ctx.rotate(t)}drawImage(...t){const e=t[0],s=t[1],i=t[2],o=t[3],r=t[4],n=t[t.length-4],a=t[t.length-3],h=t[t.length-2],l=t[t.length-1];return 9===t.length?this._ctx.drawImage(e,this._doSize(s),this._doSize(i),this._doSize(o),this._doSize(r),this._doSize(n),this._doSize(a),this._doSize(h),this._doSize(l)):this._ctx.drawImage(e,this._doSize(n),this._doSize(a),this._doSize(h),this._doSize(l))}createPattern(t,e){return this._ctx.createPattern(t,e)}measureText(t){return this._ctx.measureText(t)}setTextAlign(t){this._ctx.textAlign=t}fillText(t,e,s,i){return void 0!==i?this._ctx.fillText(t,this._doSize(e),this._doSize(s),this._doSize(i)):this._ctx.fillText(t,this._doSize(e),this._doSize(s))}strokeText(t,e,s,i){return void 0!==i?this._ctx.strokeText(t,this._doSize(e),this._doSize(s),this._doSize(i)):this._ctx.strokeText(t,this._doSize(e),this._doSize(s))}setFont(t){const e=[];"bold"===t.fontWeight&&e.push(`${t.fontWeight}`),e.push(`${this._doSize(t.fontSize||12)}px`),e.push(`${t.fontFamily||"sans-serif"}`),this._ctx.font=`${e.join(" ")}`}setTextBaseline(t){this._ctx.textBaseline=t}setGlobalAlpha(t){this._ctx.globalAlpha=t}save(){this._ctx.save()}restore(){this._ctx.restore()}scale(t,e){this._ctx.scale(t,e)}setShadowColor(t){this._ctx.shadowColor=t}setShadowOffsetX(t){this._ctx.shadowOffsetX=this._doSize(t)}setShadowOffsetY(t){this._ctx.shadowOffsetY=this._doSize(t)}setShadowBlur(t){this._ctx.shadowBlur=this._doSize(t)}ellipse(t,e,s,i,o,r,n,a){this._ctx.ellipse(this._doSize(t),this._doSize(e),this._doSize(s),this._doSize(i),o,r,n,a)}_doSize(t){return this._opts.devicePixelRatio*t}_doX(t){const{scale:e,scrollX:s}=this._transform,i=(t-s)/e;return this._doSize(i)}_doY(t){const{scale:e,scrollY:s}=this._transform,i=(t-s)/e;return this._doSize(i)}}function u(t){return"number"==typeof t&&(t>0||t<=0)}function c(t){return"number"==typeof t&&t>=0}function d(t){return"string"==typeof t&&/^(http:\/\/|https:\/\/|\.\/|\/)/.test(`${t}`)}function _(t){return"string"==typeof t&&/^(data:image\/)/.test(`${t}`)}const f={x:function(t){return u(t)},y:function(t){return u(t)},w:c,h:function(t){return"number"==typeof t&&t>=0},angle:function(t){return"number"==typeof t&&t>=-360&&t<=360},number:u,borderWidth:function(t){return c(t)},borderRadius:function(t){return u(t)&&t>=0},color:function(e){return t(e)},imageSrc:function(t){return _(t)||d(t)},imageURL:d,imageBase64:_,svg:function(t){return"string"==typeof t&&/^(<svg[\s]{1,}|<svg>)/i.test(`${t}`.trim())&&/<\/[\s]{0,}svg>$/i.test(`${t}`.trim())},html:function(t){let e=!1;if("string"==typeof t){let s=document.createElement("div");s.innerHTML=t,s.children.length>0&&(e=!0),s=null}return e},text:function(t){return"string"==typeof t},fontSize:function(t){return u(t)&&t>0},lineHeight:function(t){return u(t)&&t>0},textAlign:function(t){return["center","left","right"].includes(t)},fontFamily:function(t){return"string"==typeof t&&t.length>0},fontWeight:function(t){return["bold"].includes(t)},strokeWidth:function(t){return u(t)&&t>0}};function g(t,e,s){const i=function(t){return{x:t.x+t.w/2,y:t.y+t.h/2}}(e);return function(t,e,s,i){e&&(s>0||s<0)&&(t.translate(e.x,e.y),t.rotate(s),t.translate(-e.x,-e.y));i(t),e&&(s>0||s<0)&&(t.translate(e.x,e.y),t.rotate(-s),t.translate(-e.x,-e.y))}(t,i,(e.angle||0)/180*Math.PI||0,s)}function m(t){t.setFillStyle("#000000"),t.setStrokeStyle("#000000"),t.setLineDash([]),t.setGlobalAlpha(1),t.setShadowColor("#00000000"),t.setShadowOffsetX(0),t.setShadowOffsetY(0),t.setShadowBlur(0)}function x(e,s,o){m(e),function(e,s){m(e),g(e,s,(()=>{if(!(s.desc.borderWidth&&s.desc.borderWidth>0))return;const i=s.desc.borderWidth;let o="#000000";!0===t(s.desc.borderColor)&&(o=s.desc.borderColor);const r=s.x-i/2,n=s.y-i/2,a=s.w+i,h=s.h+i;let l=s.desc.borderRadius||0;l=Math.min(l,a/2,h/2),l<a/2&&l<h/2&&(l+=i/2);const{desc:u}=s;void 0!==u.shadowColor&&t(u.shadowColor)&&e.setShadowColor(u.shadowColor),void 0!==u.shadowOffsetX&&f.number(u.shadowOffsetX)&&e.setShadowOffsetX(u.shadowOffsetX),void 0!==u.shadowOffsetY&&f.number(u.shadowOffsetY)&&e.setShadowOffsetY(u.shadowOffsetY),void 0!==u.shadowBlur&&f.number(u.shadowBlur)&&e.setShadowBlur(u.shadowBlur),e.beginPath(),e.setLineWidth(i),e.setStrokeStyle(o),e.moveTo(r+l,n),e.arcTo(r+a,n,r+a,n+h,l),e.arcTo(r+a,n+h,r,n+h,l),e.arcTo(r,n+h,r,n,l),e.arcTo(r,n,r+a,n,l),e.closePath(),e.stroke()}))}(e,s),m(e),g(e,s,(()=>{const{x:t,y:r,w:n,h:a}=s;let h=s.desc.borderRadius||0;h=Math.min(h,n/2,a/2),(n<2*h||a<2*h)&&(h=0),e.beginPath(),e.moveTo(t+h,r),e.arcTo(t+n,r,t+n,r+a,h),e.arcTo(t+n,r+a,t,r+a,h),e.arcTo(t,r+a,t,r,h),e.arcTo(t,r,t+n,r,h),e.closePath(),("string"==typeof o||["CanvasPattern"].includes(i.type(o)))&&e.setFillStyle(o),e.fill()}))}function w(t,e){x(t,e,e.desc.bgColor)}function S(t,e,s){const i=s.getContent(e.uuid);g(t,e,(()=>{i&&t.drawImage(i,e.x,e.y,e.w,e.h)}))}function p(t,e,s){const i=s.getContent(e.uuid);g(t,e,(()=>{i&&t.drawImage(i,e.x,e.y,e.w,e.h)}))}function y(t,e,s){const i=s.getContent(e.uuid);g(t,e,(()=>{i&&t.drawImage(i,e.x,e.y,e.w,e.h)}))}function v(e,s,i){m(e),x(e,s,s.desc.bgColor||"transparent"),g(e,s,(()=>{const i={fontSize:12,fontFamily:"sans-serif",textAlign:"center",...s.desc};e.setFillStyle(s.desc.color),e.setTextBaseline("top"),e.setFont({fontWeight:i.fontWeight,fontSize:i.fontSize,fontFamily:i.fontFamily});const o=i.text.replace(/\r\n/gi,"\n"),r=i.lineHeight||i.fontSize,n=o.split("\n"),a=[];let h=0;n.forEach(((t,i)=>{let o="";if(t.length>0){for(let l=0;l<t.length&&(e.measureText(o+(t[l]||"")).width<e.calcDeviceNum(s.w)?o+=t[l]||"":(a.push({text:o,width:e.calcScreenNum(e.measureText(o).width)}),o=t[l]||"",h++),!((h+1)*r>s.h));l++)if(t.length-1===l&&(h+1)*r<s.h){a.push({text:o,width:e.calcScreenNum(e.measureText(o).width)}),i<n.length-1&&h++;break}}else a.push({text:"",width:0})}));let l=0;a.length*r<s.h&&("top"===s.desc.verticalAlign?l=0:"bottom"===s.desc.verticalAlign?l+=s.h-a.length*r:l+=(s.h-a.length*r)/2);{const o=s.y+l;void 0!==i.textShadowColor&&t(i.textShadowColor)&&e.setShadowColor(i.textShadowColor),void 0!==i.textShadowOffsetX&&f.number(i.textShadowOffsetX)&&e.setShadowOffsetX(i.textShadowOffsetX),void 0!==i.textShadowOffsetY&&f.number(i.textShadowOffsetY)&&e.setShadowOffsetY(i.textShadowOffsetY),void 0!==i.textShadowBlur&&f.number(i.textShadowBlur)&&e.setShadowBlur(i.textShadowBlur),a.forEach(((t,n)=>{let a=s.x;"center"===i.textAlign?a=s.x+(s.w-t.width)/2:"right"===i.textAlign&&(a=s.x+(s.w-t.width)),e.fillText(t.text,a,o+r*n)})),m(e)}if(t(i.strokeColor)&&void 0!==i.strokeWidth&&i.strokeWidth>0){const t=s.y+l;a.forEach(((o,n)=>{let a=s.x;"center"===i.textAlign?a=s.x+(s.w-o.width)/2:"right"===i.textAlign&&(a=s.x+(s.w-o.width)),void 0!==i.strokeColor&&e.setStrokeStyle(i.strokeColor),void 0!==i.strokeWidth&&i.strokeWidth>0&&e.setLineWidth(i.strokeWidth),e.strokeText(o.text,a,t+r*n)}))}}))}function z(t,e){m(t),g(t,e,(t=>{const{x:s,y:i,w:o,h:r,desc:n}=e,{bgColor:a="#000000",borderColor:h="#000000",borderWidth:l=0}=n,u=o/2,c=r/2,d=s+u,_=i+c;if(l&&l>0){const e=l/2+u,s=l/2+c;t.beginPath(),t.setStrokeStyle(h),t.setLineWidth(l),t.ellipse(d,_,e,s,0,0,2*Math.PI),t.closePath(),t.stroke()}t.beginPath(),t.setFillStyle(a),t.ellipse(d,_,u,c,0,0,2*Math.PI),t.closePath(),t.fill()}))}function b(e,s,i){var o;m(e);const r=e.getSize();if(e.clearRect(0,0,r.contextWidth,r.contextHeight),"string"==typeof s.bgColor&&t(s.bgColor)&&function(t,e){const s=t.getSize();t.setFillStyle(e),t.fillRect(0,0,s.contextWidth,s.contextHeight)}(e,s.bgColor),s.elements.length>0)for(let t=0;t<s.elements.length;t++){const r=s.elements[t];if(!0!==(null==(o=null==r?void 0:r.operation)?void 0:o.invisible))switch(r.type){case"rect":w(e,r);break;case"text":v(e,r);break;case"image":S(e,r,i);break;case"svg":p(e,r,i);break;case"html":y(e,r,i);break;case"circle":z(e,r)}}}class L{constructor(){this._listeners=new Map}on(t,e){if(this._listeners.has(t)){const s=this._listeners.get(t);null==s||s.push(e),this._listeners.set(t,s||[])}else this._listeners.set(t,[e])}off(t,e){if(this._listeners.has(t)){const s=this._listeners.get(t);if(Array.isArray(s))for(let t=0;t<(null==s?void 0:s.length);t++)if(s[t]===e){s.splice(t,1);break}this._listeners.set(t,s||[])}}trigger(t,e){const s=this._listeners.get(t);return!!Array.isArray(s)&&(s.forEach((t=>{t(e)})),!0)}has(t){if(this._listeners.has(t)){const e=this._listeners.get(t);if(Array.isArray(e)&&e.length>0)return!0}return!1}}class D{constructor(t){this._currentLoadData={},this._currentUUIDQueue=[],this._storageLoadData={},this._status="free",this._waitingLoadQueue=[],this._opts=t,this._event=new L,this._waitingLoadQueue=[]}load(t,e){const[s,i]=this._resetLoadData(t,e);"free"===this._status||"complete"===this._status?(this._currentUUIDQueue=s,this._currentLoadData=i,this._loadTask()):"loading"===this._status&&s.length>0&&this._waitingLoadQueue.push({uuidQueue:s,loadData:i})}on(t,e){this._event.on(t,e)}off(t,e){this._event.off(t,e)}isComplete(){return"complete"===this._status}getContent(t){var e;return"loaded"===(null==(e=this._storageLoadData[t])?void 0:e.status)?this._storageLoadData[t].content:null}_resetLoadData(t,e){const s={},i=[],o=this._storageLoadData;for(let r=t.elements.length-1;r>=0;r--){const n=t.elements[r];["image","svg","html"].includes(n.type)&&(o[n.uuid]?e.includes(n.uuid)&&(s[n.uuid]=this._createEmptyLoadItem(n),i.push(n.uuid)):(s[n.uuid]=this._createEmptyLoadItem(n),i.push(n.uuid)))}return[i,s]}_createEmptyLoadItem(t){let s="";const i=t.type;let o=t.w,r=t.h;if("image"===t.type){s=t.desc.src||""}else if("svg"===t.type){s=t.desc.svg||""}else if("html"===t.type){const e=t;s=(e.desc.html||"").replace(/<script[\s\S]*?<\/script>/gi,""),o=e.desc.width||t.w,r=e.desc.height||t.h}return{uuid:t.uuid,type:i,status:"null",content:null,source:s,elemW:o,elemH:r,element:e(t)}}_loadTask(){if("loading"===this._status)return;if(this._status="loading",0===this._currentUUIDQueue.length){if(0===this._waitingLoadQueue.length)return this._status="complete",void this._event.trigger("complete",void 0);{const t=this._waitingLoadQueue.shift();if(t){const{uuidQueue:e,loadData:s}=t;this._currentLoadData=s,this._currentUUIDQueue=e}}}const{maxParallelNum:t}=this._opts,e=this._currentUUIDQueue.splice(0,t);e.forEach(((t,e)=>{}));const s=[],i=()=>{if(s.length>=t)return!1;if(0===e.length)return!0;for(let o=s.length;o<t;o++){const t=e.shift();if(void 0===t)break;s.push(t),this._loadElementSource(this._currentLoadData[t]).then((o=>{var r,n;s.splice(s.indexOf(t),1);const a=i();this._storageLoadData[t]={uuid:t,type:this._currentLoadData[t].type,status:"loaded",content:o,source:this._currentLoadData[t].source,elemW:this._currentLoadData[t].elemW,elemH:this._currentLoadData[t].elemH,element:this._currentLoadData[t].element},0===s.length&&0===e.length&&!0===a&&(this._status="free",this._loadTask()),this._event.trigger("load",{uuid:null==(r=this._storageLoadData[t])?void 0:r.uuid,type:this._storageLoadData[t].type,status:this._storageLoadData[t].status,content:this._storageLoadData[t].content,source:this._storageLoadData[t].source,elemW:this._storageLoadData[t].elemW,elemH:this._storageLoadData[t].elemH,element:null==(n=this._storageLoadData[t])?void 0:n.element})})).catch((o=>{var r,n,a,h,l,u,c,d,_,f,g,m;console.warn(o),s.splice(s.indexOf(t),1);const x=i();this._currentLoadData[t]&&(this._storageLoadData[t]={uuid:t,type:null==(r=this._currentLoadData[t])?void 0:r.type,status:"fail",content:null,error:o,source:null==(n=this._currentLoadData[t])?void 0:n.source,elemW:null==(a=this._currentLoadData[t])?void 0:a.elemW,elemH:null==(h=this._currentLoadData[t])?void 0:h.elemH,element:null==(l=this._currentLoadData[t])?void 0:l.element}),0===s.length&&0===e.length&&!0===x&&(this._status="free",this._loadTask()),this._currentLoadData[t]&&this._event.trigger("error",{uuid:t,type:null==(u=this._storageLoadData[t])?void 0:u.type,status:null==(c=this._storageLoadData[t])?void 0:c.status,content:null==(d=this._storageLoadData[t])?void 0:d.content,source:null==(_=this._storageLoadData[t])?void 0:_.source,elemW:null==(f=this._storageLoadData[t])?void 0:f.elemW,elemH:null==(g=this._storageLoadData[t])?void 0:g.elemH,element:null==(m=this._storageLoadData[t])?void 0:m.element})}))}return!1};i()}async _loadElementSource(t){if(t&&"image"===t.type){return await n(t.source)}if(t&&"svg"===t.type){return await a(t.source)}if(t&&"html"===t.type){return await h(t.source,{width:t.elemW,height:t.elemH})}throw Error("Element's source is not support!")}}class T{constructor(){this._listeners=new Map}on(t,e){if(this._listeners.has(t)){const s=this._listeners.get(t);null==s||s.push(e),this._listeners.set(t,s||[])}else this._listeners.set(t,[e])}off(t,e){if(this._listeners.has(t)){const s=this._listeners.get(t);if(Array.isArray(s))for(let t=0;t<(null==s?void 0:s.length);t++)if(s[t]===e){s.splice(t,1);break}this._listeners.set(t,s||[])}}trigger(t,e){const s=this._listeners.get(t);return!!Array.isArray(s)&&(s.forEach((t=>{t(e)})),!0)}has(t){if(this._listeners.has(t)){const e=this._listeners.get(t);if(Array.isArray(e)&&e.length>0)return!0}return!1}}const{requestAnimationFrame:O}=window;return class extends T{constructor(t){super(),this._queue=[],this._ctx=null,this._status="null",this._opts=t,this._loader=new D({maxParallelNum:6}),this._loader.on("load",(t=>{this._drawFrame(),this.trigger("load",{element:t.element})})),this._loader.on("error",(t=>{this.trigger("error",{element:t.element,error:t.error})})),this._loader.on("complete",(()=>{this.trigger("loadComplete",{t:Date.now()})}))}render(t,s,i){const{changeResourceUUIDs:o=[]}=i||{};this._status="free";const r=e(s);if(Array.isArray(r.elements)&&r.elements.forEach((t=>{"string"==typeof t.uuid&&t.uuid||(t.uuid=function(){function t(){return(65536*(1+Math.random())|0).toString(16).substring(1)}return`${t()}${t()}-${t()}-${t()}-${t()}-${t()}${t()}${t()}`}())})),!this._ctx)if(this._opts&&"[object HTMLCanvasElement]"===Object.prototype.toString.call(t)){const{width:e,height:s,contextWidth:i,contextHeight:o,devicePixelRatio:r}=this._opts,n=t;n.width=e*r,n.height=s*r;const a=n.getContext("2d");this._ctx=new l(a,{width:e,height:s,contextWidth:i||e,contextHeight:o||s,devicePixelRatio:r})}else t&&(this._ctx=t);if(["freeze"].includes(this._status))return;const n=e({data:r});this._queue.push(n),this._drawFrame(),this._loader.load(r,o||[])}getContext(){return this._ctx}thaw(){this._status="free"}_freeze(){this._status="freeze"}_drawFrame(){"freeze"!==this._status&&O((()=>{if("freeze"===this._status)return;const t=this._ctx;let e=this._queue[0],s=!1;this._queue.length>1?e=this._queue.shift():s=!0,!0!==this._loader.isComplete()?(this._drawFrame(),e&&t&&b(t,e.data,this._loader)):e&&t?(b(t,e.data,this._loader),this._retainQueueOneItem(),s?this._status="free":this._drawFrame()):this._status="free",this.trigger("drawFrame",{t:Date.now()}),!0===this._loader.isComplete()&&1===this._queue.length&&"free"===this._status&&(t&&this._queue[0]&&this._queue[0].data&&b(t,this._queue[0].data,this._loader),this.trigger("drawFrameComplete",{t:Date.now()}),this._freeze())}))}_retainQueueOneItem(){if(this._queue.length<=1)return;const t=e(this._queue[this._queue.length-1]);this._queue=[t]}}}(); | ||
var iDrawRenderer=function(e){"use strict";function t(e){return"string"==typeof e&&(/^\#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(e)||/^[a-z]{1,}$/i.test(e))}function n(e){return function e(t){const n=function(e){return Object.prototype.toString.call(e).replace(/[\]|\[]{1,1}/gi,"").split(" ")[1]}(t);if(["Null","Number","String","Boolean","Undefined"].indexOf(n)>=0)return t;if("Array"===n){const n=[];return t.forEach((t=>{n.push(e(t))})),n}if("Object"===n){const n={};Object.keys(t).forEach((i=>{n[i]=e(t[i])}));return Object.getOwnPropertySymbols(t).forEach((i=>{n[i]=e(t[i])})),n}}(e)}function i(e){return(Object.prototype.toString.call(e)||"").replace(/(\[object|\])/gi,"").trim()}const o={type(e,t){const n=i(e);return!0===t?n.toLocaleLowerCase():n},array:e=>"Array"===i(e),json:e=>"Object"===i(e),function:e=>"Function"===i(e),asyncFunction:e=>"AsyncFunction"===i(e),string:e=>"String"===i(e),number:e=>"Number"===i(e),undefined:e=>"Undefined"===i(e),null:e=>"Null"===i(e),promise:e=>"Promise"===i(e)};var r=globalThis&&globalThis.__awaiter||function(e,t,n,i){return new(n||(n=Promise))((function(o,r){function a(e){try{s(i.next(e))}catch(e){r(e)}}function l(e){try{s(i.throw(e))}catch(e){r(e)}}function s(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,l)}s((i=i.apply(e,t||[])).next())}))};const{Image:a}=window;function l(e){return new Promise(((t,n)=>{const i=new a;i.crossOrigin="anonymous",i.onload=function(){t(i)},i.onabort=n,i.onerror=n,i.src=e}))}function s(e){return r(this,void 0,void 0,(function*(){const t=yield function(e){return new Promise(((t,n)=>{const i=new Blob([e],{type:"image/svg+xml;charset=utf-8"}),o=new FileReader;o.readAsDataURL(i),o.onload=function(e){var n;const i=null===(n=null==e?void 0:e.target)||void 0===n?void 0:n.result;t(i)},o.onerror=function(e){n(e)}}))}(e);return yield l(t)}))}function c(e,t){return r(this,void 0,void 0,(function*(){e=e.replace(/\&/gi,"&");const n=yield function(e,t){const{width:n,height:i}=t;return new Promise(((t,o)=>{const r=new Blob([`\n <svg \n xmlns="http://www.w3.org/2000/svg" \n width="${n||""}" \n height = "${i||""}">\n <foreignObject width="100%" height="100%">\n <div xmlns = "http://www.w3.org/1999/xhtml">\n ${e}\n </div>\n </foreignObject>\n </svg>\n `],{type:"image/svg+xml;charset=utf-8"}),a=new FileReader;a.readAsDataURL(r),a.onload=function(e){var n;const i=null===(n=null==e?void 0:e.target)||void 0===n?void 0:n.result;t(i)},a.onerror=function(e){o(e)}}))}(e,t);return yield l(n)}))}function d(e){return"number"==typeof e&&(e>0||e<=0)}function u(e){return"number"==typeof e&&e>=0}function h(e){return"string"==typeof e&&/^(http:\/\/|https:\/\/|\.\/|\/)/.test(`${e}`)}function f(e){return"string"==typeof e&&/^(data:image\/)/.test(`${e}`)}const g={x:function(e){return d(e)},y:function(e){return d(e)},w:u,h:function(e){return"number"==typeof e&&e>=0},angle:function(e){return"number"==typeof e&&e>=-360&&e<=360},number:d,numberStr:function(e){return/^(-?\d+(?:\.\d+)?)$/.test(`${e}`)},borderWidth:function(e){return u(e)},borderRadius:function(e){return d(e)&&e>=0},color:function(e){return t(e)},imageSrc:function(e){return f(e)||h(e)},imageURL:h,imageBase64:f,svg:function(e){return"string"==typeof e&&/^(<svg[\s]{1,}|<svg>)/i.test(`${e}`.trim())&&/<\/[\s]{0,}svg>$/i.test(`${e}`.trim())},html:function(e){let t=!1;if("string"==typeof e){let n=document.createElement("div");n.innerHTML=e,n.children.length>0&&(t=!0),n=null}return t},text:function(e){return"string"==typeof e},fontSize:function(e){return d(e)&&e>0},lineHeight:function(e){return d(e)&&e>0},textAlign:function(e){return["center","left","right"].includes(e)},fontFamily:function(e){return"string"==typeof e&&e.length>0},fontWeight:function(e){return["bold"].includes(e)},strokeWidth:function(e){return d(e)&&e>0}};class w{constructor(){this._listeners=new Map}on(e,t){if(this._listeners.has(e)){const n=this._listeners.get(e)||[];null==n||n.push(t),this._listeners.set(e,n)}else this._listeners.set(e,[t])}off(e,t){if(this._listeners.has(e)){const n=this._listeners.get(e);if(Array.isArray(n))for(let e=0;e<(null==n?void 0:n.length);e++)if(n[e]===t){n.splice(e,1);break}this._listeners.set(e,n||[])}}trigger(e,t){const n=this._listeners.get(e);return!!Array.isArray(n)&&(n.forEach((e=>{e(t)})),!0)}has(e){if(this._listeners.has(e)){const t=this._listeners.get(e);if(Array.isArray(t)&&t.length>0)return!0}return!1}}function m(e,t,n){const i={x:(o=t).x+o.w/2,y:o.y+o.h/2};var o;const r=(t.angle||0)/180*Math.PI;i&&(r>0||r<0)&&(e.translate(i.x,i.y),e.rotate(r),e.translate(-i.x,-i.y)),n(e),i&&(r>0||r<0)&&(e.translate(i.x,i.y),e.rotate(-r),e.translate(-i.x,-i.y))}function v(e){let t="";return e.forEach((e=>{t+=e.type+e.params.join(" ")})),t}function y(e,n,i){var r,a;void 0!==(null==(r=null==n?void 0:n.detail)?void 0:r.opacity)&&(null==(a=null==n?void 0:n.detail)?void 0:a.opacity)>0?e.globalAlpha=n.detail.opacity:e.globalAlpha=1;const{pattern:l,renderContent:s,originElem:c,calcElemSize:d,viewScaleInfo:u,viewSizeInfo:h}=i||{};!function(e,t,n){const{renderContent:i,originElem:o,calcElemSize:r,viewScaleInfo:a,viewSizeInfo:l}=n,s=a.scale*l.devicePixelRatio,{clipPath:c}=(null==o?void 0:o.detail)||{};if(c&&r&&c.commands){const{x:n,y:o,w:a,h:l}=r,{originW:d,originH:u,originX:h,originY:f}=c,g=a/d,w=l/u;let y=n-h*g,x=o-f*w;e.save(),e.translate(y,x),e.scale(s*g,s*w);const S=v(c.commands||[]),p=new Path2D(S);e.clip(p),e.translate(0-y,0-x),e.setTransform(1,0,0,1,0,0),m(e,{...t},(()=>{null==i||i()})),e.restore()}else null==i||i()}(e,n,{originElem:c,calcElemSize:d,viewScaleInfo:u,viewSizeInfo:h,renderContent:()=>{!function(e,n,i){if(!t(n.detail.borderColor))return;const{viewScaleInfo:o}=i;let r="#000000";!0===t(n.detail.borderColor)&&(r=n.detail.borderColor);const{borderWidth:a,borderRadius:l,borderDash:s}=n.detail;let c=0;"number"==typeof a&&(c=a||1);c*=o.scale;let d=l||0;e.strokeStyle=r,e.setLineDash(s||[]);let u=0,h=0,f=0,g=0;Array.isArray(a)&&(u=a[0]||0,h=a[1]||0,f=a[2]||0,g=a[3]||0);if(g||h||u||f){const{x:t,y:i,w:r,h:a}=n;g&&(e.beginPath(),e.lineWidth=g*o.scale,e.moveTo(t,i),e.lineTo(t,i+a),e.closePath(),e.stroke()),h&&(e.beginPath(),e.lineWidth=h*o.scale,e.moveTo(t+r,i),e.lineTo(t+r,i+a),e.closePath(),e.stroke()),u&&(e.beginPath(),e.lineWidth=u*o.scale,e.moveTo(t,i),e.lineTo(t+r,i),e.closePath(),e.stroke()),f&&(e.beginPath(),e.lineWidth=f*o.scale,e.moveTo(t,i+a),e.lineTo(t+r,i+a),e.closePath(),e.stroke())}else{let{x:t,y:i,w:o,h:r}=n;const{boxSizing:a}=n.detail;"border-box"===a?(t=n.x,i=n.y,o=n.w,r=n.h):(t=n.x-c,i=n.y-c,o=n.w+2*c,r=n.h+2*c),d=Math.min(d,o/2,r/2),d<o/2&&d<r/2&&(d+=c/2),e.beginPath(),e.lineWidth=c,e.moveTo(t+d,i),e.arcTo(t+o,i,t+o,i+r,d),e.arcTo(t+o,i+r,t,i+r,d),e.arcTo(t,i+r,t,i,d),e.arcTo(t,i,t+o,i,d),e.closePath(),e.stroke()}}(e,n,{viewScaleInfo:u,viewSizeInfo:h}),function(e,t,n){var i,r;const{pattern:a,viewScaleInfo:l}=n;let s=[];if(t.detail.background||a){const{x:n,y:c,w:d,h:u}=t;let h=(t.detail.borderRadius||0)*l.scale;if(h=Math.min(h,d/2,u/2),(d<2*h||u<2*h)&&(h=0),e.beginPath(),e.moveTo(n+h,c),e.arcTo(n+d,c,n+d,c+u,h),e.arcTo(n+d,c+u,n,c+u,h),e.arcTo(n,c+u,n,c,h),e.arcTo(n,c,n+d,c,h),e.closePath(),"string"==typeof a)e.fillStyle=a;else if(["CanvasPattern"].includes(o.type(a)))e.fillStyle=a;else if("string"==typeof t.detail.background)e.fillStyle=t.detail.background;else if("linearGradient"===(null==(i=t.detail.background)?void 0:i.type)){const{start:i,end:o,stops:r}=t.detail.background,a={x:i.x+n,y:i.y+c},l={x:o.x+n,y:o.y+c},s=e.createLinearGradient(a.x,a.y,l.x,l.y);r.forEach((e=>{s.addColorStop(e.offset,e.color)})),e.fillStyle=s}else if("radialGradient"===(null==(r=t.detail.background)?void 0:r.type)){const{inner:i,outer:o,stops:r}=t.detail.background;s=t.detail.background.transform||[];const a={x:i.x,y:i.y,radius:i.radius*l.scale},d={x:o.x,y:o.y,radius:o.radius*l.scale},u=e.createRadialGradient(a.x,a.y,a.radius,d.x,d.y,d.radius);if(r.forEach((e=>{u.addColorStop(e.offset,e.color)})),e.fillStyle=u,s&&s.length>0)for(let t=0;t<(null==s?void 0:s.length);t++){const i=s[t];"translate"===i.method?e.translate(i.args[0]+n,i.args[1]+c):"rotate"===i.method?e.rotate(...i.args):"scale"===i.method&&e.scale(...i.args)}}e.fill(),s&&s.length>0&&e.setTransform(1,0,0,1,0,0)}}(e,n,{pattern:l,viewScaleInfo:u,viewSizeInfo:h}),null==s||s()}}),e.globalAlpha=1}function x(e,t,n){const{detail:i}=t,{viewScaleInfo:o,renderContent:r}=n,{shadowColor:a,shadowOffsetX:l,shadowOffsetY:s,shadowBlur:c}=i;g.number(c)?(e.save(),e.shadowColor=a||"#000000",e.shadowOffsetX=(l||0)*o.scale,e.shadowOffsetY=(s||0)*o.scale,e.shadowBlur=(c||0)*o.scale,r(),e.restore()):r()}function S(e,n,i){var o;if(!0!==(null==(o=null==n?void 0:n.operations)?void 0:o.invisible))try{switch(n.type){case"rect":!function(e,t,n){const{calculator:i,viewScaleInfo:o,viewSizeInfo:r}=n;let{x:a,y:l,w:s,h:c,angle:d}=i.elementSize(t,o,r);const u={...t,x:a,y:l,w:s,h:c,angle:d};m(e,{x:a,y:l,w:s,h:c,angle:d},(()=>{x(e,u,{viewScaleInfo:o,viewSizeInfo:r,renderContent:()=>{y(e,u,{originElem:t,calcElemSize:{x:a,y:l,w:s,h:c,angle:d},viewScaleInfo:o,viewSizeInfo:r,renderContent:()=>{}})}})}))}(e,n,i);break;case"circle":!function(e,t,n){const{detail:i,angle:o}=t,{background:r="#000000",borderColor:a="#000000",borderWidth:l=0}=i,{calculator:s,viewScaleInfo:c,viewSizeInfo:d}=n,{x:u,y:h,w:f,h:g}=s.elementSize({x:t.x,y:t.y,w:t.w,h:t.h},c,d);m(e,{x:u,y:h,w:f,h:g,angle:o},(()=>{const t=f/2,n=g/2,i=u+t,o=h+n;if(l&&l>0){const r=l/2+t,s=l/2+n;e.beginPath(),e.strokeStyle=a,e.lineWidth=l,e.circle(i,o,r,s,0,0,2*Math.PI),e.closePath(),e.stroke()}e.beginPath(),e.fillStyle=r,e.circle(i,o,t,n,0,0,2*Math.PI),e.closePath(),e.fill()}))}(e,n,i);break;case"text":!function(e,n,i){const{calculator:o,viewScaleInfo:r,viewSizeInfo:a}=i,{x:l,y:s,w:c,h:d,angle:u}=o.elementSize(n,r,a),h={...n,x:l,y:s,w:c,h:d,angle:u};m(e,{x:l,y:s,w:c,h:d,angle:u},(()=>{y(e,h,{originElem:n,calcElemSize:{x:l,y:s,w:c,h:d,angle:u},viewScaleInfo:r,viewSizeInfo:a,renderContent:()=>{const i={fontSize:12,fontFamily:"sans-serif",textAlign:"center",...n.detail},o=i.fontSize*r.scale,a=i.lineHeight?i.lineHeight*r.scale:o;e.fillStyle=n.detail.color,e.textBaseline="top",e.$setFont({fontWeight:i.fontWeight,fontSize:o,fontFamily:i.fontFamily});const u=i.text.replace(/\r\n/gi,"\n"),h=a,f=u.split("\n"),w=[];let m=0;f.forEach(((t,n)=>{let i="";if(t.length>0){for(let o=0;o<t.length&&(e.measureText(i+(t[o]||"")).width<e.$doPixelRatio(c)?i+=t[o]||"":(w.push({text:i,width:e.$undoPixelRatio(e.measureText(i).width)}),i=t[o]||"",m++),!((m+1)*h>d));o++)if(t.length-1===o&&(m+1)*h<d){w.push({text:i,width:e.$undoPixelRatio(e.measureText(i).width)}),n<f.length-1&&m++;break}}else w.push({text:"",width:0})}));let v=0;w.length*h<d&&("top"===n.detail.verticalAlign?v=0:"bottom"===n.detail.verticalAlign?v+=d-w.length*h:v+=(d-w.length*h)/2);{const n=s+v;void 0!==i.textShadowColor&&t(i.textShadowColor)&&(e.shadowColor=i.textShadowColor),void 0!==i.textShadowOffsetX&&g.number(i.textShadowOffsetX)&&(e.shadowOffsetX=i.textShadowOffsetX),void 0!==i.textShadowOffsetY&&g.number(i.textShadowOffsetY)&&(e.shadowOffsetY=i.textShadowOffsetY),void 0!==i.textShadowBlur&&g.number(i.textShadowBlur)&&(e.shadowBlur=i.textShadowBlur),w.forEach(((t,o)=>{let r=l;"center"===i.textAlign?r=l+(c-t.width)/2:"right"===i.textAlign&&(r=l+(c-t.width)),e.fillText(t.text,r,n+h*o)}))}}})}))}(e,n,i);break;case"image":!function(e,t,n){const i=n.loader.getContent(t.uuid),{calculator:o,viewScaleInfo:r,viewSizeInfo:a}=n,{x:l,y:s,w:c,h:d,angle:u}=o.elementSize(t,r,a);m(e,{x:l,y:s,w:c,h:d,angle:u},(()=>{i||n.loader.load(t,n.elementAssets||{}),"image"===t.type&&i&&e.drawImage(i,l,s,c,d)}))}(e,n,i);break;case"svg":!function(e,t,n){const i=n.loader.getContent(t.uuid),{calculator:o,viewScaleInfo:r,viewSizeInfo:a}=n,{x:l,y:s,w:c,h:d,angle:u}=o.elementSize(t,r,a);m(e,{x:l,y:s,w:c,h:d,angle:u},(()=>{i||n.loader.load(t,n.elementAssets||{}),"svg"===t.type&&i&&e.drawImage(i,l,s,c,d)}))}(e,n,i);break;case"html":!function(e,t,n){const i=n.loader.getContent(t.uuid),{calculator:o,viewScaleInfo:r,viewSizeInfo:a}=n,{x:l,y:s,w:c,h:d,angle:u}=o.elementSize(t,r,a);m(e,{x:l,y:s,w:c,h:d,angle:u},(()=>{i||n.loader.load(t),"html"===t.type&&i&&e.drawImage(i,l,s,c,d)}))}(e,n,i);break;case"path":!function(e,t,n){const{detail:i}=t,{originX:o,originY:r,originW:a,originH:l}=i,{calculator:s,viewScaleInfo:c,viewSizeInfo:d}=n,{x:u,y:h,w:f,h:g,angle:w}=s.elementSize(t,c,d),S=f/a,p=g/l,b=u-o*S,I=h-r*p,T=c.scale*d.devicePixelRatio,_={...t,x:u,y:h,w:f,h:g,angle:w};m(e,{x:u,y:h,w:f,h:g,angle:w},(()=>{y(e,_,{originElem:t,calcElemSize:{x:u,y:h,w:f,h:g,angle:w},viewScaleInfo:c,viewSizeInfo:d,renderContent:()=>{x(e,_,{viewScaleInfo:c,viewSizeInfo:d,renderContent:()=>{e.save(),e.translate(b,I),e.scale(T*S/c.scale,T*p/c.scale);const t=v(i.commands||[]),n=new Path2D(t);i.fill&&(e.fillStyle=i.fill,e.fill(n)),i.stroke&&0!==i.strokeWidth&&(e.strokeStyle=i.stroke,e.lineWidth=(i.strokeWidth||1)/d.devicePixelRatio,e.lineCap=i.strokeLineCap||"square",e.stroke(n)),e.translate(-b,-I),e.restore()}})}})}))}(e,n,i);break;case"group":!function(e,t,n){const{calculator:i,viewScaleInfo:o,viewSizeInfo:r}=n,{x:a,y:l,w:s,h:c,angle:d}=i.elementSize({x:t.x,y:t.y,w:t.w,h:t.h,angle:t.angle},o,r),u={...t,x:a,y:l,w:s,h:c,angle:d};m(e,{x:a,y:l,w:s,h:c,angle:d},(()=>{y(e,u,{originElem:t,calcElemSize:{x:a,y:l,w:s,h:c,angle:d},viewScaleInfo:o,viewSizeInfo:r,renderContent:()=>{if(Array.isArray(t.detail.children)){const{parentElementSize:i}=n,o={x:i.x+t.x,y:i.y+t.y,w:t.w||i.w,h:t.h||i.h,angle:t.angle},{calculator:r}=n;"hidden"===t.detail.overflow&&(e.save(),e.beginPath(),e.moveTo(a,l),e.lineTo(a+s,l),e.lineTo(a+s,l+c),e.lineTo(a,l+c),e.closePath(),e.clip());for(let i=0;i<t.detail.children.length;i++){let a=t.detail.children[i];if(a={...a,x:o.x+a.x,y:o.y+a.y},r.isElementInView(a,n.viewScaleInfo,n.viewSizeInfo))try{S(e,a,{...n})}catch(e){console.error(e)}}e.restore()}}})}))}(e,n,i)}}catch(e){console.error(e)}}const p=["image","svg","html"];class b extends w{constructor(){super(),this._loadFuncMap={},this._currentLoadItemMap={},this._storageLoadItemMap={},this._registerLoadFunc("image",(async(e,t)=>{var n;const i=(null==(n=t[e.detail.src])?void 0:n.value)||e.detail.src,o=await l(i);return{uuid:e.uuid,lastModified:Date.now(),content:o}})),this._registerLoadFunc("html",(async(e,t)=>{var n;const i=(null==(n=t[e.detail.html])?void 0:n.value)||e.detail.html,o=await c(i,{width:e.detail.width||e.w,height:e.detail.height||e.h});return{uuid:e.uuid,lastModified:Date.now(),content:o}})),this._registerLoadFunc("svg",(async(e,t)=>{var n;const i=(null==(n=t[e.detail.svg])?void 0:n.value)||e.detail.svg,o=await s(i);return{uuid:e.uuid,lastModified:Date.now(),content:o}}))}_registerLoadFunc(e,t){this._loadFuncMap[e]=t}_getLoadElementSource(e){var t,n,i;let o=null;return"image"===e.type?o=(null==(t=null==e?void 0:e.detail)?void 0:t.src)||null:"svg"===e.type?o=(null==(n=null==e?void 0:e.detail)?void 0:n.svg)||null:"html"===e.type&&(o=(null==(i=null==e?void 0:e.detail)?void 0:i.html)||null),o}_createLoadItem(e){return{element:e,status:"null",content:null,error:null,startTime:-1,endTime:-1,source:this._getLoadElementSource(e)}}_emitLoad(e){const t=e.element.uuid,n=this._storageLoadItemMap[t];n?n.startTime<e.startTime&&(this._storageLoadItemMap[t]=e,this.trigger("load",{...e,countTime:e.endTime-e.startTime})):(this._storageLoadItemMap[t]=e,this.trigger("load",{...e,countTime:e.endTime-e.startTime}))}_emitError(e){const t=e.element.uuid,n=this._storageLoadItemMap[t];n?n.startTime<e.startTime&&(this._storageLoadItemMap[t]=e,this.trigger("error",{...e,countTime:e.endTime-e.startTime})):(this._storageLoadItemMap[t]=e,this.trigger("error",{...e,countTime:e.endTime-e.startTime}))}_loadResource(e,t){const n=this._createLoadItem(e);this._currentLoadItemMap[e.uuid]=n;const i=this._loadFuncMap[e.type];"function"==typeof i&&(n.startTime=Date.now(),i(e,t).then((e=>{n.content=e.content,n.endTime=Date.now(),n.status="load",this._emitLoad(n)})).catch((t=>{console.warn(`Load element source "${n.source}" fail`,t,e),n.endTime=Date.now(),n.status="error",n.error=t,this._emitError(n)})))}_isExistingErrorStorage(e){var t;const n=null==(t=this._currentLoadItemMap)?void 0:t[null==e?void 0:e.uuid];return!(!n||"error"!==n.status||!n.source||n.source!==this._getLoadElementSource(e))}load(e,t){if(!this._isExistingErrorStorage(e)&&p.includes(e.type)){const i=n(e);this._loadResource(i,t)}}getContent(e){var t,n;return(null==(n=null==(t=this._storageLoadItemMap)?void 0:t[e])?void 0:n.content)||null}}return e.Renderer=class extends w{constructor(e){super(),this._loader=new b,this._opts=e,this._init()}_init(){const{_loader:e}=this;e.on("load",(e=>{this.trigger("load",e)})),e.on("error",(()=>{}))}updateOptions(e){this._opts=e}drawData(e,t){const{_loader:n}=this,{calculator:i}=this._opts,{viewContext:o}=this._opts.viewContent;o.clearRect(0,0,o.canvas.width,o.canvas.height);!function(e,t,n){const{elements:i=[]}=t;for(let t=0;t<i.length;t++){const o=i[t];if(n.calculator.isElementInView(o,n.viewScaleInfo,n.viewSizeInfo))try{S(e,o,n)}catch(e){console.error(e)}}}(o,e,{loader:n,calculator:i,parentElementSize:{x:0,y:0,w:t.viewSizeInfo.width,h:t.viewSizeInfo.height},elementAssets:e.assets,...t})}scale(e){const{sharer:t}=this._opts,{data:n,offsetTop:i,offsetBottom:o,offsetLeft:r,offsetRight:a,width:l,height:s,contextHeight:c,contextWidth:d,devicePixelRatio:u}=t.getActiveStoreSnapshot();n&&this.drawData(n,{viewScaleInfo:{scale:e,offsetTop:i,offsetBottom:o,offsetLeft:r,offsetRight:a},viewSizeInfo:{width:l,height:s,contextHeight:c,contextWidth:d,devicePixelRatio:u}})}},Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),e}({}); |
{ | ||
"name": "@idraw/renderer", | ||
"version": "0.3.1", | ||
"version": "0.4.0-alpha.2", | ||
"description": "", | ||
@@ -24,6 +24,6 @@ "main": "dist/esm/index.js", | ||
"devDependencies": { | ||
"@idraw/types": "^0.3.1" | ||
"@idraw/types": "^0.4.0-alpha.0" | ||
}, | ||
"dependencies": { | ||
"@idraw/util": "^0.3.1" | ||
"@idraw/util": "^0.4.0-alpha.2" | ||
}, | ||
@@ -33,3 +33,3 @@ "publishConfig": { | ||
}, | ||
"gitHead": "7c831450d14f34e2eb0d937bccdd4896b2c4b4b8" | ||
} | ||
"gitHead": "5cc462b9206ea0e4e70b5183771dfbf694402483" | ||
} |
@@ -35,3 +35,3 @@ # @idraw/renderer | ||
type: "rect", | ||
desc: { | ||
detail: { | ||
bgColor: "#f0f0f0", | ||
@@ -38,0 +38,0 @@ borderRadius: 20, |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
96581
30
2072
1
+ Added@idraw/util@0.4.0-beta.39(transitive)
- Removed@idraw/util@0.3.1(transitive)
Updated@idraw/util@^0.4.0-alpha.2