UNPKG

@visactor/vrender-components

Version:

components library for dp visualization

1,251 lines (1,226 loc) 1.63 MB
import { isFunction, EventEmitter, Logger, isBoolean, isObject, tau, halfPi as halfPi$1, AABBBounds, degreeToRadian, Point, PointService, abs, max, min, atan2, epsilon, Matrix, pi2, isArray, cos, sin, pi, isString, pointAt, isNumber, sqrt, isPointInLine, Color, OBBBounds, isEqual, isNil, normalTransform, isValidUrl, isBase64, isPlainObject as isPlainObject$2, merge, getContextFont, rotatePoint, transformBoundsWithMatrix, clampAngleByRadian, asin, isNumberClose, TextMeasure, Bounds, getRectIntersect, isRectIntersect, arrayEqual, acos, isValid, clamp, clampRange, normalizePadding, debounce, throttle, hexToRgb, crossProduct, isEmpty, array, rectInsideAnotherRect, radianToDegree, getAngleByPoint, polarToCartesian, normalizeAngle, isValidNumber, flattenArray, isRotateAABBIntersect, isLess, isGreater, aabbSeparation, obbSeparation, cloneDeep, get, last, mixin, interpolateString, minInArray, maxInArray, binaryFuzzySearchInNumberRange, pointInRect, calculateAnchorOfBounds, computeQuadrant, polygonContainPoint } from '@visactor/vutils'; import { isContinuous, isDiscrete, LinearScale } from '@visactor/vscale'; class FederatedEvent { get layerX() { return this.layer.x; } get layerY() { return this.layer.y; } get pageX() { return this.page.x; } get pageY() { return this.page.y; } get x() { return this.canvas.x; } get y() { return this.canvas.y; } get canvasX() { return this.canvas.x; } get canvasY() { return this.canvas.y; } get viewX() { return this.viewport.x; } get viewY() { return this.viewport.y; } constructor(manager) { this.bubbles = !0, this.cancelBubble = !0, this.cancelable = !1, this.composed = !1, this.defaultPrevented = !1, this.eventPhase = FederatedEvent.prototype.NONE, this.propagationStopped = !1, this.propagationImmediatelyStopped = !1, this.layer = { x: 0, y: 0 }, this.page = { x: 0, y: 0 }, this.canvas = { x: 0, y: 0 }, this.viewport = { x: 0, y: 0 }, this.NONE = 0, this.CAPTURING_PHASE = 1, this.AT_TARGET = 2, this.BUBBLING_PHASE = 3, this.manager = manager; } composedPath() { return !this.manager || this.path && this.path[this.path.length - 1] === this.target || (this.path = this.target ? this.manager.propagationPath(this.target) : []), this.composedDetailPath(), this.path; } composedDetailPath() { return this.pickParams && this.pickParams.graphic ? (this.detailPath = this.path.slice(), this._composedDetailPath(this.pickParams)) : this.detailPath = this.path.slice(), this.detailPath; } _composedDetailPath(params) { if (params && params.graphic) { const g = params.graphic; if (g.stage) { const path = g.stage.eventSystem.manager.propagationPath(g); this.detailPath.push(path), this._composedDetailPath(params.params); } } } preventDefault() { try { this.nativeEvent instanceof Event && this.nativeEvent.cancelable && this.nativeEvent.preventDefault(); } catch (err) { this.nativeEvent.preventDefault && isFunction(this.nativeEvent.preventDefault) && this.nativeEvent.preventDefault(); } this.defaultPrevented = !0; } stopImmediatePropagation() { this.propagationImmediatelyStopped = !0; } stopPropagation() { try { this.nativeEvent instanceof Event && this.nativeEvent.cancelable && this.nativeEvent.stopPropagation(); } catch (err) { this.nativeEvent.stopPropagation && isFunction(this.nativeEvent.stopPropagation) && this.nativeEvent.stopPropagation(); } this.propagationStopped = !0; } initEvent() {} initUIEvent() {} clone() { throw new Error("Method not implemented."); } } class CustomEvent extends FederatedEvent { constructor(eventName, object) { super(), this.type = eventName, this.detail = object; } } var UpdateTag; !function (UpdateTag) { UpdateTag[UpdateTag.NONE = 0] = "NONE", UpdateTag[UpdateTag.UPDATE_BOUNDS = 1] = "UPDATE_BOUNDS", UpdateTag[UpdateTag.UPDATE_SHAPE = 2] = "UPDATE_SHAPE", UpdateTag[UpdateTag.CLEAR_SHAPE = 253] = "CLEAR_SHAPE", UpdateTag[UpdateTag.UPDATE_SHAPE_AND_BOUNDS = 3] = "UPDATE_SHAPE_AND_BOUNDS", UpdateTag[UpdateTag.INIT = 179] = "INIT", UpdateTag[UpdateTag.CLEAR_BOUNDS = 254] = "CLEAR_BOUNDS", UpdateTag[UpdateTag.UPDATE_GLOBAL_MATRIX = 32] = "UPDATE_GLOBAL_MATRIX", UpdateTag[UpdateTag.CLEAR_GLOBAL_MATRIX = 223] = "CLEAR_GLOBAL_MATRIX", UpdateTag[UpdateTag.UPDATE_LOCAL_MATRIX = 16] = "UPDATE_LOCAL_MATRIX", UpdateTag[UpdateTag.CLEAR_LOCAL_MATRIX = 239] = "CLEAR_LOCAL_MATRIX", UpdateTag[UpdateTag.UPDATE_GLOBAL_LOCAL_MATRIX = 48] = "UPDATE_GLOBAL_LOCAL_MATRIX", UpdateTag[UpdateTag.UPDATE_PAINT = 64] = "UPDATE_PAINT", UpdateTag[UpdateTag.CLEAR_PAINT = 191] = "CLEAR_PAINT", UpdateTag[UpdateTag.UPDATE_LAYOUT = 128] = "UPDATE_LAYOUT", UpdateTag[UpdateTag.CLEAR_LAYOUT = 127] = "CLEAR_LAYOUT"; }(UpdateTag || (UpdateTag = {})); var IContainPointMode; !function (IContainPointMode) { IContainPointMode[IContainPointMode.GLOBAL = 1] = "GLOBAL", IContainPointMode[IContainPointMode.LOCAL = 16] = "LOCAL", IContainPointMode[IContainPointMode.GLOBAL_ACCURATE = 3] = "GLOBAL_ACCURATE", IContainPointMode[IContainPointMode.LOCAL_ACCURATE = 48] = "LOCAL_ACCURATE"; }(IContainPointMode || (IContainPointMode = {})); var AttributeUpdateType; !function (AttributeUpdateType) { AttributeUpdateType[AttributeUpdateType.INIT = 0] = "INIT", AttributeUpdateType[AttributeUpdateType.DEFAULT = 1] = "DEFAULT", AttributeUpdateType[AttributeUpdateType.STATE = 2] = "STATE", AttributeUpdateType[AttributeUpdateType.ANIMATE_BIND = 10] = "ANIMATE_BIND", AttributeUpdateType[AttributeUpdateType.ANIMATE_PLAY = 11] = "ANIMATE_PLAY", AttributeUpdateType[AttributeUpdateType.ANIMATE_START = 12] = "ANIMATE_START", AttributeUpdateType[AttributeUpdateType.ANIMATE_UPDATE = 13] = "ANIMATE_UPDATE", AttributeUpdateType[AttributeUpdateType.ANIMATE_END = 14] = "ANIMATE_END", AttributeUpdateType[AttributeUpdateType.TRANSLATE = 20] = "TRANSLATE", AttributeUpdateType[AttributeUpdateType.TRANSLATE_TO = 21] = "TRANSLATE_TO", AttributeUpdateType[AttributeUpdateType.SCALE = 22] = "SCALE", AttributeUpdateType[AttributeUpdateType.SCALE_TO = 23] = "SCALE_TO", AttributeUpdateType[AttributeUpdateType.ROTATE = 24] = "ROTATE", AttributeUpdateType[AttributeUpdateType.ROTATE_TO = 25] = "ROTATE_TO"; }(AttributeUpdateType || (AttributeUpdateType = {})); var Direction; !function (Direction) { Direction[Direction.ROW = 1] = "ROW", Direction[Direction.COLUMN = 2] = "COLUMN"; }(Direction || (Direction = {})); var CurveTypeEnum; !function (CurveTypeEnum) { CurveTypeEnum[CurveTypeEnum.CubicBezierCurve = 0] = "CubicBezierCurve", CurveTypeEnum[CurveTypeEnum.QuadraticBezierCurve = 1] = "QuadraticBezierCurve", CurveTypeEnum[CurveTypeEnum.ArcCurve = 2] = "ArcCurve", CurveTypeEnum[CurveTypeEnum.LineCurve = 3] = "LineCurve", CurveTypeEnum[CurveTypeEnum.EllipseCurve = 4] = "EllipseCurve", CurveTypeEnum[CurveTypeEnum.MoveCurve = 5] = "MoveCurve"; }(CurveTypeEnum || (CurveTypeEnum = {})); var BaseRenderContributionTime; !function (BaseRenderContributionTime) { BaseRenderContributionTime[BaseRenderContributionTime.beforeFillStroke = 0] = "beforeFillStroke", BaseRenderContributionTime[BaseRenderContributionTime.afterFillStroke = 1] = "afterFillStroke"; }(BaseRenderContributionTime || (BaseRenderContributionTime = {})); var AnimateMode; !function (AnimateMode) { AnimateMode[AnimateMode.NORMAL = 0] = "NORMAL", AnimateMode[AnimateMode.SET_ATTR_IMMEDIATELY = 1] = "SET_ATTR_IMMEDIATELY"; }(AnimateMode || (AnimateMode = {})); var AnimateStepType; !function (AnimateStepType) { AnimateStepType.wait = "wait", AnimateStepType.from = "from", AnimateStepType.to = "to", AnimateStepType.customAnimate = "customAnimate"; }(AnimateStepType || (AnimateStepType = {})); var AnimateStatus; !function (AnimateStatus) { AnimateStatus[AnimateStatus.INITIAL = 0] = "INITIAL", AnimateStatus[AnimateStatus.RUNNING = 1] = "RUNNING", AnimateStatus[AnimateStatus.PAUSED = 2] = "PAUSED", AnimateStatus[AnimateStatus.END = 3] = "END"; }(AnimateStatus || (AnimateStatus = {})); var STATUS$1; !function (STATUS) { STATUS[STATUS.INITIAL = 0] = "INITIAL", STATUS[STATUS.RUNNING = 1] = "RUNNING", STATUS[STATUS.PAUSE = 2] = "PAUSE"; }(STATUS$1 || (STATUS$1 = {})); class Application {} const APPLICATION_STATE_SYMBOL = Symbol.for("@visactor/vrender-core/application-state"); function createApplicationState() { return { application: new Application() }; } function getApplicationState() { const scope = globalThis; return scope[APPLICATION_STATE_SYMBOL] || (scope[APPLICATION_STATE_SYMBOL] = createApplicationState()), scope[APPLICATION_STATE_SYMBOL]; } const application = getApplicationState().application; class Generator { static GenAutoIncrementId() { return Generator.auto_increment_id++; } } Generator.auto_increment_id = 0; var __awaiter$4 = undefined && undefined.__awaiter || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } } function step(result) { var value; result.done ? resolve(result.value) : (value = result.value, value instanceof P ? value : new P(function (resolve) { resolve(value); })).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; class Node extends EventEmitter { get previousSibling() { return this._prev; } get nextSibling() { return this._next; } get children() { return this.getChildren(); } get firstChild() { return this._firstChild; } get lastChild() { return this._lastChild; } get count() { return this._count; } get childrenCount() { return this._idMap ? this._idMap.size : 0; } constructor() { super(), this._uid = Generator.GenAutoIncrementId(), this._firstChild = null, this._lastChild = null, this.parent = null, this._count = 1; } onParentSharedStateTreeChanged(_stage, _layer) {} forEachChildren(cb, reverse = !1) { if (reverse) { let child = this._lastChild, i = 0; for (; child;) { if (cb(child, i++)) return; child = child._prev; } } else { let child = this._firstChild, i = 0; for (; child;) { if (cb(child, i++)) return; child = child._next; } } } forEachChildrenAsync(cb, reverse = !1) { return __awaiter$4(this, void 0, void 0, function* () { if (reverse) { let child = this._lastChild, i = 0; for (; child;) { let breakTag = cb(child, i++); if (breakTag.then && (breakTag = yield breakTag), breakTag) return; child = child._prev; } } else { let child = this._firstChild, i = 0; for (; child;) { let breakTag = cb(child, i++); if (breakTag.then && (breakTag = yield breakTag), breakTag) return; child = child._next; } } }); } forEach(cb) { return this.forEachChildren(cb); } appendChild(node, highPerformance = !0) { if (this._uid === node._uid) return null; if (!highPerformance && node.isAncestorsOf(this)) throw new Error("【Node::appendChild】不能将父辈元素append为子元素"); return node.parent && node.parent.removeChild(node), node.parent = this, this._lastChild ? (this._lastChild._next = node, node._prev = this._lastChild, this._lastChild = node) : (this._firstChild = this._lastChild = node, node._prev = node._next = null), this._idMap || (this._idMap = new Map()), this._idMap.set(node._uid, node), this.setCount(node.count), this._structEdit = !0, node; } appendChildArrHighPerformance(nodes, replace = !1) { return console.error("暂不支持该函数"), nodes; } insertBefore(newNode, referenceNode) { if (!referenceNode) return this.appendChild(newNode); if (this === newNode || newNode === referenceNode) return null; if (newNode.isAncestorsOf(this)) throw new Error("【Node::insertBefore】不能将父辈元素insert为子元素"); return referenceNode.parent !== this ? null : (newNode.parent && newNode.parent.removeChild(newNode), newNode.parent = this, newNode._prev = referenceNode._prev, referenceNode._prev ? referenceNode._prev._next = newNode : this._firstChild = newNode, referenceNode._prev = newNode, newNode._next = referenceNode, this._idMap || (this._idMap = new Map()), this._idMap.set(newNode._uid, newNode), this._structEdit = !0, this.setCount(newNode.count), newNode); } insertAfter(newNode, referenceNode) { if (!referenceNode) return this.appendChild(newNode); if (this === newNode || newNode === referenceNode) return null; if (newNode.isAncestorsOf(this)) throw new Error("【Node::insertAfter】不能将父辈元素insert为子元素"); return referenceNode.parent !== this ? null : (newNode.parent && newNode.parent.removeChild(newNode), newNode.parent = this, referenceNode._next ? (referenceNode._next._prev = newNode, newNode._next = referenceNode._next) : this._lastChild = newNode, referenceNode._next = newNode, newNode._prev = referenceNode, this._idMap || (this._idMap = new Map()), this._idMap.set(newNode._uid, newNode), this._structEdit = !0, this.setCount(newNode.count), newNode); } insertInto(newNode, idx) { if (!this._ignoreWarn && this._nodeList && Logger.getInstance().warn("insertIntoKeepIdx和insertInto混用可能会存在错误"), idx >= this.childrenCount) return this.appendChild(newNode); if (this === newNode) return null; if (newNode.isAncestorsOf(this)) throw new Error("【Node::insertBefore】不能将父辈元素insert为子元素"); if (newNode.parent && newNode.parent.removeChild(newNode), newNode.parent = this, 0 === idx) newNode._next = this._firstChild, this._firstChild && (this._firstChild._prev = newNode), newNode._prev = null, this._firstChild = newNode;else { let child = this._firstChild; for (let i = 0; i < idx; i++) { if (!child) return null; i > 0 && (child = child._next); } if (!child) return null; newNode._next = child._next, newNode._prev = child, child._next = newNode, newNode._next && (newNode._next._prev = newNode); } return this._idMap || (this._idMap = new Map()), this._idMap.set(newNode._uid, newNode), this._structEdit = !0, this.setCount(newNode.count), newNode; } insertIntoKeepIdx(newNode, idx) { if (this._nodeList || (this._nodeList = this.children), this._nodeList[idx]) { const node = this._nodeList[idx]; return this._nodeList.splice(idx, 0, newNode), this.insertBefore(newNode, node); } let node; this._nodeList[idx] = newNode; for (let i = idx - 1; i >= 0 && (node = this._nodeList[i], !node); i--); if (node) return node._next ? this.insertBefore(newNode, node._next) : this.appendChild(newNode); this._ignoreWarn = !0; const data = this.insertInto(newNode, 0); return this._ignoreWarn = !1, data; } removeChild(child) { if (!this._idMap) return null; if (!this._idMap.has(child._uid)) return null; if (this._idMap.delete(child._uid), this._nodeList) { const idx = this._nodeList.findIndex(n => n === child); idx >= 0 && this._nodeList.splice(idx, 1); } return child._prev ? child._prev._next = child._next : this._firstChild = child._next, child._next ? child._next._prev = child._prev : this._lastChild = child._prev, child.parent = null, child._prev = null, child._next = null, this._structEdit = !0, this.setCount(-child.count), child; } delete() { this.parent && this.parent.removeChild(this); } removeAllChild(deep) { if (!this._idMap) return; this._nodeList && (this._nodeList.length = 0); let child = this._firstChild; for (; child;) { const next = child._next; child.parent = null, child._prev = null, child._next = null, child = child._next, child = next; } this._firstChild = null, this._lastChild = null, this._idMap.clear(), this._structEdit = !0, this.setCount(1 - this._count); } replaceChild(newChild, oldChild) { throw new Error("暂不支持"); } find(callback, deep = !1) { let target = null; return this.forEachChildren((node, index) => !(node === this || !callback(node, index)) && (target = node, !0)), deep && this.forEachChildren(child => { if (child.isContainer) { const node = child.find(callback, !0); if (node) return target = node, !0; } return !1; }), target; } findAll(callback, deep = !1) { let nodes = []; return this.forEachChildren((node, index) => { node !== this && callback(node, index) && nodes.push(node); }), deep && this.forEachChildren(child => { if (child.isContainer) { const targets = child.findAll(callback, !0); targets.length && (nodes = nodes.concat(targets)); } }), nodes; } getElementById(id) { return this.find(node => node.id === id, !0); } findChildById(id) { return this.getElementById(id); } findChildByUid(uid) { return this._idMap && this._idMap.get(uid) || null; } getElementsByName(name) { return this.findAll(node => node.name === name, !0); } findChildrenByName(name) { return this.getElementsByName(name); } getElementsByType(type) { return this.findAll(node => node.type === type, !0); } getChildByName(name, deep = !1) { return this.find(node => node.name === name, deep); } getChildAt(idx) { let c = this._firstChild; if (!c) return null; for (let i = 0; i < idx; i++) { if (!c._next) return null; c = c._next; } return c; } at(idx) { return this.getChildAt(idx); } containNode(node) { if (!this._idMap) return !1; if (this._idMap.has(node._uid)) return !0; let child = this._firstChild; for (; child;) { if (child.containNode(node)) return !0; child = child._next; } return !1; } getRootNode() { let parent = this.parent; for (; null == parent ? void 0 : parent.parent;) parent = parent.parent; return parent || this; } hasChildNodes() { return null !== this._firstChild; } addChild(node) { return this.appendChild(node); } add(node) { return this.appendChild(node); } getChildren() { const nodes = []; let child = this._firstChild; for (; child;) nodes.push(child), child = child._next; return nodes; } isChildOf(node) { return !!this.parent && this.parent._uid === node._uid; } isParentOf(node) { return node.isChildOf(this); } isDescendantsOf(node) { let parent = this.parent; if (!parent) return !1; do { if (parent._uid === node._uid) return !0; parent = parent.parent; } while (null !== parent); return !1; } isAncestorsOf(node) { return node.isDescendantsOf(this); } getAncestor(idx) { throw new Error("暂不支持"); } setAllDescendantsProps(propsName, propsValue) { let child = this._firstChild; for (; child;) child[propsName] = propsValue, child.setAllDescendantsProps(propsName, propsValue), child = child._next; } setCount(deltaCount) { this._count += deltaCount; let parent = this.parent; if (parent) do { parent._count += deltaCount, parent = parent.parent; } while (null !== parent); } clone() { throw new Error("暂不支持"); } cloneTo(node) { throw new Error("暂不支持"); } getParent() { return this.parent; } del(child) { return this.removeChild(child); } addEventListener(type, listener, options) { const capture = isBoolean(options, !0) && options || isObject(options) && options.capture, once = isObject(options) && options.once, context = isFunction(listener) ? void 0 : listener; return type = capture ? `${type}capture` : type, listener = isFunction(listener) ? listener : listener.handleEvent, once ? super.once(type, listener, context) : super.on(type, listener, context), this; } on(type, listener, options) { return this.addEventListener(type, listener, options); } removeEventListener(type, listener, options) { const capture = isBoolean(options, !0) && options || isObject(options) && options.capture, context = isFunction(listener) ? void 0 : listener; type = capture ? `${type}capture` : type, listener = isFunction(listener) ? listener : listener.handleEvent; const once = isObject(options) && options.once; return super.off(type, listener, context, once), this; } off(type, listener, options) { return this.removeEventListener(type, listener, options); } once(type, listener, options) { return isObject(options) ? (options.once = !0, this.addEventListener(type, listener, options)) : this.addEventListener(type, listener, { once: !0 }); } removeAllEventListeners() { return super.removeAllListeners(), this; } removeAllListeners() { return this.removeAllEventListeners(); } dispatchEvent(event, ...args) { return super.emit(event.type, event, ...args), !event.defaultPrevented; } emit(event, data) { return this.dispatchEvent(event, data); } release() { this.removeAllListeners(); } } const EventTarget = { dispatchEvent(e) { var _a; if (!(e instanceof FederatedEvent)) throw new Error("DisplayObject cannot propagate events outside of the Federated Events API"); return e.defaultPrevented = !1, e.path = [], e.detailPath && (e.detailPath = []), e.target = this, null === (_a = null == e ? void 0 : e.manager) || void 0 === _a || _a.dispatchEvent(e), !e.defaultPrevented; }, emit(eventName, object) { return this.dispatchEvent(new CustomEvent(eventName, object)); } }; const circleThreshold = tau - 1e-8; class BoundsContext { constructor(bounds) { this.init(bounds); } init(bounds) { this.bounds = bounds; } arc(cx, cy, r, sa, ea, ccw) { if (Math.abs(ea - sa) > circleThreshold) return this.bounds.add(cx - r, cy - r), void this.bounds.add(cx + r, cy + r); let s, i, x, y, xmin = 1 / 0, xmax = -1 / 0, ymin = 1 / 0, ymax = -1 / 0; function update(a) { x = r * Math.cos(a), y = r * Math.sin(a), x < xmin && (xmin = x), x > xmax && (xmax = x), y < ymin && (ymin = y), y > ymax && (ymax = y); } if (update(sa), update(ea), ea !== sa) if ((sa %= tau) < 0 && (sa += tau), (ea %= tau) < 0 && (ea += tau), ea < sa && (ccw = !ccw, s = sa, sa = ea, ea = s), ccw) for (ea -= tau, s = sa - sa % halfPi$1, i = 0; i < 4 && s > ea; ++i, s -= halfPi$1) update(s);else for (s = sa - sa % halfPi$1 + halfPi$1, i = 0; i < 4 && s < ea; ++i, s += halfPi$1) update(s); this.bounds.add(cx + xmin, cy + ymin), this.bounds.add(cx + xmax, cy + ymax); } arcTo(x1, y1, x2, y2, radius) { this.bounds.add(x1, y1); } bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) { this.bounds.add(cp1x, cp1y), this.bounds.add(cp2x, cp2y), this.bounds.add(x, y); } closePath() {} ellipse() { throw new Error("不支持ellipse"); } lineTo(x, y) { this.bounds.add(x, y); } moveTo(x, y) { this.bounds.add(x, y); } quadraticCurveTo(cpx, cpy, x, y) { this.bounds.add(cpx, cpy), this.bounds.add(x, y); } rect(x, y, w, h) { this.bounds.add(x, y), this.bounds.add(x + w, y + h); } clear() { this.bounds.clear(); } release(...params) {} } class CurvePath { constructor() { this._curves = [], this.bounds = new AABBBounds(); } get curves() { return this._curves; } getCurveLengths() { return this._curves.map(curve => curve.getLength()); } getPointAt(t) { return { x: 0, y: 0 }; } getLength() { return 0; } getBounds() { return this.bounds; } } const rePathCommand = /([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:[eE][-+]?\d+)?)/gi, commandLengths = { m: 2, l: 2, h: 1, v: 1, c: 6, s: 4, q: 4, t: 2, a: 7, M: 2, L: 2, H: 1, V: 1, C: 6, S: 4, Q: 4, T: 2, A: 7 }; const enumCommandMap = { A: 0, AT: 1, C: 2, Z: 3, E: 4, L: 5, M: 6, Q: 7, R: 8 }; let currPath, coordsStr, commandChar, coordStr, coordNumber, standardCommandLen; function parseSvgPath(str) { if (!str) return []; const paths = str.match(/[mzlhvcsqta][^mzlhvcsqta]*/gi); if (null === paths) return []; let currCommandData, coordsStrArr; const result = []; for (let i = 0, len = paths.length; i < len; i++) if (currPath = paths[i], coordsStr = currPath.slice(1), commandChar = currPath[0], currCommandData = [commandChar], coordsStrArr = coordsStr.match(rePathCommand), null !== coordsStrArr) { for (let i = 0, len = coordsStrArr.length; i < len; i++) coordStr = coordsStrArr[i], coordNumber = parseFloat(coordStr), Number.isNaN(coordNumber) || currCommandData.push(coordNumber); if (standardCommandLen = commandLengths[commandChar], currCommandData.length - 1 > standardCommandLen) { let subCommand, bestCommandChar = commandChar; for (let i = 1, len = currCommandData.length; i < len; i += standardCommandLen) { subCommand = [bestCommandChar]; for (let j = i, subLen = i + standardCommandLen; j < subLen; j++) subCommand.push(currCommandData[j]); result.push(subCommand), "m" === bestCommandChar ? bestCommandChar = "l" : "M" === bestCommandChar && (bestCommandChar = "L"); } } else result.push(currCommandData); } else result.push(currCommandData); return result; } function segments(x, y, rx, ry, large, sweep, rotateX, ox, oy) { const th = degreeToRadian(rotateX), sin_th = Math.sin(th), cos_th = Math.cos(th), px = cos_th * (ox - x) * .5 + sin_th * (oy - y) * .5, py = cos_th * (oy - y) * .5 - sin_th * (ox - x) * .5; let pl = px * px / ((rx = Math.abs(rx)) * rx) + py * py / ((ry = Math.abs(ry)) * ry); pl > 1 && (pl = Math.sqrt(pl), rx *= pl, ry *= pl); const a00 = cos_th / rx, a01 = sin_th / rx, a10 = -sin_th / ry, a11 = cos_th / ry, x0 = a00 * ox + a01 * oy, y0 = a10 * ox + a11 * oy, x1 = a00 * x + a01 * y, y1 = a10 * x + a11 * y; let sfactor_sq = 1 / ((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)) - .25; sfactor_sq < 0 && (sfactor_sq = 0); let sfactor = Math.sqrt(sfactor_sq); sweep === large && (sfactor = -sfactor); const xc = .5 * (x0 + x1) - sfactor * (y1 - y0), yc = .5 * (y0 + y1) + sfactor * (x1 - x0), th0 = Math.atan2(y0 - yc, x0 - xc); let th_arc = Math.atan2(y1 - yc, x1 - xc) - th0; th_arc < 0 && 1 === sweep ? th_arc += tau : th_arc > 0 && 0 === sweep && (th_arc -= tau); const segs = Math.ceil(Math.abs(th_arc / (halfPi$1 + .001))), result = []; for (let i = 0; i < segs; ++i) { const th2 = th0 + i * th_arc / segs, th3 = th0 + (i + 1) * th_arc / segs; result[i] = [xc, yc, th2, th3, rx, ry, sin_th, cos_th]; } return result; } function bezier(params) { const cx = params[0], cy = params[1], th0 = params[2], th1 = params[3], rx = params[4], ry = params[5], sin_th = params[6], cos_th = params[7], a00 = cos_th * rx, a01 = -sin_th * ry, a10 = sin_th * rx, a11 = cos_th * ry, cos_th0 = Math.cos(th0), sin_th0 = Math.sin(th0), cos_th1 = Math.cos(th1), sin_th1 = Math.sin(th1), th_half = .5 * (th1 - th0), sin_th_h2 = Math.sin(.5 * th_half), t = 8 / 3 * sin_th_h2 * sin_th_h2 / Math.sin(th_half), x1 = cx + cos_th0 - t * sin_th0, y1 = cy + sin_th0 + t * cos_th0, x3 = cx + cos_th1, y3 = cy + sin_th1, x2 = x3 + t * sin_th1, y2 = y3 - t * cos_th1; return [a00 * x1 + a01 * y1, a10 * x1 + a11 * y1, a00 * x2 + a01 * y2, a10 * x2 + a11 * y2, a00 * x3 + a01 * y3, a10 * x3 + a11 * y3]; } function drawArc(context, x, y, coords) { const seg = segments(coords[5], coords[6], coords[0], coords[1], coords[3], coords[4], coords[2], x, y); for (let i = 0; i < seg.length; ++i) { const bez = bezier(seg[i]); context.bezierCurveTo(bez[0], bez[1], bez[2], bez[3], bez[4], bez[5]); } } const addArcToBezierPath = (bezierPath, startAngle, endAngle, cx, cy, rx, ry, counterclockwise = !1) => { const PI2 = 2 * Math.PI, sAngle = (startAngle % PI2 + PI2) % PI2; let deltaAngle, eAngle = (endAngle % PI2 + PI2) % PI2; counterclockwise ? (eAngle >= sAngle && (eAngle -= PI2), deltaAngle = eAngle - sAngle) : (eAngle <= sAngle && (eAngle += PI2), deltaAngle = eAngle - sAngle); const count = Math.ceil(Math.abs(deltaAngle) / (.5 * Math.PI)), stepAngle = deltaAngle / count; for (let i = 0; i < count; i++) { const sa = sAngle + stepAngle * i, ea = sAngle + stepAngle * (i + 1), len = 4 / 3 * Math.tan(Math.abs(stepAngle) / 4), c1 = Math.cos(sa), s1 = Math.sin(sa), c2 = Math.cos(ea), s2 = Math.sin(ea), x1 = c1 * rx + cx, y1 = s1 * ry + cy, x4 = c2 * rx + cx, y4 = s2 * ry + cy, sign = counterclockwise ? -1 : 1, hx = rx * len * sign, hy = ry * len * sign; bezierPath.push(x1 - hx * s1, y1 + hy * c1, x4 + hx * s2, y4 - hy * c2, x4, y4); } }; const commandFuncs = [(command, context, x, y, sx, sy, z) => context.arc(command[1] * sx + x, command[2] * sy + y, command[3] * (sx + sy) / 2, command[4], command[5], command[6], z), (command, context, x, y, sx, sy, z) => context.arcTo(command[1] * sx + x, command[2] * sy + y, command[3] * sx + x, command[4] * sy + y, command[5] * (sx + sy) / 2, z), (command, context, x, y, sx, sy, z) => context.bezierCurveTo(command[1] * sx + x, command[2] * sy + y, command[3] * sx + x, command[4] * sy + y, command[5] * sx + x, command[6] * sy + y, z), (command, context, x, y) => context.closePath(), (command, context, x, y, sx, sy) => context.ellipse(command[1] * sx + x, command[2] * sy + y, command[3] * sx, command[4] * sy, command[5], command[6], command[7], command[8]), (command, context, x, y, sx, sy, z) => context.lineTo(command[1] * sx + x, command[2] * sy + y, z), (command, context, x, y, sx, sy, z) => context.moveTo(command[1] * sx + x, command[2] * sy + y, z), (command, context, x, y, sx, sy, z) => context.quadraticCurveTo(command[1] * sx + x, command[2] * sy + y, command[3] * sx + x, command[4] * sy + y, z), (command, context, x, y, sx, sy, z) => context.rect(command[1] * sx + x, command[2] * sy + y, command[3] * sx, command[4] * sy, z)]; function renderCommandList(commandList, context, x = 0, y = 0, sx = 1, sy = 1, z) { for (let i = 0; i < commandList.length; i++) { const command = commandList[i]; commandFuncs[command[0]](command, context, x, y, sx, sy, z); } } class Curve { getLength(direction) { return null != direction ? this.calcProjLength(direction) : (Number.isFinite(this.length) || (this.length = this.calcLength()), this.length); } } function snapLength(xArr, yArr) { let totalLength = 0; const count = xArr.length; for (let i = 0; i < count; i++) { const x = xArr[i], y = yArr[i], nextX = xArr[(i + 1) % count], nextY = yArr[(i + 1) % count]; totalLength += PointService.distanceNN(x, y, nextX, nextY); } return totalLength / 2; } function cubicLength(p0, p1, p2, p3, iterationCount) { return snapLength([p0.x, p1.x, p2.x, p3.x], [p0.y, p1.y, p2.y, p3.y]); } function cubicCalc(p0, p1, p2, p3, t) { const one = 1 - t; return one * one * one * p0 + 3 * p1 * t * one * one + 3 * p2 * t * t * one + p3 * t * t * t; } function cubicPointAt(p0, p1, p2, p3, t) { const x = cubicCalc(p0.x, p1.x, p2.x, p3.x, t), y = cubicCalc(p0.y, p1.y, p2.y, p3.y, t); return new Point(x, y); } function quadCalc(p0, p1, p2, t) { const one = 1 - t; return one * one * p0 + 2 * one * t * p1 + t * t * p2; } function quadPointAt(p0, p1, p2, t) { const x = quadCalc(p0.x, p1.x, p2.x, t), y = quadCalc(p0.y, p1.y, p2.y, t); return new Point(x, y); } function quadLength(p0, p1, p2, iterationCount) { return snapLength([p0.x, p1.x, p2.x], [p0.y, p1.y, p2.y]); } function divideCubic(curve, t) { const { p0: p0, p1: p1, p2: p2, p3: p3 } = curve, pt = cubicPointAt(p0, p1, p2, p3, t), c1 = PointService.pointAtPP(p0, p1, t), c2 = PointService.pointAtPP(p1, p2, t), c3 = PointService.pointAtPP(p2, p3, t), c12 = PointService.pointAtPP(c1, c2, t), c23 = PointService.pointAtPP(c2, c3, t); return [new CubicBezierCurve(p0, c1, c12, pt), new CubicBezierCurve(pt, c23, c3, p3)]; } class CubicBezierCurve extends Curve { constructor(p0, p1, p2, p3) { super(), this.type = CurveTypeEnum.CubicBezierCurve, this.p0 = p0, this.p1 = p1, this.p2 = p2, this.p3 = p3; } _validPoint() { return Number.isFinite(this.p0.x + this.p0.y + this.p1.x + this.p1.y + this.p2.x + this.p2.y + this.p3.x + this.p3.y); } getPointAt(t) { if (!1 !== this.defined) return cubicPointAt(this.p0, this.p1, this.p2, this.p3, t); throw new Error("defined为false的点不能getPointAt"); } calcLength() { return this._validPoint() ? cubicLength(this.p0, this.p1, this.p2, this.p3) : 60; } calcProjLength(direction) { return direction === Direction.ROW ? abs(this.p0.x - this.p3.x) : direction === Direction.COLUMN ? abs(this.p0.y - this.p3.y) : 0; } getAngleAt(t) { const minT = max(t - .01, 0), maxT = min(t + .01, 1), minP = this.getPointAt(minT), maxP = this.getPointAt(maxT); return atan2(maxP.y - minP.y, maxP.x - minP.x); } draw(path, x, y, sx, sy, percent) { if (path.moveTo(this.p0.x * sx + x, this.p0.y * sy + y), percent >= 1) path.bezierCurveTo(this.p1.x * sx + x, this.p1.y * sy + y, this.p2.x * sx + x, this.p2.y * sy + y, this.p3.x * sx + x, this.p3.y * sy + y);else if (percent > 0) { const [curve1] = divideCubic(this, percent); path.bezierCurveTo(curve1.p1.x * sx + x, curve1.p1.y * sy + y, curve1.p2.x * sx + x, curve1.p2.y * sy + y, curve1.p3.x * sx + x, curve1.p3.y * sy + y); } } includeX(x) { const minX = min(this.p0.x, this.p1.x, this.p2.x, this.p3.x), maxX = max(this.p0.x, this.p1.x, this.p2.x, this.p3.x); return x >= minX && x <= maxX; } getYAt(x) { const minX = min(this.p0.x, this.p1.x, this.p2.x, this.p3.x), t = (x - minX) / (max(this.p0.x, this.p1.x, this.p2.x, this.p3.x) - minX); return this.getPointAt(t).y; } } function divideLinear(curve, t) { const { p0: p0, p1: p1 } = curve, c1 = PointService.pointAtPP(p0, p1, t); return [new LineCurve(p0, c1), new LineCurve(c1, p1)]; } class LineCurve extends Curve { constructor(p0, p1) { super(), this.type = CurveTypeEnum.LineCurve, this.p0 = p0, this.p1 = p1; } getPointAt(t) { if (!1 !== this.defined) return PointService.pointAtPP(this.p0, this.p1, t); throw new Error("defined为false的点不能getPointAt"); } getAngleAt(t) { return null == this.angle && (this.angle = atan2(this.p1.y - this.p0.y, this.p1.x - this.p0.x)), this.angle; } _validPoint() { return Number.isFinite(this.p0.x + this.p0.y + this.p1.x + this.p1.y); } calcLength() { return this._validPoint() ? PointService.distancePP(this.p0, this.p1) : 60; } calcProjLength(direction) { return direction === Direction.ROW ? abs(this.p0.x - this.p1.x) : direction === Direction.COLUMN ? abs(this.p0.y - this.p1.y) : 0; } draw(path, x, y, sx, sy, percent) { if (path.moveTo(this.p0.x * sx + x, this.p0.y * sy + y), percent >= 1) path.lineTo(this.p1.x * sx + x, this.p1.y * sy + y);else if (percent > 0) { const p = this.getPointAt(percent); path.lineTo(p.x * sx + x, p.y * sy + y); } } includeX(x) { return x >= this.p0.x && x <= this.p1.x || x >= this.p1.x && x <= this.p0.x; } getYAt(x) { if (this.includeX(x)) { let minP = this.p0, maxP = this.p1; this.p0.x > this.p1.x && (minP = this.p1, maxP = this.p0); const percent = (x - minP.x) / (maxP.x - minP.x); return minP.y + percent * (maxP.y - minP.y); } return 1 / 0; } } class SegContext { get endX() { return this._lastX; } get endY() { return this._lastY; } constructor(curveType, direction) { this.init(curveType, direction); } init(curveType, direction) { this._lastX = this._lastY = this._startX = this._startY = 0, this.curveType = curveType, this.direction = direction, this.curves = []; } bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y, defined, p) { const curve = new CubicBezierCurve(new Point(this._lastX, this._lastY), new Point(cp1x, cp1y), new Point(cp2x, cp2y), new Point(x, y)); curve.originP1 = this._lastOriginP, curve.originP2 = p, curve.defined = defined, this.curves.push(curve), this._lastX = x, this._lastY = y, this._lastOriginP = p; } closePath() { if (this.curves.length < 2) return; const lastCurve = this.curves[this.curves.length - 1]; this.lineTo(this._startX, this._startY, lastCurve.defined, this._startOriginP); } ellipse() { throw new Error("SegContext不支持调用ellipse"); } lineTo(x, y, defined, p) { const curve = this.addLinearCurve(x, y, defined, this._lastOriginP, p); this.curves.push(curve), this._lastX = x, this._lastY = y, this._lastOriginP = p; } moveTo(x, y, p) { return this._lastX = this._startX = x, this._lastY = this._startY = y, this._lastOriginP = p, this._startOriginP = p, this; } quadraticCurveTo(cpx, cpy, x, y) { throw new Error("SegContext不支持调用quadraticCurveTo"); } clear() { this.curves = [], this.length = NaN; } tryUpdateLength(direction) { return this.getLength(direction); } addLinearCurve(x, y, defined, p1, p2) { const curve = new LineCurve(new Point(this._lastX, this._lastY), new Point(x, y)); return curve.originP1 = p1, curve.originP2 = p2, curve.defined = defined, curve; } getPointAt(t) { throw new Error("暂未实现"); } getCurveLengths() { return []; } getLength(direction) { var _a, _b; if (direction === Direction.COLUMN) { if (!this.curves.length) return 0; const sc = this.curves[0], ec = this.curves[this.curves.length - 1], endP = null !== (_a = ec.p3) && void 0 !== _a ? _a : ec.p1; return abs(sc.p0.y - endP.y); } if (direction === Direction.ROW) { if (!this.curves.length) return 0; const sc = this.curves[0], ec = this.curves[this.curves.length - 1], endP = null !== (_b = ec.p3) && void 0 !== _b ? _b : ec.p1; return abs(sc.p0.x - endP.x); } return Number.isFinite(this.length) || (this.length = this.curves.reduce((l, c) => l + c.getLength(), 0)), this.length; } } class ReflectSegContext extends SegContext { bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y, defined, p) { return super.bezierCurveTo(cp1y, cp1x, cp2y, cp2x, y, x, defined, p); } lineTo(x, y, defined, p) { return super.lineTo(y, x, defined, p); } moveTo(x, y, p) { return super.moveTo(y, x, p); } clear() { return super.clear(); } } function genCurveSegments(path, points, step = 1) { let defined0 = !1; for (let i = 0, n = points.length; i <= n; i++) i >= n === defined0 && ((defined0 = !defined0) ? path.lineStart() : path.lineEnd()), defined0 && path.point(points[i]); } function genSegContext(curveType, direction, points) { const curveDirection = null != direction ? direction : abs(points[points.length - 1].x - points[0].x) > abs(points[points.length - 1].y - points[0].y) ? Direction.ROW : Direction.COLUMN; return "monotoneY" === curveType ? new ReflectSegContext(curveType, curveDirection) : new SegContext(curveType, curveDirection); } class Linear { constructor(context, startPoint) { this.context = context, startPoint && (this.startPoint = startPoint); } areaStart() { this._line = 0; } areaEnd() { this._line = NaN; } lineStart() { this._point = 0, this.startPoint && this.point(this.startPoint); } lineEnd() { (this._line || 0 !== this._line && 1 === this._point) && this.context.closePath(), this._line = 1 - this._line; } point(p) { const x = p.x, y = p.y; switch (this._point) { case 0: this._point = 1, this._line ? this.context.lineTo(x, y, !1 !== this._lastDefined && !1 !== p.defined, p) : this.context.moveTo(x, y, p); break; case 1: this._point = 2; default: this.context.lineTo(x, y, !1 !== this._lastDefined && !1 !== p.defined, p); } this._lastDefined = p.defined; } tryUpdateLength() { return this.context.tryUpdateLength(); } } function genLinearSegments(points, params = {}) { const { direction: direction, startPoint: startPoint } = params; if (points.length < 2 - Number(!!startPoint)) return null; const segContext = genSegContext("linear", direction, points); return genLinearTypeSegments(new Linear(segContext, startPoint), points), segContext; } function genLinearTypeSegments(path, points) { return genCurveSegments(path, points, 1); } function point$3(curveClass, x, y, defined, p) { curveClass.context.bezierCurveTo((2 * curveClass._x0 + curveClass._x1) / 3, (2 * curveClass._y0 + curveClass._y1) / 3, (curveClass._x0 + 2 * curveClass._x1) / 3, (curveClass._y0 + 2 * curveClass._y1) / 3, (curveClass._x0 + 4 * curveClass._x1 + x) / 6, (curveClass._y0 + 4 * curveClass._y1 + y) / 6, defined, curveClass.lastPoint1); } class Basis { constructor(context, startPoint) { this.context = context, this.startPoint = startPoint; } areaStart() { this._line = 0; } areaEnd() { this._line = NaN; } lineStart() { this._x0 = this._x1 = this._y0 = this._y1 = NaN, this._point = 0, this.startPoint && this.point(this.startPoint); } lineEnd() { if (2 === this._point) point$3(this, 6 * this._x1 - (this._x0 + 4 * this._x1), 6 * this._y1 - (this._y0 + 4 * this._y1), !1 !== this._lastDefined1 && !1 !== this._lastDefined2, this.lastPoint1); (this._line || 0 !== this._line && 1 === this._point) && this.context.closePath(), this._line = 1 - this._line; } point(p) { const x = p.x, y = p.y; switch (this._point) { case 0: this._point = 1, this._line ? this.context.lineTo(x, y, !1 !== this._lastDefined1 && !1 !== this._lastDefined2, p) : this.context.moveTo(x, y, p); break; case 1: this._point = 2; break; default: point$3(this, x, y, !1 !== this._lastDefined1 && !1 !== this._lastDefined2); } this._x0 = this._x1, this._x1 = x, this._y0 = this._y1, this._y1 = y, this._lastDefined1 = this._lastDefined2, this._lastDefined2 = p.defined, this.lastPoint0 = this.lastPoint1, this.lastPoint1 = p; } tryUpdateLength() { return this.context.tryUpdateLength(); } } function genBasisTypeSegments(path, points) { return genCurveSegments(path, points, 2); } function genBasisSegments(points, params = {}) { const { direction: direction, startPoint: startPoint } = params; if (points.length < 2 - Number(!!startPoint)) return null; if (points.length < 3 - Number(!!startPoint)) return genLinearSegments(points, params); const segContext = genSegContext("basis", direction, points); return genBasisTypeSegments(new Basis(segContext, startPoint), points), segContext; } function sign(x) { return x < 0 ? -1 : 1; } function slope3(curveClass, x2, y2) { const h0 = curveClass._x1 - curveClass._x0, h1 = x2 - curveClass._x1, s0 = (curveClass._y1 - curveClass._y0) / (h0 || Number(h1 < 0 && -0)), s1 = (y2 - curveClass._y1) / (h1 || Number(h0 < 0 && -0)), p = (s0 * h1 + s1 * h0) / (h0 + h1); return (sign(s0) + sign(s1)) * Math.min(Math.abs(s0), Math.abs(s1), .5 * Math.abs(p)) || 0; } function slope2(curveClass, t) { const h = curveClass._x1 - curveClass._x0; return h ? (3 * (curveClass._y1 - curveClass._y0) / h - t) / 2 : t; } function point$2(curveClass, t0, t1, defined, p) { const x0 = curveClass._x0, y0 = curveClass._y0, x1 = curveClass._x1, y1 = curveClass._y1, dx = (x1 - x0) / 3; curveClass.context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1, defined, curveClass.lastPoint1); } class MonotoneX { constructor(context, startPoint) { this.context = context, this.startPoint = startPoint; } areaStart() { this._line = 0; } areaEnd() { this._line = NaN; } lineStart() { this._x0 = this._x1 = this._y0 = this._y1 = this._t0 = NaN, this._point = 0, this.startPoint && this.point(this.startPoint); } lineEnd() { switch (this._point) { case 2: this.context.lineTo(this._x1, this._y1, !1 !== this._lastDefined1 && !1 !== this._lastDefined2, this.lastPoint1); break; case 3: point$2(this, this._t0, slope2(this, this._t0), !1 !== this._lastDefined1 && !1 !== this._lastDefined2, this.lastPoint1); } (this._line || 0 !== this._line && 1 === this._point) && this.context.closePath(), this._line = 1 - this._line; } point(p) { let t1 = NaN; const x = p.x, y = p.y; switch (this._point) { case 0: this._point = 1, this._line ? this.context.lineTo(x, y, !1 !== this._lastDefined1 && !1 !== this._lastDefined2, p) : this.context.moveTo(x, y, p); break; case 1: this._point = 2; break; case 2: this._point = 3, point$2(this, slope2(this, t1 = slope3(this, x, y)), t1, !1 !== this._lastDefined1 && !1 !== this._lastDefined2); break; default: point$2(this, this._t0, t1 = slope3(this, x, y), !1 !== this._lastDefined1 && !1 !== this._lastDefined2); } this._x0 = this._x1, this._x1 = x, this._y0 = this._y1, this._y1 = y, this._t0 = t1, this._lastDefined1 = this._lastDefined2, this._lastDefined2 = !1 !== p.defined, this.lastPoint0 = this.lastPoint1, this.lastPoint1 = p; } tryUpdateLength() { return this.context.tryUpdateLength(); } } class MonotoneY extends MonotoneX { constructor(context, startPoint) { super(context, startPoint); } point(p) { return super.point({ y: p.x, x: p.y, defined: p.defined }); } } function genMonotoneXTypeSegments(path, points) { return genCurveSegments(path, points, 2); } function genMonotoneXSegments(points, params = {}) { const { direction: direction, startPoint: startPoint } = params; if (points.length < 2 - Number(!!startPoint)) return null; if (points.length < 3 - Number(!!startPoint)) return genLinearSegments(points, params); const segContext = genSegContext("monotoneX", direction, points); return genMonotoneXTypeSegments(new MonotoneX(segContext, startPoint), points), segContext; } function genMonotoneYTypeSegments(path, points) { return genCurveSegments(path, points, 2); } function genMonotoneYSegments(points, params = {}) { const { direction: direction, startPoint: startPoint } = params; if (points.length < 2 - Number(!!startPoint)) return null; if (points.length < 3 - Number(!!startPoint)) return genLinearSegments(points, params); const segContext = genSegContext("monotoneY", direction, points); return genMonotoneYTypeSegments(new MonotoneY(segContext, startPoint), points), segContext; } let Step$1 = class Step { constructor(context, t = .5, startPoint) { this.context = context, this._t = t, this.startPoint = startPoint; } areaStart() { this._line = 0; } areaEnd() { this._line = NaN; } lineStart() { this._x = this._y = NaN, this._point = 0, this.startPoint && this.point(this.startPoint); } lineEnd() { 0 < this._t && this._t < 1 && 2 === this._point && this.context.lineTo(this._x, this._y, !1 !== this._lastDefined, this.lastPoint), (this._line || 0 !== this._line && 1 === this._point) && this.context.closePath(), this._line >= 0 && (this._t = 1 - this._t, this._line = 1 - this._line); } point(p) { const x = p.x, y = p.y; switch (this._point) { case 0: this._point = 1, this._line ? this.context.lineTo(x, y, !1 !== this._lastDefined && !1 !== p.defined, p) : this.context.moveTo(x, y, p); break; case 1: this._point = 2; default: if (this._t <= 0) this.context.lineTo(this._x, y, !1 !== this._lastDefined && !1 !== p.defined, this.lastPoint), this.context.lineTo(x, y, !1 !== this._lastDefined && !1 !== p.defined, p);else { const x1 = this._x * (1 - this._t) + x * this._t; .5 === this._t ? this.context.lineTo(x1, this._y, !1 !== this._lastDefined, this.lastPoint) : this.context.lineTo(x1, this._y, !1 !== this._lastDefined && !1 !== p.defined, this.lastPoint), this.context.lineTo(x1, y, !1 !== this._lastDefined && !1 !== p.defined, p); } } this._lastDefined = p.defined, this._x = x, this._y = y, this.lastPoint = p; } tryUpdateLength() { return this.context.tryUpdateLength(); } }; class StepClosed extends Step$1 { lineEnd() { this.context.closePath(); } } function genStepSegments(points, t, params = {}) { const { direction: direction, startPoint: startPoint } = params; if (points.length < 2 - Number(!!startPoint)) return null; const segContext = new SegContext("step", null != direction ? direction : abs(points[points.length - 1].x - points[0].x) > abs(points[points.length - 1].y - points[0].y) ? Direction.ROW : Direction.COLUMN); return genStepTypeSegments(new Step$1(segContext, t, startPoint), points), segContext; } function genStepTypeSegments(path, points) { return genCurveSegments(path, points, 1); } function genStepClosedSegments(points, t, params = {}) { const { direction: direction, startPoint: startPoint } = params; if (points.length < 2 - Number(!!startPoint)) return null; const segContext = new SegContext("step", null != direction ? direction : abs(points[points.length - 1].x - points[0].x) > abs(points[points.length - 1].y - poin