@visactor/vrender-components
Version:
components library for dp visualization
353 lines (329 loc) • 17.4 kB
JavaScript
var __rest = this && this.__rest || function(s, e) {
var t = {};
for (var p in s) Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0 && (t[p] = s[p]);
if (null != s && "function" == typeof Object.getOwnPropertySymbols) {
var i = 0;
for (p = Object.getOwnPropertySymbols(s); i < p.length; i++) e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]) && (t[p[i]] = s[p[i]]);
}
return t;
};
import { AABBBounds, Bounds, getRectIntersect, isArray, isBoolean, isEmpty, isValid, max, merge, min, normalizePadding, pi, rectInsideAnotherRect } from "@visactor/vutils";
import { AbstractComponent } from "../core/base";
import { loadPoptipComponent } from "./register";
const _tBounds = new AABBBounds;
loadPoptipComponent();
const tlStr = "M -0.5 -0.5, L -0.5 0.5, L 0.5 -0.5, Z", blStr = "M -0.5 -0.5, L -0.5 0.5, L 0.5 0.5, Z", trStr = "M -0.5 -0.5, L 0.5 -0.5, L 0.5 0.5, Z", brStr = "M 0.5 -0.5, L 0.5 0.5, L -0.5 0.5, Z", conciseSymbolMap = {
tl: tlStr,
tr: trStr,
bl: blStr,
br: brStr,
lt: tlStr,
lb: blStr,
rt: trStr,
rb: brStr
};
export class PopTip extends AbstractComponent {
constructor(attributes, options) {
super((null == options ? void 0 : options.skipDefault) ? attributes : merge({}, PopTip.defaultAttributes, attributes)),
this.name = "poptip", this.positionList = [ "top", "tl", "tr", "bottom", "bl", "br", "left", "lt", "lb", "right", "rt", "rb" ];
}
render() {
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
const {titleStyle: titleStyle = {}, position: position, contentStyle: contentStyle = {}, panel: panel, logoSymbol: logoSymbol, poptipAnchor: poptipAnchor = "position", logoText: logoText, logoTextStyle: logoTextStyle = {}, triangleMode: triangleMode = "default", space: space = 4, minWidth: minWidth = 0, maxWidth: maxWidth = 1 / 0, padding: padding = 4, maxWidthPercent: maxWidthPercent, visible: visible, state: state, dx: dx = 0, dy: dy = 0, positionBounds: positionBounds} = this.attribute;
let {title: title = "", content: content = ""} = this.attribute;
title = this.attribute.titleFormatMethod ? this.attribute.titleFormatMethod(title) : title,
content = this.attribute.contentFormatMethod ? this.attribute.contentFormatMethod(content) : content;
const parsedPadding = normalizePadding(padding), group = this.createOrUpdateChild("poptip-content", {
x: 0,
y: 0,
zIndex: 1
}, "group");
this.group = group;
const maxLineWidth = maxWidth - parsedPadding[1] - parsedPadding[3], titleVisible = isValid(title) && !1 !== visible, titleAttrs = Object.assign(Object.assign({
text: isArray(title) ? title : [ title ],
visible: titleVisible,
wrap: !0
}, titleStyle), {
x: parsedPadding[3],
y: parsedPadding[0],
maxLineWidth: maxLineWidth,
textAlign: "left",
textBaseline: "top"
}), titleShape = group.createOrUpdateChild("poptip-title", titleAttrs, "text");
isEmpty(null == state ? void 0 : state.title) || (titleShape.states = state.title);
const titleBounds = titleShape.AABBBounds, titleHeight = titleBounds.height(), titleWidth = titleBounds.width();
let height = titleHeight + space;
titleVisible || (height = 0);
const contentVisible = isValid(content) && !1 !== visible, contentAttrs = Object.assign(Object.assign({
text: isArray(content) ? content : [ content ],
visible: contentVisible,
wrap: !0
}, contentStyle), {
x: parsedPadding[3],
y: parsedPadding[0] + height,
maxLineWidth: maxLineWidth,
textAlign: "left",
textBaseline: "top"
}), contentShape = group.createOrUpdateChild("poptip-content", contentAttrs, "text");
isEmpty(null == state ? void 0 : state.content) || (contentShape.states = state.content);
const contentBounds = contentShape.AABBBounds, contentHeight = contentBounds.height(), contentWidth = contentBounds.width();
contentVisible && (height += contentHeight), this.titleShape = titleShape, this.contentShape = contentShape;
let popTipWidth = max(titleWidth + parsedPadding[1] + parsedPadding[3], contentWidth + parsedPadding[1] + parsedPadding[3]);
popTipWidth > maxWidth ? popTipWidth = maxWidth : popTipWidth < minWidth && (popTipWidth = minWidth);
let poptipHeight = parsedPadding[0] + parsedPadding[2] + height;
const {visible: bgVisible, square: square} = panel, backgroundStyle = __rest(panel, [ "visible", "square" ]);
if (square) {
const maxWH = max(popTipWidth, poptipHeight);
popTipWidth = maxWH;
const deltaH = maxWH - poptipHeight;
poptipHeight = maxWH, titleShape.setAttributes({
dy: deltaH / 2
}), contentShape.setAttributes({
dy: deltaH / 2
});
}
const symbolSize = null !== (_a = backgroundStyle.size) && void 0 !== _a ? _a : 12, spaceSize = isArray(symbolSize) ? [ symbolSize[0] + (null !== (_b = backgroundStyle.space) && void 0 !== _b ? _b : 0), symbolSize[1] + (null !== (_c = backgroundStyle.space) && void 0 !== _c ? _c : 0) ] : symbolSize + (null !== (_d = backgroundStyle.space) && void 0 !== _d ? _d : 0), lineWidth = null !== (_e = backgroundStyle.lineWidth) && void 0 !== _e ? _e : 1, range = this.stage ? [ null !== (_f = this.stage.viewWidth) && void 0 !== _f ? _f : this.stage.width, null !== (_g = this.stage.viewHeight) && void 0 !== _g ? _g : this.stage.height ] : void 0;
if (range) {
const b = this.AABBBounds, leftWidth = null !== (_h = this.attribute.x) && void 0 !== _h ? _h : b.x1, rightWidth = range[0] - b.x1;
let maxSpace = Math.max(leftWidth, rightWidth);
const buf = (isArray(symbolSize) ? symbolSize[0] : 12) + 3;
if (maxSpace = Math.min(maxSpace - buf, maxSpace * maxWidthPercent), maxSpace < popTipWidth) {
popTipWidth = maxSpace;
const buf = parsedPadding[1] + parsedPadding[3];
titleShape.setAttribute("maxLineWidth", maxSpace - buf), contentShape.setAttribute("maxLineWidth", maxSpace - buf),
poptipHeight = parsedPadding[0] + parsedPadding[2], titleVisible && (poptipHeight += titleShape.AABBBounds.height() + space),
poptipHeight += contentShape.AABBBounds.height();
}
}
const layout = "auto" === position || isArray(position), positionList = isArray(position) ? position : this.positionList;
let maxBBoxI, maxBBoxSize = -1 / 0;
for (let i = 0; i < positionList.length + 1; i++) {
const p = layout ? positionList[i === positionList.length ? maxBBoxI : i] : position;
let symbolType = "arrow2Left", offsetX = (isArray(symbolSize) ? symbolSize[0] : symbolSize) / 4, offsetY = 0;
"top" === p || "bottom" === p || "left" === p || "right" === p ? symbolType = "arrow2Left" : "concise" === triangleMode && (symbolType = conciseSymbolMap[p],
offsetX = [ "tl", "bl", "rt", "rb" ].includes(p) ? (isArray(symbolSize) ? symbolSize[0] : symbolSize) / 2 : -(isArray(symbolSize) ? symbolSize[0] : symbolSize) / 2,
offsetY = [ "tl", "tr", "lb", "rb" ].includes(p) ? -(isArray(symbolSize) ? symbolSize[1] : symbolSize) / 2 : (isArray(symbolSize) ? symbolSize[1] : symbolSize) / 2);
const {angle: angle, offset: offset} = this.getAngleAndOffset(p, popTipWidth, poptipHeight, isArray(spaceSize) ? spaceSize : [ spaceSize, spaceSize - lineWidth ], symbolType);
let bgSymbol, anchorPoint = {
x: 0,
y: 0
};
if ("bounds" === poptipAnchor && positionBounds && (anchorPoint = this.calculateAnchorPoint(p, positionBounds)),
isBoolean(bgVisible)) {
let bgRect;
bgSymbol = group.createOrUpdateChild("poptip-symbol-panel", Object.assign(Object.assign({}, backgroundStyle), {
visible: bgVisible && (contentVisible || titleVisible),
x: offsetX,
y: offsetY,
strokeBoundsBuffer: -1,
boundsPadding: -2,
anchor: [ 0, 0 ],
symbolType: symbolType,
angle: angle,
dx: offset[0],
dy: offset[1] - (null !== (_j = backgroundStyle.space) && void 0 !== _j ? _j : 0),
size: symbolSize,
zIndex: 9
}), "symbol"), isEmpty(null == state ? void 0 : state.panel) || (bgSymbol.states = state.panel),
bgRect = panel.panelSymbolType ? group.createOrUpdateChild("poptip-rect-panel", Object.assign(Object.assign({}, backgroundStyle), {
visible: bgVisible && (contentVisible || titleVisible),
x: 0,
y: 0,
symbolType: "rect",
size: [ popTipWidth, poptipHeight ],
zIndex: -8
}), "symbol") : group.createOrUpdateChild("poptip-rect-panel", Object.assign(Object.assign({}, backgroundStyle), {
visible: bgVisible && (contentVisible || titleVisible),
x: 0,
y: 0,
width: popTipWidth,
height: poptipHeight,
zIndex: -8
}), "rect"), isEmpty(null == state ? void 0 : state.panel) || (bgRect.states = state.panel);
}
if (group.setAttributes({
x: -offset[0] + dx + anchorPoint.x,
y: -offset[1] + dy + anchorPoint.y,
anchor: [ offsetX, offsetY ]
}), logoSymbol) {
const {size: size = 12} = logoSymbol, sizeArray = isArray(size) ? size : [ size, size ];
"auto" === sizeArray[1] && (sizeArray[1] = poptipHeight), "auto" === sizeArray[0] && (sizeArray[0] = poptipHeight);
const sizeW = sizeArray[0];
group.createOrUpdateChild("poptip-logo", Object.assign(Object.assign({}, logoSymbol), {
x: 0,
y: poptipHeight / 2,
visible: bgVisible && (contentVisible || titleVisible),
zIndex: 10,
size: sizeArray
}), "symbol"), group.setAttributes({
x: -offset[0] + dx + sizeW / 2,
y: -offset[1] + dy
}), logoText && group.createOrUpdateChild("poptip-logo-text", Object.assign(Object.assign({}, logoTextStyle), {
x: 0,
y: poptipHeight / 2,
visible: bgVisible && (contentVisible || titleVisible),
text: logoText,
textAlign: "center",
textBaseline: "middle",
zIndex: 10
}), "text");
}
if (!range) break;
{
_tBounds.setValue(0, 0, popTipWidth, poptipHeight).transformWithMatrix(group.globalTransMatrix);
const b = _tBounds, stageBounds = (new Bounds).setValue(0, 0, range[0], range[1]);
if (layout) {
if (rectInsideAnotherRect(b, stageBounds, !1)) break;
{
const bbox = getRectIntersect(b, stageBounds, !1), size = (bbox.x2 - bbox.x1) * (bbox.y2 - bbox.y1);
size > maxBBoxSize && (maxBBoxSize = size, maxBBoxI = i);
}
}
if ([ "top", "bottom", "left", "right" ].includes(p)) {
const isVerticalPosition = "top" === p || "bottom" === p, isHorizontalPosition = "left" === p || "right" === p;
let mainDirectionOverlap = !1;
if (isVerticalPosition ? mainDirectionOverlap = "top" === p && b.y1 < 0 || "bottom" === p && b.y2 > stageBounds.y2 : isHorizontalPosition && (mainDirectionOverlap = "left" === p && b.x1 < 0 || "right" === p && b.x2 > stageBounds.x2),
!mainDirectionOverlap) {
let secondaryOffset = 0;
const szNumber = (isArray(symbolSize) ? symbolSize[1] : symbolSize) / 2;
isVerticalPosition ? (b.x1 < 0 ? secondaryOffset = -b.x1 : b.x2 > stageBounds.x2 && (secondaryOffset = stageBounds.x2 - b.x2),
group.setAttribute("x", group.attribute.x + secondaryOffset), bgSymbol.setAttribute("dx", min(max(bgSymbol.attribute.dx - secondaryOffset, szNumber), b.width() - szNumber))) : isHorizontalPosition && (b.y1 < 0 ? secondaryOffset = -b.y1 : b.y2 > stageBounds.y2 && (secondaryOffset = stageBounds.y2 - b.y2),
group.setAttribute("y", group.attribute.y + secondaryOffset), bgSymbol.setAttribute("dy", min(max(bgSymbol.attribute.dy - secondaryOffset, szNumber), b.height() - szNumber)));
break;
}
}
if (!layout) break;
}
}
}
calculateAnchorPoint(position, positionBounds) {
if (!positionBounds) return {
x: 0,
y: 0
};
const {x: x, y: y} = this.attribute, {x1: x1, y1: y1, x2: x2, y2: y2} = positionBounds, width = x2 - x1, height = y2 - y1;
switch (position) {
case "top":
case "tl":
case "tr":
return {
x: x1 + width / 2 - x,
y: y1 - y
};
case "bottom":
case "bl":
case "br":
return {
x: x1 + width / 2 - x,
y: y2 - y
};
case "left":
case "lt":
case "lb":
return {
x: x1 - x,
y: y1 + height / 2 - y
};
case "right":
case "rt":
case "rb":
return {
x: x2 - x,
y: y1 + height / 2 - y
};
default:
return {
x: 0,
y: 0
};
}
}
getAngleAndOffset(position, width, height, size, symbolType) {
const sizeH = "arrow2Left" === symbolType ? size[1] / 2 : size[1];
switch (position) {
case "tl":
return {
angle: "arrow2Left" === symbolType ? pi / 2 * 3 : 0,
offset: "arrow2Left" === symbolType ? [ width / 4, height + sizeH ] : [ 0, height + sizeH ]
};
case "top":
return {
angle: pi / 2 * 3,
offset: [ width / 2, height + sizeH ]
};
case "tr":
return {
angle: "arrow2Left" === symbolType ? pi / 2 * 3 : 0,
offset: "arrow2Left" === symbolType ? [ width / 4 * 3, height + sizeH ] : [ width, height + sizeH ]
};
case "rt":
return {
angle: 0,
offset: "arrow2Left" === symbolType ? [ -sizeH, height / 5 ] : [ -sizeH, 0 ]
};
case "right":
return {
angle: 0,
offset: [ -sizeH, height / 2 ]
};
case "rb":
return {
angle: 0,
offset: "arrow2Left" === symbolType ? [ -sizeH, height / 5 * 4 ] : [ -sizeH, height ]
};
case "bl":
return {
angle: "arrow2Left" === symbolType ? pi / 2 : 0,
offset: "arrow2Left" === symbolType ? [ width / 4, -sizeH ] : [ 0, -sizeH ]
};
case "bottom":
return {
angle: pi / 2,
offset: [ width / 2, -sizeH ]
};
case "br":
return {
angle: "arrow2Left" === symbolType ? pi / 2 : 0,
offset: "arrow2Left" === symbolType ? [ width / 4 * 3, -sizeH ] : [ width, -sizeH ]
};
case "lt":
return {
angle: "arrow2Left" === symbolType ? pi : 0,
offset: "arrow2Left" === symbolType ? [ width + sizeH, height / 5 ] : [ width + sizeH, 0 ]
};
case "left":
return {
angle: pi,
offset: [ width + sizeH, height / 2 ]
};
case "lb":
return {
angle: "arrow2Left" === symbolType ? pi : 0,
offset: "arrow2Left" === symbolType ? [ width + sizeH, height / 5 * 4 ] : [ width + sizeH, height ]
};
}
}
}
PopTip.defaultAttributes = {
position: "rt",
visible: !0,
title: null,
content: null,
titleStyle: {
fontSize: 12,
fill: "#000",
textAlign: "left",
textBaseline: "top"
},
contentStyle: {
fontSize: 12,
fill: "#000",
textAlign: "left",
textBaseline: "top"
},
panel: {},
maxWidthPercent: .8,
space: 8,
padding: 10
};
//# sourceMappingURL=poptip.js.map