@visactor/vchart
Version:
charts lib based @visactor/VGrammar
156 lines (143 loc) • 7.7 kB
JavaScript
import { isValid } from "@visactor/vutils";
import { ComponentTypeEnum } from "../interface/type";
import { LineCrosshair, RectCrosshair } from "@visactor/vrender-components";
import { BaseCrossHair } from "./base";
import { isXAxis, isYAxis } from "../axis/cartesian/util/common";
import { Factory } from "../../core/factory";
import { layoutByValue, layoutCrosshair } from "./utils/cartesian";
import { getFirstSeries } from "../../util";
import { getSpecInfo } from "../util";
import { crosshair } from "../../theme/builtin/common/component/crosshair";
export class CartesianCrossHair extends BaseCrossHair {
static getSpecInfo(chartSpec) {
return getSpecInfo(chartSpec, this.specKey, this.type, (s => s.xField && !1 !== s.xField.visible || s.yField && !1 !== s.yField.visible));
}
constructor(spec, options) {
super(spec, options), this.type = ComponentTypeEnum.cartesianCrosshair, this.name = ComponentTypeEnum.cartesianCrosshair,
this._stateByField = {
xField: {
coordKey: "x",
anotherAxisKey: "y",
currentValue: new Map,
labelsComp: {
top: null,
bottom: null
}
},
yField: {
coordKey: "y",
anotherAxisKey: "x",
currentValue: new Map,
labelsComp: {
left: null,
right: null
}
}
};
}
_findAllAxisContains(relativeX, relativeY) {
const xAxisMap = this._getAxisInfoByField("x"), yAxisMap = this._getAxisInfoByField("y");
return {
xAxisMap: this._filterAxisByPoint(xAxisMap, relativeX, relativeY),
yAxisMap: this._filterAxisByPoint(yAxisMap, relativeX, relativeY)
};
}
_getDatumAtPoint(axis, point) {
const dim = isXAxis(axis.getOrient()) ? "x" : "y", coordByAxis = point[dim] - (axis.getLayoutStartPoint()[dim] - this.getLayoutStartPoint()[dim]);
return axis.getScale().invert(coordByAxis);
}
setAxisValue(datum, axis) {
isXAxis(axis.getOrient()) ? this._stateByField.xField.currentValue.set(axis.getSpecIndex(), {
datum: datum,
axis: axis
}) : this._stateByField.yField.currentValue.set(axis.getSpecIndex(), {
datum: datum,
axis: axis
});
}
_layoutCrosshair(relativeX, relativeY, tooltipData, activeType) {
var _a;
let x = relativeX, y = relativeY;
if (tooltipData && tooltipData.length) if ("dimension" === activeType) {
const dimensionInfo = tooltipData[0], datumIndex = dimensionInfo.data.findIndex((dimData => dimData.datum.length > 0));
let pos;
if (datumIndex > -1) {
const dimensionData = dimensionInfo.data[datumIndex];
pos = dimensionData.series.dataToPosition(dimensionData.datum[0]);
}
(isValid(dimensionInfo.dimType) ? "y" === dimensionInfo.dimType : isYAxis(null === (_a = null == dimensionInfo ? void 0 : dimensionInfo.axis) || void 0 === _a ? void 0 : _a.getOrient())) ? y = null == pos ? void 0 : pos.y : x = null == pos ? void 0 : pos.x;
} else if ("mark" === activeType) {
const dimensionData = tooltipData[0], pos = dimensionData.series.dataToPosition(dimensionData.datum[0]);
x = null == pos ? void 0 : pos.x, y = null == pos ? void 0 : pos.y;
}
this.clearAxisValue();
const {xAxisMap: xAxisMap, yAxisMap: yAxisMap} = this._findAllAxisContains(x, y);
if (xAxisMap && 0 === xAxisMap.size || yAxisMap && 0 === yAxisMap.size) {
if (this.enableRemain) return;
this.hide();
} else xAxisMap && xAxisMap.size && this._setAllAxisValues(xAxisMap, {
x: x,
y: y
}, "xField"), yAxisMap && yAxisMap.size && this._setAllAxisValues(yAxisMap, {
x: x,
y: y
}, "yField"), this.layoutByValue();
}
layoutByValue(enableRemain) {
if (!this.enable) return;
const series = getFirstSeries(this._regions, "cartesian");
series && (layoutByValue(this._stateByField, series, this.getLayoutStartPoint(), null != enableRemain ? enableRemain : this.enableRemain),
Object.keys(this._stateByField).forEach((field => {
this._layoutByField(field);
})));
}
_layoutByField(field) {
const {cacheInfo: cacheInfo, attributes: attributes, labelsComp: labelsComp, bandSize: bandSize, coordKey: coordKey} = this._stateByField[field];
if (!attributes || !cacheInfo || cacheInfo._isCache && this.enableRemain) return;
const {coord: coord, labels: labels, visible: visible, labelsTextStyle: labelsTextStyle} = cacheInfo;
if (visible) {
const positionAttribute = layoutCrosshair(this._stateByField[field]);
this._updateCrosshairByField(field, positionAttribute), Object.keys(labels).forEach((labelKey => {
var _a, _b, _c;
if (labels[labelKey].visible) {
const updateAttrs = Object.assign(Object.assign(Object.assign({
[coordKey]: coord + bandSize / 2
}, labels[labelKey]), attributes.label), {
angle: attributes.label.syncAxisLabelAngle && null !== (_b = null === (_a = cacheInfo.axisLabel) || void 0 === _a ? void 0 : _a.attribute.angle) && void 0 !== _b ? _b : 0,
textStyle: Object.assign(Object.assign({}, null === (_c = attributes.label) || void 0 === _c ? void 0 : _c.textStyle), labelsTextStyle[labelKey]),
zIndex: this.labelZIndex,
visible: !0
});
this._updateCrosshairLabel(labelsComp[labelKey], updateAttrs, (label => {
label.name = `crosshair-${field.replace("Field", "")}-${labelKey}-label`, labelsComp[labelKey] = label;
}));
} else labelsComp[labelKey] && labelsComp[labelKey].hideAll();
}));
} else this._hideByField(field);
}
_updateCrosshairByField(field, positionAttribute) {
const container = this.getContainer(), {attributes: attributes} = this._stateByField[field];
let {crosshairComp: crosshairComp} = this._stateByField[field];
if (crosshairComp) crosshairComp.setAttributes(positionAttribute); else {
const style = attributes.style;
"line" === attributes.type ? crosshairComp = new LineCrosshair(Object.assign(Object.assign({}, positionAttribute), {
lineStyle: style,
zIndex: this.gridZIndex + 1,
disableTriggerEvent: this._option.disableTriggerEvent,
pickable: !1
})) : "rect" === attributes.type && (crosshairComp = new RectCrosshair(Object.assign(Object.assign({}, positionAttribute), {
rectStyle: style,
zIndex: this.gridZIndex,
disableTriggerEvent: this._option.disableTriggerEvent,
pickable: !1
}))), null == container || container.add(crosshairComp), this._stateByField[field].crosshairComp = crosshairComp;
}
}
}
CartesianCrossHair.specKey = "crosshair", CartesianCrossHair.builtInTheme = {
crosshair: crosshair
}, CartesianCrossHair.type = ComponentTypeEnum.cartesianCrosshair;
export const registerCartesianCrossHair = () => {
Factory.registerComponent(CartesianCrossHair.type, CartesianCrossHair);
};
//# sourceMappingURL=cartesian.js.map