UNPKG

@visactor/vchart

Version:

charts lib based @visactor/VGrammar

279 lines (265 loc) 15.3 kB
import { DataSet, DataView } from "@visactor/vdataset"; import { array, isValid, isNil, isString, isEqual } from "@visactor/vutils"; import { BaseComponent } from "../base/base-component"; import { calcLayoutNumber } from "../../util/space"; import { isAggrSpec } from "./utils"; import { getFirstSeries } from "../../util"; import { arrayParser } from "../../data/parser/array"; import { getSpecInfo } from "../util"; import { registerDataSetInstanceTransform } from "../../data/register"; import { markerAggregation } from "../../data/transforms/aggregation"; import { markerFilter } from "../../data/transforms/marker-filter"; import { releaseDataViewWithDependencies } from "../../data/data-view-utils"; const MARKER_FORMAT_METHOD_PLACEHOLDER = "__vchart_marker_format_method__", MARKER_COORDINATE_PLACEHOLDER = "__vchart_marker_coordinate__", MARKER_TEXT_PLACEHOLDER = "__vchart_marker_text__", MARKER_AUTO_RANGE_PLACEHOLDER = "__vchart_marker_auto_range__", MARKER_STYLE_PLACEHOLDER = "__vchart_marker_style__", MARKER_DOMAIN_POSITION_SPEC_KEYS = [ "coordinate", "coordinates", "x", "y", "x1", "y1", "angle", "angle1", "radius", "radius1" ], MARKER_LAYOUT_POSITION_SPEC_KEYS = [ "position", "positions", "coordinatesOffset", "regionRelative" ], MARKER_ITEM_CONTENT_LAYOUT_SPEC_KEYS = [ "offsetX", "offsetY", "confine" ], normalizeMarkerLabelFormatMethod = label => Array.isArray(label) ? label.map(normalizeMarkerLabelFormatMethod) : label && "object" == typeof label ? "function" != typeof label.formatMethod ? label : Object.assign(Object.assign({}, label), { formatMethod: MARKER_FORMAT_METHOD_PLACEHOLDER }) : label, normalizeMarkerStyles = value => { if (Array.isArray(value)) return value.map(normalizeMarkerStyles); if (!value || "object" != typeof value) return value; const normalized = Object.assign({}, value); return Object.keys(normalized).forEach((key => { "style" === key || key.endsWith("Style") ? normalized[key] = MARKER_STYLE_PLACEHOLDER : normalized[key] = normalizeMarkerStyles(normalized[key]); })), normalized; }, normalizeMarkerSpecForComponentOnlyUpdate = (spec, options) => { if (!spec || "object" != typeof spec) return spec; const normalized = Object.assign({}, spec); options.normalizeDomainPosition && MARKER_DOMAIN_POSITION_SPEC_KEYS.forEach((key => { normalized[key] = MARKER_COORDINATE_PLACEHOLDER; })), options.normalizeAutoRange && "autoRange" in normalized && (normalized.autoRange = MARKER_AUTO_RANGE_PLACEHOLDER), MARKER_LAYOUT_POSITION_SPEC_KEYS.forEach((key => { key in normalized && (normalized[key] = MARKER_COORDINATE_PLACEHOLDER); })), "label" in normalized && (normalized.label = normalizeMarkerLabelFormatMethod(normalized.label)), Object.keys(normalized).forEach((key => { normalized[key] = normalizeMarkerStyles(normalized[key]); })); const itemContent = normalized.itemContent; if (itemContent && "object" == typeof itemContent) { normalized.itemContent = Object.assign({}, itemContent), MARKER_ITEM_CONTENT_LAYOUT_SPEC_KEYS.forEach((key => { key in normalized.itemContent && (normalized.itemContent[key] = MARKER_COORDINATE_PLACEHOLDER); })); const text = normalized.itemContent.text; text && "object" == typeof text && (normalized.itemContent.text = Object.assign(Object.assign({}, normalizeMarkerLabelFormatMethod(text)), { text: MARKER_TEXT_PLACEHOLDER })); } return normalized; }; export class BaseMarker extends BaseComponent { constructor() { super(...arguments), this.layoutType = "none", this._markerDataChangeHandler = null, this._markerDataOwned = !1, this._layoutOffsetX = 0, this._layoutOffsetY = 0; } getRelativeSeries() { return this._relativeSeries; } getMarkerData() { return this._markerData; } static _getMarkerCoordinateType(markerSpec) { return "cartesian"; } static getSpecInfo(chartSpec) { return getSpecInfo(chartSpec, this.specKey, this.type, (s => !1 !== s.visible && this._getMarkerCoordinateType(s) === this.coordinateType)); } getMarkAttributeContext() { return this._markAttributeContext; } _buildMarkerAttributeContext() { this._markAttributeContext = { relativeSeries: this._relativeSeries, startRelativeSeries: this._startRelativeSeries, endRelativeSeries: this._endRelativeSeries, vchart: this._option.globalInstance }; } created() { super.created(), this._bindSeries(), this._initDataView(), this.initEvent(), this._buildMarkerAttributeContext(); } _getAllRelativeSeries() { return { getRelativeSeries: () => this._relativeSeries, getStartRelativeSeries: () => this._startRelativeSeries, getEndRelativeSeries: () => this._endRelativeSeries }; } _getAutoRangeExtendDomainKeyPrefix() { return `marker_${this.type}_${this.id}`; } _getAutoRangeExtendDomainKey(axisKey) { return `${this._getAutoRangeExtendDomainKeyPrefix()}_${axisKey}_extend`; } _clearAutoRangeExtendDomain() { var _a, _b; array(null === (_b = (_a = this._option).getAllSeries) || void 0 === _b ? void 0 : _b.call(_a)).forEach((series => { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; null === (_c = null === (_b = null === (_a = null == series ? void 0 : series.getXAxisHelper) || void 0 === _a ? void 0 : _a.call(series)) || void 0 === _b ? void 0 : _b.setExtendDomain) || void 0 === _c || _c.call(_b, this._getAutoRangeExtendDomainKey("xAxis"), void 0), null === (_f = null === (_e = null === (_d = null == series ? void 0 : series.getYAxisHelper) || void 0 === _d ? void 0 : _d.call(series)) || void 0 === _e ? void 0 : _e.setExtendDomain) || void 0 === _f || _f.call(_e, this._getAutoRangeExtendDomainKey("yAxis"), void 0), null === (_h = null === (_g = null == series ? void 0 : series.angleAxisHelper) || void 0 === _g ? void 0 : _g.setExtendDomain) || void 0 === _h || _h.call(_g, this._getAutoRangeExtendDomainKey("angleAxis"), void 0), null === (_k = null === (_j = null == series ? void 0 : series.radiusAxisHelper) || void 0 === _j ? void 0 : _j.setExtendDomain) || void 0 === _k || _k.call(_j, this._getAutoRangeExtendDomainKey("radiusAxis"), void 0); })); } _updateMarkerLayout() { this._clearAutoRangeExtendDomain(), this._markerLayout(); } _getFieldInfoFromSpec(dim, spec, relativeSeries) { const specKeyByDim = { x: "xField", y: "yField", radius: "valueField", angle: "categoryField", areaName: "nameField" }; return isString(spec) && isAggrSpec(spec) ? { field: relativeSeries.getSpec()[specKeyByDim[dim]], aggrType: spec } : spec; } _processSpecByDims(dimSpec) { const relativeSeries = this._relativeSeries, dimMap = {}; return dimSpec.forEach((d => dimMap[d.dim] = this._getFieldInfoFromSpec(d.dim, d.specValue, relativeSeries))), Object.assign(Object.assign({}, dimMap), this._getAllRelativeSeries()); } _processSpecCoo(spec) { return Object.assign(Object.assign({ coordinates: spec.coordinates || spec.coordinate }, this._getAllRelativeSeries()), { getSeriesByIdOrIndex: (seriesUserId, seriesIndex) => this._getSeriesByIdOrIndex(seriesUserId, seriesIndex), coordinateType: this.coordinateType }); } _getRelativeDataView() { if (this._specifiedDataSeries) { let resultData = []; array(this._specifiedDataSeries).forEach((series => { resultData = resultData.concat(series.getViewData().latestData); })); const dataSet = new DataSet; return dataSet.registerParser("array", arrayParser), new DataView(dataSet).parse(resultData, { type: "array" }); } return this._relativeSeries.getViewData(); } _setMarkerData(data, owned = !1) { this._releaseMarkerData(), this._markerData = data, this._markerDataOwned = owned; } _bindMarkerDataChange() { var _a; (null === (_a = this._markerData) || void 0 === _a ? void 0 : _a.target) && (this._markerDataChangeHandler = () => { this._updateMarkerLayout(); }, this._markerData.target.on("change", this._markerDataChangeHandler)); } _releaseMarkerData() { const markerData = this._markerData; (null == markerData ? void 0 : markerData.target) && this._markerDataChangeHandler && markerData.target.removeListener("change", this._markerDataChangeHandler), this._markerDataChangeHandler = null, this._markerDataOwned && releaseDataViewWithDependencies(markerData, (dataView => dataView.name === `${this.type}_${this.id}_data`)), this._markerData = null, this._markerDataOwned = !1; } updateLayoutAttribute() { var _a, _b, _c; if (null === (_a = this._spec.visible) || void 0 === _a || _a) { if (!this._markerComponent) { const markerComponent = this._createMarkerComponent(); markerComponent.name = null !== (_b = this._spec.name) && void 0 !== _b ? _b : this.type, markerComponent.id = null !== (_c = this._spec.id) && void 0 !== _c ? _c : `${this.type}-${this.id}`, this._markerComponent = markerComponent, this.getContainer().add(this._markerComponent), this._markerComponent.on("*", ((event, type) => { this._delegateEvent(this._markerComponent, event, type, null, this.getMarkerData.bind(this)); })); } this._updateMarkerLayout(); } super.updateLayoutAttribute(); } _getSeriesByIdOrIndex(seriesUserId, seriesIndex) { var _a, _b; let series; return series = null === (_a = this._option.getSeriesInUserIdOrIndex(isValid(seriesUserId) ? [ seriesUserId ] : [], [ seriesIndex ])) || void 0 === _a ? void 0 : _a[0], series || (series = null !== (_b = this._relativeSeries) && void 0 !== _b ? _b : this._getFirstSeries()), series; } _bindSeries() { const spec = this._spec; this._relativeSeries = this._getSeriesByIdOrIndex(spec.relativeSeriesId, spec.relativeSeriesIndex), this._startRelativeSeries = this._getSeriesByIdOrIndex(spec.startRelativeSeriesId, spec.startRelativeSeriesIndex), this._endRelativeSeries = this._getSeriesByIdOrIndex(spec.endRelativeSeriesId, spec.endRelativeSeriesIndex), spec.specifiedDataSeriesIndex && "all" === spec.specifiedDataSeriesIndex || spec.specifiedDataSeriesId && "all" === spec.specifiedDataSeriesId ? this._specifiedDataSeries = this._option.getAllSeries() : (spec.specifiedDataSeriesIndex || spec.specifiedDataSeriesId) && (this._specifiedDataSeries = this._getSeriesByIdOrIndex(spec.specifiedDataSeriesId, spec.specifiedDataSeriesIndex)); } initEvent() { "cartesian" !== this._relativeSeries.coordinate && (this._relativeSeries.event.on("zoom", this._updateMarkerLayout.bind(this)), this._relativeSeries.event.on("panmove", this._updateMarkerLayout.bind(this)), this._relativeSeries.event.on("scroll", this._updateMarkerLayout.bind(this))); } clear() { super.clear(), this._markerComponent = null, this._firstSeries = null; } release() { this._releaseMarkerData(), super.release(); } _getFirstSeries() { var _a; if (this._firstSeries) return this._firstSeries; const firstSeries = getFirstSeries(this._regions); return firstSeries ? (this._firstSeries = firstSeries, firstSeries) : (null === (_a = this._option) || void 0 === _a || _a.onError("need at least one series"), null); } _getNeedClearVRenderComponents() { return [ this._markerComponent ]; } onLayoutStart(layoutRect, chartViewRect) { isNil(this._spec.offsetX) || (this._layoutOffsetX = calcLayoutNumber(this._spec.offsetX, chartViewRect.width, chartViewRect)), isNil(this._spec.offsetY) || (this._layoutOffsetY = calcLayoutNumber(this._spec.offsetY, chartViewRect.height, chartViewRect)), super.onLayoutStart(layoutRect, chartViewRect); } _compareSpec(spec, prevSpec) { const result = super._compareSpec(spec, prevSpec); return isEqual(prevSpec, spec) || (result.reRender = !0, result.change = !0, result.reMake || result.reCompile || !this._isComponentOnlySpecChange(spec, prevSpec) ? result.reMake || result.reCompile || !this._isAutoRangeSpecChange(spec, prevSpec) ? result.reMake = !0 : result.effects = Object.assign(Object.assign({}, result.effects), { component: !0, scaleDomain: !0, layout: !0, render: !0 }) : result.effects = Object.assign(Object.assign({}, result.effects), { component: !0, layout: !0, render: !0 })), result; } _isComponentOnlySpecChange(spec, prevSpec) { const normalizeDomainPosition = !(null == spec ? void 0 : spec.autoRange) && !(null == prevSpec ? void 0 : prevSpec.autoRange); return isEqual(normalizeMarkerSpecForComponentOnlyUpdate(prevSpec, { normalizeDomainPosition: normalizeDomainPosition }), normalizeMarkerSpecForComponentOnlyUpdate(spec, { normalizeDomainPosition: normalizeDomainPosition })); } _isAutoRangeSpecChange(spec, prevSpec) { return !(!(null == spec ? void 0 : spec.autoRange) && !(null == prevSpec ? void 0 : prevSpec.autoRange)) && isEqual(normalizeMarkerSpecForComponentOnlyUpdate(prevSpec, { normalizeDomainPosition: !0, normalizeAutoRange: !0 }), normalizeMarkerSpecForComponentOnlyUpdate(spec, { normalizeDomainPosition: !0, normalizeAutoRange: !0 })); } reInit(spec) { super.reInit(spec), this._releaseMarkerData(), this._bindSeries(), this._initDataView(), this._buildMarkerAttributeContext(), this._markerComponent && this._updateMarkerLayout(); } _initCommonDataView() { const {options: options} = this._computeOptions(), seriesData = this._getRelativeDataView(); registerDataSetInstanceTransform(this._option.dataSet, "markerAggregation", markerAggregation), registerDataSetInstanceTransform(this._option.dataSet, "markerFilter", markerFilter), this._releaseMarkerData(); const data = new DataView(this._option.dataSet, { name: `${this.type}_${this.id}_data` }); data.parse([ seriesData ], { type: "dataview" }), data.transform({ type: "markerAggregation", options: options }), data.transform({ type: "markerFilter", options: this._getAllRelativeSeries() }), this._setMarkerData(data, !0), this._bindMarkerDataChange(); } } //# sourceMappingURL=base-marker.js.map