@visactor/vchart
Version:
charts lib based @visactor/VGrammar
279 lines (262 loc) • 16.2 kB
JavaScript
import { DataView } from "@visactor/vdataset";
import { BaseComponent } from "../base/base-component";
import { ComponentTypeEnum } from "../interface/type";
import { LayoutZIndex } from "../../constant/layout";
import { layoutByPosition, layoutOuter, placeRectByOrient } from "./layout";
import { CompilableData } from "../../compile/data/compilable-data";
import { normalizeLayoutPaddingSpec } from "../../util/space";
import { MarkPoint } from "@visactor/vrender-components";
import { createGroup, createRect, createSymbol, createText } from "@visactor/vrender-core";
import { transformToGraphic } from "../../util/style";
import { isValid } from "@visactor/vutils";
import { Factory } from "../../core/factory";
import { TransformLevel } from "../../data/initialize";
import { getSpecInfo } from "../util";
export class MapLabelComponent extends BaseComponent {
constructor() {
super(...arguments), this.type = ComponentTypeEnum.mapLabel, this.name = ComponentTypeEnum.mapLabel,
this.specKey = "mapLabel", this.layoutType = "none", this.layoutZIndex = LayoutZIndex.MarkPoint,
this._activeDatum = [];
}
static getSpecInfo(chartSpec) {
return getSpecInfo(chartSpec, this.specKey, this.type, (s => s.visible && isValid(s.seriesId)));
}
setAttrFromSpec() {
var _a, _b, _c, _d;
this.nameField = null !== (_a = this._spec.nameField) && void 0 !== _a ? _a : null === (_b = this._series) || void 0 === _b ? void 0 : _b.getDimensionField()[0],
this.valueField = null !== (_c = this._spec.valueField) && void 0 !== _c ? _c : null === (_d = this._series) || void 0 === _d ? void 0 : _d.getMeasureField()[0];
}
created() {
super.created(), !1 != !!this._spec.visible && (this.initRelatedInfo(), this.initData(),
this.initEvent());
}
initRelatedInfo() {
var _a, _b, _c, _d, _e, _f, _g, _h;
this._series = this._option.getSeriesInUserIdOrIndex([ this._spec.seriesId ])[0],
"outer" === this._spec.position && (this._map = null === (_b = null === (_a = this._regions[0].getSeriesInType("map")[0]) || void 0 === _a ? void 0 : _a.getMapViewData()) || void 0 === _b ? void 0 : _b.latestData,
this._longitudeField = null === (_e = null === (_d = (_c = this._regions[0]).getSpec) || void 0 === _d ? void 0 : _d.call(_c)) || void 0 === _e ? void 0 : _e.longitudeField,
this._latitudeField = null === (_h = null === (_g = (_f = this._regions[0]).getSpec) || void 0 === _g ? void 0 : _g.call(_f)) || void 0 === _h ? void 0 : _h.latitudeField);
}
initData() {
const series = this._series;
if (!series) return;
const seriesData = series.getViewData();
if (seriesData) {
const data = new DataView(this._option.dataSet, {
name: `${this.name}_data`
});
data.parse([ seriesData ], {
type: "dataview"
}), data.transform({
type: "copyDataView",
level: TransformLevel.copyDataView
}, !1), this._data = new CompilableData(this._option, data), data.target.addListener("change", (() => {
"hover" !== this._spec.trigger && "click" !== this._spec.trigger && (this._activeDatum = this._data.getLatestData());
}));
}
}
initEvent() {
var _a;
this.event.on("zoom", {
filter: params => this._isRelativeModel(params.model)
}, (e => (this.handleZoom(e), !0))), this.event.on("panmove", {
filter: params => this._isRelativeModel(params.model)
}, (e => (this.handlePan(e), !0)));
const trigger = this._spec.trigger;
if ("none" === trigger) return;
const view = null === (_a = this.getCompiler()) || void 0 === _a ? void 0 : _a.getVGrammarView();
view && ("hover" === trigger ? (view.addEventListener("element-highlight:start", (params => {
this._isRelativeSeries(params.options.seriesId) && this._updateDatum(params.elements[0].getDatum());
})), view.addEventListener("element-highlight:reset", (params => {
this._isRelativeSeries(params.options.seriesId) && this._updateDatum(null);
}))) : "click" === trigger && (view.addEventListener("element-select:start", (params => {
this._isRelativeSeries(params.options.seriesId) && this._updateDatum(params.elements[0].getDatum());
})), view.addEventListener("elementSelectReset", (params => {
this._isRelativeSeries(params.options.seriesId) && this._updateDatum([]);
}))));
}
handlePan(e) {
const {delta: delta} = e;
this._markerComponents.forEach((marker => {
marker.translate(delta[0], delta[1]);
}));
}
handleZoom(e) {
this._updateMarkerLayoutAttribute();
}
_updateDatum(datum) {
this._activeDatum = datum, this._markerComponents.forEach(((marker, index) => {
var _a;
const markerDatum = null === (_a = this._data) || void 0 === _a ? void 0 : _a.getLatestData()[index];
this._activeDatum.includes(markerDatum) ? marker.setAttribute("visible", !0) : marker.setAttribute("visible", !1);
}));
}
dataToPosition(datum) {
return this._series.dataToPosition(datum);
}
updateLayoutAttribute() {
var _a;
const markData = null === (_a = this._data) || void 0 === _a ? void 0 : _a.getLatestData();
markData && 0 !== markData.length && (super.updateLayoutAttribute(), this._updateMarkerLayoutAttribute());
}
_updateMarkerLayoutAttribute() {
var _a;
const layoutPairInfo = [], markerMarks = [];
this._markerComponents || (this._markerComponents = null === (_a = this._data) || void 0 === _a ? void 0 : _a.getLatestData().map(((data, index) => {
var _a;
const cmp = new MarkPoint({
position: void 0,
animation: !1
});
return cmp && (cmp.name = `${this.name}_marker_${index}`, cmp.id = null !== (_a = this._spec.id) && void 0 !== _a ? _a : `${this.name}_marker_${this.id}`,
cmp.setAttribute("zIndex", this.layoutZIndex)), cmp;
})));
this._markerComponents.forEach(((marker, index) => {
marker.removeAllChild();
const {pairInfo: pairInfo, contentMarks: contentMarks} = this._evaluateMarker(this._data.getLatestData()[index], index);
pairInfo && layoutPairInfo.push(pairInfo), contentMarks && markerMarks.push(contentMarks);
}));
const positionedRects = this._layoutLabels(layoutPairInfo);
this._layoutMarkers(positionedRects, markerMarks), this._renderMarkers();
}
_evaluateMarker(data, index) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
let contentItemCount = 0, paddingWidth = 0, paddingHeight = 0, contentWidth = 0, contentHeight = 0;
const position = this._spec.position || "top", offset = this._spec.offset, padding = normalizeLayoutPaddingSpec(null === (_a = this._spec.background) || void 0 === _a ? void 0 : _a.padding), space = this._spec.space || 0;
paddingWidth += ((null == padding ? void 0 : padding.left) || 0) + ((null == padding ? void 0 : padding.right) || 0),
paddingHeight += ((null == padding ? void 0 : padding.top) || 0) + ((null == padding ? void 0 : padding.bottom) || 0);
const contentMarks = {}, positionAttr = this.dataToPosition(data), container = createGroup({});
if (container.name = `${this.name}_marker_itemContainer_${index}`, contentMarks.container = container,
null === (_b = this._spec.background) || void 0 === _b ? void 0 : _b.visible) {
const labelBackground = createRect(transformToGraphic(Object.assign({}, this._spec.background.style)));
labelBackground.setAttributes(positionAttr), contentMarks.labelBackground = labelBackground,
container.appendChild(labelBackground);
}
if (null === (_c = this._spec.icon) || void 0 === _c ? void 0 : _c.visible) {
const icon = createSymbol(transformToGraphic(Object.assign({}, this._spec.icon.style)));
icon.setAttributes(positionAttr), icon.setAttribute("symbolType", null === (_d = this._spec.icon.style) || void 0 === _d ? void 0 : _d.shape);
const iconBound = icon.AABBBounds, iconHeight = null !== (_e = (null == iconBound ? void 0 : iconBound.y2) - (null == iconBound ? void 0 : iconBound.y1)) && void 0 !== _e ? _e : 0, iconWidth = null !== (_f = (null == iconBound ? void 0 : iconBound.x2) - (null == iconBound ? void 0 : iconBound.x1)) && void 0 !== _f ? _f : 0;
contentMarks.icon = icon, container.appendChild(icon), contentHeight = iconHeight,
contentWidth += iconWidth, contentItemCount++;
}
if (null === (_g = this._spec.nameLabel) || void 0 === _g ? void 0 : _g.visible) {
const nameLabel = createText(transformToGraphic(Object.assign({}, this._spec.nameLabel.style)));
nameLabel.setAttributes(positionAttr), nameLabel.setAttribute("text", data[this.nameField]);
const nameLabelBound = nameLabel.AABBBounds, nameLabelHeight = null !== (_h = (null == nameLabelBound ? void 0 : nameLabelBound.y2) - (null == nameLabelBound ? void 0 : nameLabelBound.y1)) && void 0 !== _h ? _h : 0, nameLabelWidth = null !== (_j = (null == nameLabelBound ? void 0 : nameLabelBound.x2) - (null == nameLabelBound ? void 0 : nameLabelBound.x1)) && void 0 !== _j ? _j : 0;
contentMarks.nameLabel = nameLabel, container.appendChild(nameLabel), contentHeight = Math.max(contentHeight, nameLabelHeight),
contentWidth += nameLabelWidth, contentItemCount++;
}
if ((null === (_k = this._spec.valueLabel) || void 0 === _k ? void 0 : _k.visible) && isValid(data[this.valueField])) {
const valueLabel = createText(transformToGraphic(Object.assign({}, this._spec.valueLabel.style)));
valueLabel.setAttributes(positionAttr), valueLabel.setAttribute("text", data[this.valueField]);
const valueLabelBound = valueLabel.AABBBounds, valueLabelHeight = null !== (_l = (null == valueLabelBound ? void 0 : valueLabelBound.y2) - (null == valueLabelBound ? void 0 : valueLabelBound.y1)) && void 0 !== _l ? _l : 0, valueLabelWidth = null !== (_m = (null == valueLabelBound ? void 0 : valueLabelBound.x2) - (null == valueLabelBound ? void 0 : valueLabelBound.x1)) && void 0 !== _m ? _m : 0;
contentMarks.valueLabel = valueLabel, container.appendChild(valueLabel), contentHeight = Math.max(contentHeight, valueLabelHeight),
contentWidth += valueLabelWidth, contentItemCount++;
}
const firstValidMark = Object.values(contentMarks).find((m => !!m && "group" !== m.type)), anchor = {
x: null == firstValidMark ? void 0 : firstValidMark.getComputedAttribute("x"),
y: null == firstValidMark ? void 0 : firstValidMark.getComputedAttribute("y")
}, itemRect = {
x: anchor.x,
y: anchor.y,
width: 0,
height: 0
};
itemRect.width = paddingWidth + contentWidth + (contentItemCount - 1) * space, itemRect.height = paddingHeight + contentHeight;
const pairInfo = {
rect: itemRect,
point: anchor,
index: index
};
if ("outer" !== position) {
const anchors = [ "top", "right", "left", "bottom" ].filter((a => a !== position));
pairInfo.rect = placeRectByOrient(itemRect, position, offset), pairInfo.anchors = anchors,
pairInfo.offset = offset;
} else pairInfo.pointCoord = {
x: +(null == data ? void 0 : data[this._longitudeField]),
y: +(null == data ? void 0 : data[this._latitudeField])
};
return {
pairInfo: pairInfo,
contentMarks: contentMarks
};
}
_layoutMarkers(positionedRects, contentMarks) {
var _a, _b, _c;
for (let i = 0; i < contentMarks.length; i++) {
if (!positionedRects[i] || !contentMarks[i]) return;
const {icon: icon, nameLabel: nameLabel, valueLabel: valueLabel, labelBackground: labelBackground, container: container} = contentMarks[i], itemRect = positionedRects[i], padding = normalizeLayoutPaddingSpec(null === (_a = this._spec.background) || void 0 === _a ? void 0 : _a.padding), space = this._spec.space || 0, curY = itemRect.height / 2;
let curX = (null == padding ? void 0 : padding.left) || 0;
[ icon, nameLabel, valueLabel ].forEach(((item, index) => {
var _a, _b;
if (item) {
const bounds = item.AABBBounds;
let offset = 0;
"symbol" === item.type && (offset += (null !== (_a = bounds.x2 - bounds.x1) && void 0 !== _a ? _a : 0) / 2),
item.setAttributes({
x: curX + offset,
y: curY
}), curX += null !== (_b = bounds.x2 - bounds.x1) && void 0 !== _b ? _b : 0, 2 !== index && (curX += space);
}
})), null == labelBackground || labelBackground.setAttributes({
x: 0,
y: 0,
width: itemRect.width,
height: itemRect.height
}), null == container || container.setAttributes({
dx: -itemRect.width / 2,
dy: -itemRect.height / 2
});
const datum = this._data.getLatestData()[i], anchor = this.dataToPosition(datum), regionPos = this.getRegions()[0].getLayoutStartPoint(), showLeader = !(!(null === (_b = this._spec.leader) || void 0 === _b ? void 0 : _b.visible) || !(icon || nameLabel || valueLabel));
this._markerComponents[i].setAttributes({
x: regionPos.x,
y: regionPos.y,
position: anchor,
visible: this._activeDatum.includes(datum),
itemContent: {
refX: 0,
type: "custom",
renderCustomCallback: () => container,
autoRotate: !1,
offsetX: itemRect.x + itemRect.width / 2 - anchor.x,
offsetY: itemRect.y + itemRect.height / 2 - anchor.y
},
itemLine: {
visible: showLeader,
type: "type-po",
lineStyle: transformToGraphic(Object.assign({}, null === (_c = this._spec.leader) || void 0 === _c ? void 0 : _c.style)),
startSymbol: {
visible: !1
}
}
});
}
}
_renderMarkers() {
if (this._markerComponents && this._markerComponents.length) for (let i = 0; i < this._markerComponents.length; i++) this.getContainer().add(this._markerComponents[i]);
}
_layoutLabels(rects) {
return "outer" === this._spec.position && this._map ? layoutOuter(rects, this._map, (coord => this._series.dataToPosition({
[this._longitudeField]: coord[0],
[this._latitudeField]: coord[1]
}))) : layoutByPosition(rects);
}
_isRelativeModel(model) {
var _a, _b, _c;
const id = null !== (_b = null === (_a = this._series.getXAxisHelper()) || void 0 === _a ? void 0 : _a.getAxisId()) && void 0 !== _b ? _b : null === (_c = this._series.getCoordinateHelper()) || void 0 === _c ? void 0 : _c.getCoordinateId();
return (null == model ? void 0 : model.id) === id;
}
_isRelativeSeries(model) {
return (null == model ? void 0 : model.id) === this._series.id;
}
onRender(ctx) {}
changeRegions() {}
_getNeedClearVRenderComponents() {
return this._markerComponents;
}
}
MapLabelComponent.type = ComponentTypeEnum.mapLabel, MapLabelComponent.specKey = "mapLabel";
export const registerMapLabel = () => {
Factory.registerComponent(MapLabelComponent.type, MapLabelComponent);
};
//# sourceMappingURL=component.js.map