UNPKG

@visactor/vrender-components

Version:

components library for dp visualization

283 lines (267 loc) 18.1 kB
import { graphicCreator } from "@visactor/vrender-core"; import { isValidNumber, merge } from "@visactor/vutils"; import { ArcSegment, Segment } from "../segment"; import { Tag } from "../tag"; import { Marker } from "./base"; import { DEFAULT_MARK_POINT_TEXT_STYLE_MAP, DEFAULT_MARK_POINT_THEME, FUZZY_EQUAL_DELTA } from "./config"; import { IMarkPointItemPosition } from "./type"; import { loadMarkPointComponent } from "./register"; import { computeOffsetForlimit } from "../util/limit-shape"; import { DEFAULT_STATES } from "../constant"; import { DefaultExitMarkerAnimation, DefaultUpdateMarkPointAnimation, markPointAnimate } from "./animate/animate"; import { deltaXYToAngle, fuzzyEqualNumber, getTextAlignAttrOfVerticalDir, isPostiveXAxis, removeRepeatPoint } from "../util"; loadMarkPointComponent(); export function registerMarkPointAnimate() { MarkPoint._animate = markPointAnimate; } export class MarkPoint extends Marker { markerAnimate(state) { MarkPoint._animate && this._animationConfig && MarkPoint._animate([ this._line, this._decorativeLine ], this._item, this._animationConfig, state); } constructor(attributes, options) { super((null == options ? void 0 : options.skipDefault) ? attributes : merge({}, MarkPoint.defaultAttributes, attributes)), this.name = "markPoint", this.defaultUpdateAnimation = DefaultUpdateMarkPointAnimation, this.defaultExitAnimation = DefaultExitMarkerAnimation, this._isArcLine = !1, this._isStraightLine = !1; } setLabelPos() {} getTextAlignAttr(autoRotate, offsetX, offsetY, lineEndAngle, itemPosition) { return fuzzyEqualNumber(Math.abs(lineEndAngle), Math.PI / 2, FUZZY_EQUAL_DELTA) || fuzzyEqualNumber(Math.abs(lineEndAngle), 3 * Math.PI / 2, FUZZY_EQUAL_DELTA) ? getTextAlignAttrOfVerticalDir(autoRotate, lineEndAngle, itemPosition) : isPostiveXAxis(lineEndAngle) ? DEFAULT_MARK_POINT_TEXT_STYLE_MAP.postiveXAxis[itemPosition] : DEFAULT_MARK_POINT_TEXT_STYLE_MAP.negativeXAxis[itemPosition]; } setItemAttributes(item, itemContent, newPosition, newItemPosition, itemType) { var _a, _b; if (!item) return; const {autoRotate: autoRotate = !0, refX: refX = 0, refY: refY = 0, refAngle: refAngle = 0, style: style, position: positionType = IMarkPointItemPosition.middle} = itemContent, {state: state} = this.attribute, lineEndAngle = (null === (_a = this._line) || void 0 === _a ? void 0 : _a.getEndAngle()) || 0, itemRefOffsetX = refX * Math.cos(lineEndAngle) + refY * Math.cos(lineEndAngle - Math.PI / 2), itemRefOffsetY = refX * Math.sin(lineEndAngle) + refY * Math.sin(lineEndAngle - Math.PI / 2); if ("text" === itemType) { const offsetX = newItemPosition.x - newPosition.x, offsetY = newItemPosition.y - newPosition.y; item.setAttributes(Object.assign(Object.assign({}, style), { textStyle: Object.assign(Object.assign({}, this.getTextAlignAttr(autoRotate, offsetX, offsetY, lineEndAngle, null !== (_b = itemContent.position) && void 0 !== _b ? _b : "end")), style.textStyle), state: { panel: merge({}, DEFAULT_STATES, null == state ? void 0 : state.textBackground), text: merge({}, DEFAULT_STATES, null == state ? void 0 : state.itemContent) } })); } else ("richText" === itemType || "image" === itemType) && (item.setAttributes({ dx: this.getItemDx(item, positionType, style) + (style.dx || 0), dy: this.getItemDy(item, positionType, style) + (style.dy || 0) }), item.states = merge({}, DEFAULT_STATES, null == state ? void 0 : state.itemContent)); const itemAngle = isPostiveXAxis(lineEndAngle) ? lineEndAngle : lineEndAngle - Math.PI; item.setAttributes({ x: newItemPosition.x + (itemRefOffsetX || 0), y: newItemPosition.y + (itemRefOffsetY || 0), angle: autoRotate && itemAngle + refAngle }); } getItemDx(item, position, style) { var _a, _b; const width = null !== (_b = null === (_a = null == item ? void 0 : item.AABBBounds) || void 0 === _a ? void 0 : _a.width()) && void 0 !== _b ? _b : (null == style ? void 0 : style.width) || 0; return position.includes("inside") ? -width : 0; } getItemDy(item, position, style) { var _a, _b; const height = null !== (_b = null === (_a = null == item ? void 0 : item.AABBBounds) || void 0 === _a ? void 0 : _a.height()) && void 0 !== _b ? _b : (null == style ? void 0 : style.height) || 0; return position.includes("top") || position.includes("Top") ? -height : position.includes("middle") || position.includes("Middle") ? -height / 2 : 0; } initItem(itemContent, newPosition, newItemPosition) { const {state: state} = this.attribute, {type: type = "text", style: style, renderCustomCallback: renderCustomCallback} = itemContent; let item; return "symbol" === type ? (item = graphicCreator.symbol(Object.assign(Object.assign({}, newItemPosition), style)), item.states = merge({}, DEFAULT_STATES, null == state ? void 0 : state.itemContent)) : "text" === type ? item = new Tag(Object.assign(Object.assign({}, newItemPosition), { state: { panel: merge({}, DEFAULT_STATES, null == state ? void 0 : state.textBackground), text: merge({}, DEFAULT_STATES, null == state ? void 0 : state.itemContent) } })) : "richText" === type ? (item = graphicCreator.richtext(Object.assign(Object.assign({}, newItemPosition), style)), item.states = merge({}, DEFAULT_STATES, null == state ? void 0 : state.itemContent)) : "image" === type ? (item = graphicCreator.image(Object.assign(Object.assign({}, newItemPosition), style)), item.states = merge({}, DEFAULT_STATES, null == state ? void 0 : state.itemContent)) : "custom" === type && renderCustomCallback && (item = renderCustomCallback(), item.states = merge({}, DEFAULT_STATES, null == state ? void 0 : state.itemContent)), item.name = `mark-point-${type}`, this.setItemAttributes(item, itemContent, newPosition, newItemPosition, type), item; } getItemLineAttr(itemLine, newPosition, newItemPosition) { let points = [], center = { x: 0, y: 0 }, radius = 0, startAngle = 0, endAngle = 0; const {type: type = "type-s", arcRatio: arcRatio = .8} = itemLine, itemOffsetX = newItemPosition.x - newPosition.x, itemOffsetY = newItemPosition.y - newPosition.y; if (this._isStraightLine = fuzzyEqualNumber(itemOffsetX, 0, FUZZY_EQUAL_DELTA) || fuzzyEqualNumber(itemOffsetY, 0, FUZZY_EQUAL_DELTA), this._isArcLine) { const {x: x1, y: y1} = this.attribute.position, {x: x2, y: y2} = newItemPosition, x0 = (x1 + x2) / 2, y0 = (y1 + y2) / 2, k = y1 === y2 ? 0 : -(x1 - x2) / (y1 - y2), centerX = x0 + arcRatio * (y2 > y1 ? -1 : 1) * x0, centerY = (x => k * (x - x0) + y0)(centerX); startAngle = deltaXYToAngle(y1 - centerY, x1 - centerX), endAngle = deltaXYToAngle(y2 - centerY, x2 - centerX), center = { x: centerX, y: centerY }; const R = Math.sqrt((centerX - x1) * (centerX - x1) + (centerY - y1) * (centerY - y1)), r = this.attribute.targetSymbol.style.size / 2; startAngle += 2 * Math.acos(Math.sqrt(1 - r * r / (4 * R * R))), arcRatio > 0 ? endAngle < startAngle && (endAngle += 2 * Math.PI) : startAngle < endAngle && (startAngle += 2 * Math.PI), radius = Math.sqrt((centerX - x1) * (centerX - x1) + (centerY - y1) * (centerY - y1)); } else points = "type-do" !== type || this._isStraightLine ? "type-po" !== type || this._isStraightLine ? "type-op" !== type || this._isStraightLine ? [ newPosition, newItemPosition ] : [ newPosition, { x: newPosition.x, y: newItemPosition.y }, newItemPosition ] : [ newPosition, { x: newItemPosition.x, y: newPosition.y }, newItemPosition ] : [ newPosition, { x: (newPosition.x + newItemPosition.x) / 2, y: newItemPosition.y }, newItemPosition ]; return points = removeRepeatPoint(points), { points: points, center: center, radius: radius, startAngle: startAngle, endAngle: endAngle }; } reDrawLine(itemLine, pointsAttr) { this._line.release(); const {startSymbol: startSymbol, endSymbol: endSymbol, lineStyle: lineStyle, type: type = "type-s"} = itemLine, {state: state} = this.attribute, lineConstructor = this._isArcLine ? ArcSegment : Segment; this._container.removeChild(this._line), this._line = new lineConstructor(Object.assign(Object.assign({}, pointsAttr), { pickable: !1, startSymbol: startSymbol, endSymbol: endSymbol, lineStyle: lineStyle, visible: itemLine.visible, state: { line: merge({}, DEFAULT_STATES, null == state ? void 0 : state.line), startSymbol: merge({}, DEFAULT_STATES, null == state ? void 0 : state.lineStartSymbol), endSymbol: merge({}, DEFAULT_STATES, null == state ? void 0 : state.lineEndSymbol) } })), this._container.add(this._line); } setItemLineAttr(itemLine, newPosition, newItemPosition) { if (this._line) { const {startSymbol: startSymbol, endSymbol: endSymbol, lineStyle: lineStyle, type: type = "type-s"} = itemLine, {state: state} = this.attribute, pointsAttr = this.getItemLineAttr(itemLine, newPosition, newItemPosition); this._isArcLine && "arc-segment" === this._line.key || !this._isArcLine && "segment" === this._line.key ? this._line.setAttributes(Object.assign(Object.assign({}, pointsAttr), { startSymbol: startSymbol, endSymbol: endSymbol, lineStyle: lineStyle, visible: itemLine.visible, state: { line: merge({}, DEFAULT_STATES, null == state ? void 0 : state.line), startSymbol: merge({}, DEFAULT_STATES, null == state ? void 0 : state.lineStartSymbol), endSymbol: merge({}, DEFAULT_STATES, null == state ? void 0 : state.lineEndSymbol) } })) : this.reDrawLine(itemLine, pointsAttr); } } getDecorativeLineAttr(itemLine) { var _a; const decorativeLength = (null === (_a = null == itemLine ? void 0 : itemLine.decorativeLine) || void 0 === _a ? void 0 : _a.length) || 10, itemAngle = this._line.getEndAngle() || 0; return { startPointOffsetX: decorativeLength / 2 * Math.cos(itemAngle - Math.PI / 2), startPointOffsetY: decorativeLength / 2 * Math.sin(itemAngle - Math.PI / 2), endPointOffsetX: -decorativeLength / 2 * Math.cos(itemAngle - Math.PI / 2), endPointOffsetY: -decorativeLength / 2 * Math.sin(itemAngle - Math.PI / 2) }; } setDecorativeLineAttr(itemLine, newItemPosition, visible) { var _a; if (this._decorativeLine) { const {lineStyle: lineStyle} = itemLine, {startPointOffsetX: startPointOffsetX, startPointOffsetY: startPointOffsetY, endPointOffsetX: endPointOffsetX, endPointOffsetY: endPointOffsetY} = this.getDecorativeLineAttr(itemLine); this._decorativeLine.setAttributes(Object.assign(Object.assign({ points: [ { x: newItemPosition.x + startPointOffsetX, y: newItemPosition.y + startPointOffsetY }, { x: newItemPosition.x + endPointOffsetX, y: newItemPosition.y + endPointOffsetY } ] }, lineStyle), { visible: visible })), this._decorativeLine.states = merge({}, DEFAULT_STATES, null === (_a = this.attribute.state) || void 0 === _a ? void 0 : _a.line); } } setTargetItemAttributes(targetItem, position) { var _a, _b; this._targetItem && (this._targetItem.setAttributes(Object.assign({ x: position.x, y: position.y, visible: null !== (_a = targetItem.visible) && void 0 !== _a && _a, size: targetItem.size }, targetItem.style)), this._targetItem.states = merge({}, DEFAULT_STATES, null === (_b = this.attribute.state) || void 0 === _b ? void 0 : _b.targetItem)); } setAllOfItemsAttr(newPosition, newItemPosition) { var _a; const {position: position, itemLine: itemLine = {}, itemContent: itemContent = {}, limitRect: limitRect, targetSymbol: targetSymbol} = this.attribute, {type: type = "text", confine: confine} = itemContent; if (limitRect && confine) { const {x: x, y: y, width: width, height: height} = limitRect, {dx: dx, dy: dy} = computeOffsetForlimit(this._item, { x1: x, y1: y, x2: x + width, y2: y + height }); newItemPosition.x = newItemPosition.x + dx, newItemPosition.y = newItemPosition.y + dy; } this.setTargetItemAttributes(targetSymbol, position), this.setItemLineAttr(itemLine, newPosition, newItemPosition), this.setItemAttributes(this._item, itemContent, newPosition, newItemPosition, type), this.setDecorativeLineAttr(itemLine, newItemPosition, null === (_a = itemLine.decorativeLine) || void 0 === _a ? void 0 : _a.visible); } computeNewPositionAfterTargetItem(position) { var _a, _b; const {itemContent: itemContent = {}, targetSymbol: targetSymbol, itemLine: itemLine} = this.attribute, {offsetX: itemContentOffsetX = 0, offsetY: itemContentOffsetY = 0} = itemContent, {offset: targetSymbolOffset = 0, style: targetSymbolStyle, visible: targetItemvisible = !1, size: targetSymbolSize} = targetSymbol, targetSize = targetItemvisible ? null !== (_b = null !== (_a = targetSymbolStyle.size) && void 0 !== _a ? _a : targetSymbolSize) && void 0 !== _b ? _b : 20 : 0; let targetOffsetAngle; targetOffsetAngle = "type-do" === itemLine.type ? deltaXYToAngle(itemContentOffsetY, itemContentOffsetX / 2) : "type-po" === itemLine.type ? deltaXYToAngle(0, itemContentOffsetX) : "type-op" === itemLine.type ? deltaXYToAngle(itemContentOffsetY, 0) : deltaXYToAngle(itemContentOffsetY, itemContentOffsetX); return { newPosition: { x: position.x + (targetSize / 2 + targetSymbolOffset) * Math.cos(targetOffsetAngle), y: position.y + (targetSize / 2 + targetSymbolOffset) * Math.sin(targetOffsetAngle) }, newItemPosition: { x: position.x + (targetSize / 2 + targetSymbolOffset) * Math.cos(targetOffsetAngle) + itemContentOffsetX, y: position.y + (targetSize / 2 + targetSymbolOffset) * Math.sin(targetOffsetAngle) + itemContentOffsetY } }; } initMarker(container) { const {position: position, itemContent: itemContent = {}, itemLine: itemLine} = this.attribute, {type: itemLineType = "type-s", arcRatio: arcRatio = .8} = itemLine, {offsetX: offsetX = 0, offsetY: offsetY = 0} = itemContent; this._isStraightLine = fuzzyEqualNumber(offsetX, 0, FUZZY_EQUAL_DELTA) || fuzzyEqualNumber(offsetY, 0, FUZZY_EQUAL_DELTA), this._isArcLine = "type-arc" === itemLineType && 0 !== arcRatio && !this._isStraightLine; const {newPosition: newPosition, newItemPosition: newItemPosition} = this.computeNewPositionAfterTargetItem(position), line = new (this._isArcLine ? ArcSegment : Segment)({ points: [], pickable: !1, center: { x: 0, y: 0 }, radius: 0, startAngle: 0, endAngle: 0 }); line.name = "mark-point-line", this._line = line, container.add(line); const decorativeLine = graphicCreator.line({ points: [] }); decorativeLine.name = "mark-point-decorativeLine", this._decorativeLine = decorativeLine, container.add(decorativeLine); const targetItem = graphicCreator.symbol({}); targetItem.name = "mark-point-targetItem", this._targetItem = targetItem, container.add(this._targetItem); const item = this.initItem(itemContent, newPosition, newItemPosition); this._item = item, container.add(item), this.setAllOfItemsAttr(newPosition, newItemPosition); } updateMarker() { const {position: position, itemContent: itemContent = {}, itemLine: itemLine} = this.attribute, {type: type = "text"} = itemContent, {type: itemLineType = "type-s", arcRatio: arcRatio = .8} = itemLine, {offsetX: offsetX = 0, offsetY: offsetY = 0} = itemContent; this._isStraightLine = fuzzyEqualNumber(offsetX, 0, FUZZY_EQUAL_DELTA) || fuzzyEqualNumber(offsetY, 0, FUZZY_EQUAL_DELTA); const isArcLine = "type-arc" === itemLineType && 0 !== arcRatio && !this._isStraightLine, {newPosition: newPosition, newItemPosition: newItemPosition} = this.computeNewPositionAfterTargetItem(position); isArcLine !== this._isArcLine ? (this._isArcLine = isArcLine, this.reDrawLine(itemLine, { points: [ { x: 0, y: 0 } ], pickable: !1, center: { x: 0, y: 0 }, radius: 0, startAngle: 0, endAngle: 0 })) : this._isArcLine = isArcLine, this.setItemAttributes(this._item, itemContent, newPosition, newItemPosition, type), this.setAllOfItemsAttr(newPosition, newItemPosition); } isValidPoints() { const {position: position} = this.attribute; return !(!isValidNumber(position.x) || !isValidNumber(position.y)); } } MarkPoint.defaultAttributes = DEFAULT_MARK_POINT_THEME; //# sourceMappingURL=point.js.map