@visactor/vchart
Version:
charts lib based @visactor/VGrammar
201 lines (185 loc) • 13.5 kB
JavaScript
import { DEFAULT_CHART_WIDTH, DEFAULT_CHART_HEIGHT } from "../../../constant/base";
import { DEFAULT_OPTIONS } from "./constants";
import { isTrueBrowser } from "../../../util/env";
import { getScale } from "./utils/common";
import { getActualTooltipPositionValue, getPositionType, isFixedTooltipPositionPattern, isGlobalTooltipPositionPattern } from "./utils/position";
import { isNumber, isObject, isValidNumber, isValid, isFunction } from "@visactor/vutils";
import { BasePlugin } from "../../base/base-plugin";
import { getTooltipPatternValue } from "../../../component/tooltip/utils";
export class BaseTooltipHandler extends BasePlugin {
constructor() {
super(...arguments), this._visible = !0, this._isReleased = !1, this.showTooltip = (activeType, data, params) => {
const {changePositionOnly: changePositionOnly} = params;
return changePositionOnly ? this.changeTooltipPosition(params, data) : this.changeTooltip(!0, params, data);
}, this.changeTooltip = (visible, params, data) => this._isReleased ? 1 : visible ? this.changeTooltipPosition(params, data) : (this._updateTooltip(!1, params),
0), this.changeTooltipPosition = (params, data) => {
var _a, _b, _c, _d, _e;
if (this._isReleased) return 1;
const event = params.event, {tooltipSpec: tooltipSpec, activeTooltipSpec: activeTooltipSpec, changePositionOnly: changePositionOnly} = params;
if (!activeTooltipSpec) return 1;
const activeType = activeTooltipSpec.activeType;
if (activeTooltipSpec.handler) return null !== (_c = null === (_b = (_a = activeTooltipSpec.handler).showTooltip) || void 0 === _b ? void 0 : _b.call(_a, activeType, data, params)) && void 0 !== _c ? _c : 0;
const pattern = activeTooltipSpec, position = this._getActualTooltipPosition(activeTooltipSpec, params, this._getTooltipBoxSize(activeTooltipSpec, changePositionOnly));
activeTooltipSpec.position = position;
const updatePosition = null !== (_d = activeTooltipSpec.updatePosition) && void 0 !== _d ? _d : null === (_e = tooltipSpec[activeType]) || void 0 === _e ? void 0 : _e.updatePosition;
updatePosition && (activeTooltipSpec.position = updatePosition(activeTooltipSpec.position, data, params));
let tooltipVisible = !1 !== (null == pattern ? void 0 : pattern.visible);
return data && "pointerout" !== event.type && activeTooltipSpec.visible && (activeTooltipSpec.title || activeTooltipSpec.content) || (tooltipVisible = !1),
this._updateTooltip(tooltipVisible, Object.assign(Object.assign({}, params), {
changePositionOnly: changePositionOnly
})), 0;
}, this._getActualTooltipPosition = (actualTooltip, params, tooltipBoxSize) => {
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
const getCartesianCrosshairRect = this._chartOption.getRectByDimensionData, {tooltipSpec: tooltipSpec} = params, invalidPosition = {
x: 1 / 0,
y: 1 / 0
};
if (!tooltipSpec) return invalidPosition;
const event = params.event, {activeType: activeType, data: data} = actualTooltip, firstDim = "dimension" === activeType ? null === (_b = null === (_a = data[0]) || void 0 === _a ? void 0 : _a.data) || void 0 === _b ? void 0 : _b[0] : null == data ? void 0 : data[0], {offsetX: offsetX, offsetY: offsetY} = this._option, spec = tooltipSpec[activeType], position = getTooltipPatternValue(null == spec ? void 0 : spec.position, data, params), positionMode = null !== (_c = getTooltipPatternValue(null == spec ? void 0 : spec.positionMode, data, params)) && void 0 !== _c ? _c : "mark" === activeType ? "mark" : "pointer", {width: tooltipBoxWidth = 0, height: tooltipBoxHeight = 0} = null != tooltipBoxSize ? tooltipBoxSize : {}, isCanvas = "canvas" === tooltipSpec.renderMode, canvasRect = null === (_d = null == params ? void 0 : params.chart) || void 0 === _d ? void 0 : _d.getCanvasRect(), canvasWidth = null !== (_e = null == canvasRect ? void 0 : canvasRect.width) && void 0 !== _e ? _e : DEFAULT_CHART_WIDTH, canvasHeight = null !== (_f = null == canvasRect ? void 0 : canvasRect.height) && void 0 !== _f ? _f : DEFAULT_CHART_HEIGHT;
let isFixedPosition = !1;
const containerSize = {
width: 0,
height: 0
};
let chartElementRect, relativePosOffset = {
x: 0,
y: 0
}, tooltipParentElementRect = {
x: 0,
y: 0
}, chartElementScale = 1, tooltipParentElementScale = 1;
const isBrowser = isTrueBrowser(this._env);
if (isBrowser && !tooltipSpec.confine ? (containerSize.width = window.innerWidth,
containerSize.height = window.innerHeight) : (containerSize.width = canvasWidth,
containerSize.height = canvasHeight), isBrowser && !isCanvas) {
const tooltipParentElement = this._getParentElement(tooltipSpec);
tooltipParentElementRect = null !== (_h = null === (_g = null == tooltipParentElement ? void 0 : tooltipParentElement.getBoundingClientRect) || void 0 === _g ? void 0 : _g.call(tooltipParentElement)) && void 0 !== _h ? _h : invalidPosition;
const chartElement = null !== (_j = this._compiler.getCanvas()) && void 0 !== _j ? _j : this._chartContainer;
chartElementRect = null == chartElement ? void 0 : chartElement.getBoundingClientRect(),
relativePosOffset = {
x: chartElementRect.x - tooltipParentElementRect.x,
y: chartElementRect.y - tooltipParentElementRect.y
}, chartElementScale = getScale(chartElement, chartElementRect), tooltipParentElementScale = getScale(tooltipParentElement, tooltipParentElementRect);
}
const tooltipSizeScale = tooltipParentElementScale / chartElementScale, calcPos = {}, pointerFixedPosition = {
x: position,
y: position
}, dimToPos = {
x: [ "left", "right" ],
y: [ "top", "bottom" ]
}, processCartesianFixedPosition = ({orient: orient, mode: mode, offset: offset}, dim) => {
var _a;
let dim1, dim2;
const model = params.model, startPoint = null == model ? void 0 : model.getLayoutStartPoint(), dimOffset = null != offset ? offset : "x" === dim ? offsetX : offsetY;
if ("mark" === mode) {
isFixedPosition = !0;
const markGraphic = params.item, bounds = null == markGraphic ? void 0 : markGraphic.AABBBounds;
bounds && startPoint && (dim1 = ("x" === dim ? bounds.x1 : bounds.y1) + startPoint[dim],
dim2 = ("x" === dim ? bounds.x2 : bounds.y2) + startPoint[dim]);
} else if (getCartesianCrosshairRect && "crosshair" === mode && "cartesian" === (null === (_a = null == firstDim ? void 0 : firstDim.series) || void 0 === _a ? void 0 : _a.coordinate) && firstDim.datum && firstDim.datum.length) {
isFixedPosition = !0;
const rect = getCartesianCrosshairRect(firstDim, startPoint);
rect && (dim1 = rect.start[dim], dim2 = rect.end[dim]);
} else pointerFixedPosition[dim] = orient;
if (isFixedPosition) {
const posKey = dimToPos[dim][0], boxSize = "x" === dim ? tooltipBoxWidth : tooltipBoxHeight;
switch (getPositionType(orient, dim)) {
case -2:
calcPos[posKey] = dim1 - boxSize * tooltipSizeScale - dimOffset;
break;
case -1.5:
calcPos[posKey] = dim1 + dimOffset;
break;
case 0:
calcPos[posKey] = (dim1 + dim2) / 2 - boxSize * tooltipSizeScale / 2;
break;
case -1:
calcPos[posKey] = (dim1 + dim2) / 2 - boxSize * tooltipSizeScale - dimOffset;
break;
case 1:
calcPos[posKey] = (dim1 + dim2) / 2 + dimOffset;
break;
case 1.5:
calcPos[posKey] = dim2 - boxSize * tooltipSizeScale - dimOffset;
break;
case 2:
calcPos[posKey] = dim2 + dimOffset;
}
}
}, dims = [ "x", "y" ];
if (isObject(position)) if (isGlobalTooltipPositionPattern(position)) {
const {left: posLeft, right: posRight, top: posTop, bottom: posBottom} = position;
calcPos.left = getActualTooltipPositionValue(posLeft, event), calcPos.top = getActualTooltipPositionValue(posTop, event),
calcPos.right = getActualTooltipPositionValue(posRight, event), calcPos.bottom = getActualTooltipPositionValue(posBottom, event);
} else isFixedTooltipPositionPattern(position) && dims.forEach((dim => {
const dimValue = position[dim];
isNumber(dimValue) || isFunction(dimValue) ? calcPos[dimToPos[dim][0]] = getActualTooltipPositionValue(dimValue, event) : processCartesianFixedPosition(dimValue, dim);
})); else isValid(position) && (processCartesianFixedPosition({
orient: position,
mode: positionMode
}, "x"), processCartesianFixedPosition({
orient: position,
mode: positionMode
}, "y"));
const result = {
x: null,
y: null
};
return dims.forEach((dim => {
var _a;
const boxSize = "x" === dim ? tooltipBoxWidth : tooltipBoxHeight, canvasSize = "x" === dim ? canvasWidth : canvasHeight, offset = "x" === dim ? offsetX : offsetY, posType = getPositionType(pointerFixedPosition[dim], dim);
if (isValidNumber(calcPos[dimToPos[dim][0]])) result[dim] = calcPos[dimToPos[dim][0]]; else if (isValidNumber(calcPos[dimToPos[dim][1]])) result[dim] = canvasSize - boxSize * tooltipSizeScale - calcPos[dimToPos[dim][1]]; else {
const value0 = "x" === dim ? event.canvasX : event.canvasY;
result[dim] = posType > 0 ? value0 + offset : 0 === posType ? value0 - boxSize * tooltipSizeScale / 2 : value0 - boxSize * tooltipSizeScale - offset;
}
result[dim] *= chartElementScale, isBrowser && (result[dim] += relativePosOffset[dim]),
result[dim] /= tooltipParentElementScale;
const containerDimSize = "x" === dim ? containerSize.width : containerSize.height, leftOrTop = tooltipSpec.confine ? -(tooltipParentElementRect[dim] - (null !== (_a = null == chartElementRect ? void 0 : chartElementRect[dim]) && void 0 !== _a ? _a : 0) / chartElementScale) / tooltipParentElementScale : -tooltipParentElementRect[dim] / tooltipParentElementScale, rightOrBottom = containerDimSize / tooltipParentElementScale + leftOrTop - boxSize;
2 !== posType && result[dim] < leftOrTop ? isFixedPosition ? result[dim] = leftOrTop : (result[dim] += 0 === posType ? offset + boxSize / 2 : 2 * offset + boxSize,
result[dim] > rightOrBottom && (result[dim] = rightOrBottom)) : -2 !== posType && result[dim] > rightOrBottom && (isFixedPosition ? result[dim] = rightOrBottom : (result[dim] -= 0 === posType ? offset + boxSize / 2 : 2 * offset + boxSize,
result[dim] < leftOrTop && (result[dim] = leftOrTop)));
})), result;
};
}
get env() {
return this._env;
}
onAdd(service) {
super.onAdd(service);
const component = service.component;
this._component = component, this._chartOption = component.getOption(), this._env = this._chartOption.mode,
this._chartContainer = this._chartOption.globalInstance.getContainer(), this._compiler = component.getCompiler(),
this._initFromSpec();
}
hideTooltip(params) {
return this.changeTooltip(!1, params);
}
release() {
var _a, _b, _c, _d;
const spec = null !== (_b = null === (_a = this._component) || void 0 === _a ? void 0 : _a.getSpec()) && void 0 !== _b ? _b : {};
spec.handler ? null === (_d = (_c = spec.handler).release) || void 0 === _d || _d.call(_c) : (this._removeTooltip(),
this._isReleased = !0, this._chartOption = null, this._component = null);
}
_getDefaultOption() {
var _a, _b;
const {offset: offset} = this._component.getSpec();
return offset ? {
offsetX: null !== (_a = offset.x) && void 0 !== _a ? _a : DEFAULT_OPTIONS.offsetX,
offsetY: null !== (_b = offset.y) && void 0 !== _b ? _b : DEFAULT_OPTIONS.offsetY
} : DEFAULT_OPTIONS;
}
_getParentElement(spec) {
return spec.parentElement;
}
getTooltipContainer() {
return this._container;
}
_initFromSpec() {
this._option = this._getDefaultOption();
}
reInit() {
this._initFromSpec();
}
}
BaseTooltipHandler.specKey = "tooltip";
//# sourceMappingURL=base.js.map