@visactor/vchart
Version:
charts lib based @visactor/VGrammar
925 lines • 51.6 kB
JavaScript
"use strict";
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;
};
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.BaseChart = void 0;
const data_1 = require("../chart-meta/data"), global_scale_1 = require("../../scale/global-scale"), interface_1 = require("../../component/interface"), factory_1 = require("../../core/factory"), event_1 = require("../../event/event"), util_1 = require("../../util"), base_model_1 = require("../../model/base-model"), base_mark_1 = require("../../mark/base/base-mark"), base_1 = require("../../constant/base"), vutils_1 = require("@visactor/vutils"), util_2 = require("../../theme/color-scheme/util"), compilable_base_1 = require("../../compile/compilable-base"), interface_2 = require("../../compile/mark/interface"), event_2 = require("../../constant/event"), interface_3 = require("../../event/events/dimension/interface"), util_3 = require("../util"), vscale_1 = require("@visactor/vscale"), initialize_1 = require("../../data/initialize"), layout_1 = require("../../constant/layout"), interaction_1 = require("../../interaction/interaction"), utils_1 = require("../../animation/utils"), MARKER_COMPONENT_SPEC_KEYS = {
[interface_1.ComponentTypeEnum.markPoint]: !0,
[interface_1.ComponentTypeEnum.markLine]: !0,
[interface_1.ComponentTypeEnum.markArea]: !0
}, MARKER_ADDITION_REMAKE_SPEC_KEYS = {
regionId: !0,
regionIndex: !0,
seriesId: !0,
seriesIndex: !0,
specifiedDataSeriesId: !0,
specifiedDataSeriesIndex: !0
};
class BaseChart extends compilable_base_1.CompilableBase {
getSpec() {
return this._spec;
}
setSpec(s) {
this._spec = s;
}
getOption() {
return this._option;
}
getLayoutRect() {
return this._layoutRect;
}
getViewRect() {
return this._viewRect;
}
getLayoutTag() {
return this._layoutTag;
}
setLayoutTag(tag, morphConfig, renderNextTick = !0) {
this._layoutTag = tag;
const compiler = this.getCompiler();
return compiler && (compiler.updateLayoutTag(), tag && renderNextTick && compiler.renderNextTick(morphConfig)),
this._layoutTag;
}
resetLayoutItemTag() {
this.getLayoutElements().forEach((element => element.setWillLayoutTag()));
}
getModelOption() {
return this._modelOption;
}
getGlobalScale() {
return this._globalScale;
}
getEvent() {
return this._event;
}
get chartData() {
return this._chartData;
}
_setModelOption() {}
constructor(spec, option) {
var _a, _b, _c, _d;
super(option), this.type = "chart", this.id = (0, util_1.createID)(), this._regions = [],
this._series = [], this._components = [], this._specTransformer = null, this._layoutRect = {
x: 0,
y: 0,
width: base_1.DEFAULT_CHART_WIDTH,
height: base_1.DEFAULT_CHART_HEIGHT
}, this._viewRect = {
width: base_1.DEFAULT_CHART_WIDTH,
height: base_1.DEFAULT_CHART_HEIGHT
}, this._viewBox = {
x1: 0,
y1: 0,
x2: base_1.DEFAULT_CHART_WIDTH,
y2: base_1.DEFAULT_CHART_HEIGHT
}, this._layoutTag = !0, this._idMap = new Map, this.state = {
layoutUpdateRank: 1
}, this.padding = {
top: 0,
left: 0,
right: 0,
bottom: 0
}, this.getAllSeries = () => {
var _a;
return null !== (_a = this._series) && void 0 !== _a ? _a : [];
}, this.getRegionsInIndex = index => index && 0 !== index.length ? this._regions.filter(((_r, i) => index.includes(i))) : [ this._regions[0] ],
this.getAllRegions = () => this._regions, this.getRegionsInIds = ids => ids ? this._regions.filter((r => ids.includes(r.id))) : [],
this.getRegionsInQuerier = region => region ? this._regions.filter(((r, index) => (0,
util_1.array)(region).some((regionFilter => (0, util_1.isValid)(regionFilter.regionId) && regionFilter.regionId === r.userId || regionFilter.regionIndex === index)))) : this._regions,
this.getRegionsInUserId = userId => {
if (userId) return this._regions.find((r => r.userId === userId));
}, this.getRegionsInUserIdOrIndex = (user_ids, index) => this.getAllRegions().filter((r => (null == user_ids ? void 0 : user_ids.length) ? r.userId && user_ids.includes(r.userId) : !(null == index ? void 0 : index.length) || index.includes(r.getSpecIndex()))),
this.getComponents = () => this._components, this.getSeriesInIndex = index => index && 0 !== index.length ? this._series.filter(((_r, i) => index.includes(i))) : [ this._series[0] ],
this.getSeriesInIds = ids => ids ? this._series.filter((r => ids.includes(r.id))) : [],
this.getSeriesInUserId = userId => {
if (userId) return this._series.find((r => r.userId === userId));
}, this.getSeriesInUserIdOrIndex = (user_ids, index) => this.getAllSeries().filter((s => (null == user_ids ? void 0 : user_ids.length) ? s.userId && user_ids.includes(s.userId) : !(null == index ? void 0 : index.length) || index.includes(s.getSpecIndex()))),
this.getComponentByIndex = (key, index) => {
const components = this._components.filter((c => (c.specKey || c.type) === key));
if (components && 0 !== components.length) return components[index];
}, this.getComponentsByKey = key => this._components.filter((c => (c.specKey || c.type) === key)),
this.getComponentByUserId = userId => {
const component = this._components.find((s => s.userId === userId));
if (component) return component;
}, this.getComponentsByType = type => this._components.filter((c => c.type === type)),
this._isMarkerAdditionSpecSafeWithoutRemake = spec => {
if (!spec || "object" != typeof spec) return !1;
const markerSpec = spec;
return !1 !== markerSpec.visible && !Object.keys(MARKER_ADDITION_REMAKE_SPEC_KEYS).some((key => !(0,
vutils_1.isNil)(markerSpec[key])));
}, this._paddingSpec = (0, util_1.normalizeLayoutPaddingSpec)(null !== (_a = spec.padding) && void 0 !== _a ? _a : option.getTheme("padding")),
this._event = new event_1.Event(option.eventDispatcher, option.mode), this._dataSet = option.dataSet,
this._chartData = new data_1.ChartData(this._dataSet), this._modelOption = Object.assign(Object.assign({}, option), {
mode: this._option.mode,
map: this._idMap,
getChartLayoutRect: () => this._layoutRect,
getChartViewRect: () => this._viewRect,
getChart: () => this,
globalScale: this._globalScale,
onError: null === (_b = this._option) || void 0 === _b ? void 0 : _b.onError,
disableTriggerEvent: !0 === (null === (_c = this._option) || void 0 === _c ? void 0 : _c.disableTriggerEvent),
componentShowContent: null === (_d = this._option) || void 0 === _d ? void 0 : _d.componentShowContent,
getSeriesData: this._chartData.getSeriesData.bind(this._chartData),
dispatchEvent: (eType, params) => this._option.globalInstance.event.emit(eType, params)
}), this._setModelOption && this._setModelOption(), this._spec = spec;
}
created(transformer) {
this._specTransformer = transformer, this._chartData.parseData(this._spec.data),
this._createGlobalScale(), this._createBackground(), this._createLayout(), transformer.forEachRegionInSpec(this._spec, this._createRegion.bind(this)),
transformer.forEachSeriesInSpec(this._spec, this._createSeries.bind(this)), transformer.forEachComponentInSpec(this._spec, this._createComponent.bind(this), this._option.getSpecInfo());
}
_initInteractions() {
if (this._option.disableTriggerEvent) return;
this._interaction = new interaction_1.Interaction;
const series = this.getAllSeries(), mergedTriggers = [], groupedTriggers = [];
series.forEach((s => {
const triggers = s.getInteractionTriggers();
if (triggers && triggers.length) {
const regionId = s.getRegion().id;
triggers.forEach((({trigger: trigger, marks: marks}) => {
const sameTrigger = groupedTriggers.find((item => item.regionId === regionId && (0,
vutils_1.isEqual)(item.config, trigger)));
if (sameTrigger) sameTrigger.trigger.marks.push(...marks); else {
const mergedTrigger = Object.assign(Object.assign({}, trigger), {
marks: [ ...marks ]
});
groupedTriggers.push({
regionId: regionId,
config: Object.assign({}, trigger),
trigger: mergedTrigger
}), mergedTriggers.push(mergedTrigger);
}
}));
}
})), mergedTriggers.forEach((trigger => {
const triggerInstance = factory_1.Factory.createInteractionTrigger(trigger.type, Object.assign(Object.assign({}, trigger), {
event: this._event,
interaction: this._interaction
}));
triggerInstance && (triggerInstance.init(), this._interaction.addTrigger(triggerInstance));
}));
}
init() {
var _b, _d;
null === (_b = this._beforeInit) || void 0 === _b || _b.call(this), this._regions.forEach((r => r.init({}))),
this._series.forEach((s => s.init({}))), this._components.forEach((c => c.init({
dataSet: this._dataSet
}))), this._initEvent(), null === (_d = this._initStack) || void 0 === _d || _d.call(this),
this.reDataFlow(), this._initInteractions(), this.initStageAnimation();
}
initStageAnimation() {
const compiler = this._option.getCompiler();
(null == compiler ? void 0 : compiler.setStageAnimationConfig) && compiler.setStageAnimationConfig((0,
utils_1.animationConfig)({}, (0, utils_1.userAnimationConfig)("stage", this._spec, {}), null));
}
reDataFlow() {
this._series.forEach((s => {
var _a;
return null === (_a = s.getRawData()) || void 0 === _a ? void 0 : _a.markRunning();
})), this._series.forEach((s => s.fillData())), this.updateGlobalScaleDomain();
}
onResize(width, height, reRender = !0) {
const canvasRect = {
width: width,
height: height
};
this._canvasRect = canvasRect, this._updateLayoutRect(this._option.viewBox), this.resetLayoutItemTag(),
this.setLayoutTag(!0, null, reRender);
}
updateViewBox(viewBox, reLayout) {
this._option.viewBox = viewBox, this._updateLayoutRect(viewBox), this.resetLayoutItemTag(),
this.setLayoutTag(!0, null, reLayout);
}
_createBackground() {
const bg = this._spec.background;
if (!bg || "object" != typeof bg || (0, util_1.isValid)(bg.gradient)) return;
const backgroundStyle = (0, vutils_1.pickWithout)(bg, [ "x", "y", "width", "height", "x1", "y1", "image" ]);
backgroundStyle.background = bg.image, this._backgroundMark = factory_1.Factory.createMark("group", "chart-background", {
model: this,
map: this._option.map,
getCompiler: this.getCompiler,
globalScale: this._globalScale
}), this._backgroundMark.created(), this._backgroundMark.setStyle(Object.assign(Object.assign({}, backgroundStyle), {
x: () => this._viewBox.x1,
y: () => this._viewBox.y1,
width: () => this._viewBox.x2 - this._viewBox.x1,
height: () => this._viewBox.y2 - this._viewBox.y1
})), this._backgroundMark.setMarkConfig({
zIndex: layout_1.LayoutZIndex.SeriesGroup - 2
}), this.getCompiler().addRootMark(this._backgroundMark);
}
_createRegion(constructor, specInfo) {
if (!constructor) return;
const {spec: spec} = specInfo, others = __rest(specInfo, [ "spec" ]), region = new constructor(spec, Object.assign(Object.assign({}, this._modelOption), others));
region && (region.created(), this._regions.push(region));
}
_createSeries(constructor, specInfo) {
if (!constructor) return;
const {spec: spec} = specInfo, others = __rest(specInfo, [ "spec" ]);
let region;
if ((0, util_1.isValid)(spec.regionId) ? region = this.getRegionsInUserId(spec.regionId) : (0,
util_1.isValid)(spec.regionIndex) && (region = this.getRegionsInIndex([ spec.regionIndex ])[0]),
!region && !(region = this._regions[0])) return;
const series = new constructor(spec, Object.assign(Object.assign(Object.assign({}, this._modelOption), others), {
type: spec.type,
region: region,
globalScale: this._globalScale,
sourceDataList: this._chartData.dataList
}));
series && (series.created(), this._series.push(series), region.addSeries(series));
}
getSeriesById(id) {
return this._series.find((x => x.id === id));
}
_createComponent(constructor, specInfo) {
const component = constructor.createComponent(specInfo, Object.assign(Object.assign({}, this._modelOption), {
type: constructor.type,
getAllRegions: this.getAllRegions,
getRegionsInIndex: this.getRegionsInIndex,
getRegionsInIds: this.getRegionsInIds,
getRegionsInUserIdOrIndex: this.getRegionsInUserIdOrIndex,
getAllSeries: this.getAllSeries,
getSeriesInIndex: this.getSeriesInIndex,
getSeriesInIds: this.getSeriesInIds,
getSeriesInUserIdOrIndex: this.getSeriesInUserIdOrIndex,
getAllComponents: this.getComponents,
getComponentByIndex: this.getComponentByIndex,
getComponentByUserId: this.getComponentByUserId,
getComponentsByKey: this.getComponentsByKey,
getComponentsByType: this.getComponentsByType
}));
component && (component.created(), this._components.push(component));
}
getAllComponents() {
return this._components;
}
getAllModels() {
return [].concat(this.getAllSeries(), this.getAllComponents(), this.getAllRegions());
}
getModelInFilter(filter) {
if ((0, vutils_1.isString)(filter)) return this.getAllModels().find((m => m.userId === filter));
if ((0, vutils_1.isFunction)(filter)) return this.getAllModels().find((m => filter(m)));
let index = 0;
return this.getAllModels().find((m => {
var _a;
if ((null !== (_a = m.specKey) && void 0 !== _a ? _a : m.type) === filter.type) {
if (index === filter.index) return !0;
index++;
}
return !1;
}));
}
_createLayout() {
this._updateLayoutRect(this._option.viewBox), this._initLayoutFunc();
}
setLayout(layout) {
this._option.layout = layout, this._initLayoutFunc();
}
_initLayoutFunc() {
var _a, _b, _c;
if (this._layoutFunc = this._option.layout, !this._layoutFunc) {
const constructor = factory_1.Factory.getLayoutInKey(null !== (_b = null === (_a = this._spec.layout) || void 0 === _a ? void 0 : _a.type) && void 0 !== _b ? _b : "base");
if (constructor) {
const layout = new constructor(this._spec.layout, {
onError: null === (_c = this._option) || void 0 === _c ? void 0 : _c.onError
});
this._layoutFunc = layout.layoutItems.bind(layout);
}
}
}
layout() {
var _a, _b, _c, _d;
if (null === (_b = null === (_a = this._option.performanceHook) || void 0 === _a ? void 0 : _a.beforeLayoutWithSceneGraph) || void 0 === _b || _b.call(_a, this._option.globalInstance),
this.getLayoutTag()) {
this._event.emit(event_2.ChartEvent.layoutStart, {
chart: this,
vchart: this._option.globalInstance
}), this.onLayoutStart();
const elements = this.getLayoutElements();
this._layoutFunc(this, elements, this._layoutRect, this._viewBox), this._event.emit(event_2.ChartEvent.afterLayout, {
elements: elements,
chart: this
}), this.setLayoutTag(!1), this.onLayoutEnd(), this._event.emit(event_2.ChartEvent.layoutEnd, {
chart: this,
vchart: this._option.globalInstance
});
}
null === (_d = null === (_c = this._option.performanceHook) || void 0 === _c ? void 0 : _c.afterLayoutWithSceneGraph) || void 0 === _d || _d.call(_c, this._option.globalInstance);
}
onLayoutStart() {
this.getAllModels().forEach((element => element.onLayoutStart(this._layoutRect, this._viewRect)));
}
onLayoutEnd() {
this.getAllModels().forEach((element => {
"series" !== element.modelType && element.onLayoutEnd();
}));
}
onEvaluateEnd(option) {
[ ...this._components, ...this._regions, ...this._series ].forEach((element => element.onEvaluateEnd(option)));
}
onBeforeRender() {
[ ...this._components, ...this._regions, ...this._series ].forEach((element => element.onBeforeRender()));
}
getLayoutElements() {
return this.getAllModels().map((i => i.layout)).filter((i => !!i));
}
getModelById(id) {
const model = this._idMap.get(id);
if (model && model instanceof base_model_1.BaseModel) return model;
}
getModelByUserId(userId) {
const series = this.getSeriesInUserId(userId);
if (series) return series;
const region = this.getRegionsInUserId(userId);
if (region) return region;
const component = this.getComponentByUserId(userId);
return component || void 0;
}
getAllMarks() {
return Array.from(this._idMap.values()).filter((item => item && item instanceof base_mark_1.BaseMark));
}
getMarkById(id) {
const mark = this._idMap.get(id);
if (mark && mark instanceof base_mark_1.BaseMark) return mark;
}
getMarkByUserName(name) {
return this.getAllMarks().filter((m => m.name && m.name === name));
}
updateData(id, data, updateGlobalScale = !0, options) {
const dv = this._dataSet.getDataView(id);
dv && (dv.markRunning(), dv.parseNewData(data, options)), updateGlobalScale && this.updateGlobalScaleDomain(),
this.getAllModels().forEach((model => model.onDataUpdate()));
}
updateFullData(data, updateGlobalScale = !0) {
(0, util_1.array)(data).forEach((d => {
const dv = this._dataSet.getDataView(d.id);
dv && dv.markRunning();
})), (0, util_1.array)(data).forEach((d => {
const dv = this._dataSet.getDataView(d.id);
dv && (0, initialize_1.updateDataViewInData)(dv, d, !0);
})), updateGlobalScale && this.updateGlobalScaleDomain(), this.getAllModels().forEach((model => model.onDataUpdate()));
}
setCanvasRect(width, height) {
this._canvasRect = {
width: width,
height: height
};
}
getCanvasRect() {
return this._canvasRect || (this._canvasRect = (0, util_3.calculateChartSize)(this._spec, this._option, {
width: base_1.DEFAULT_CHART_WIDTH,
height: base_1.DEFAULT_CHART_HEIGHT
})), this._canvasRect;
}
getSeriesData(id, index) {
return this._chartData.getSeriesData(id, index);
}
_transformSpecScale() {
var _a;
const scales = this._spec.scales ? [ ...this._spec.scales ] : [];
let colorScaleSpec = scales.find((s => "color" === s.id));
const colorScheme = this.getColorScheme();
if (!colorScaleSpec && (colorScaleSpec = {
type: "ordinal",
id: "color",
domain: null,
range: null
}, scales.push(colorScaleSpec), this._spec.color)) {
const colorSpec = this._spec.color;
if ((0, util_1.isArray)(colorSpec)) colorScaleSpec.range = colorSpec; else {
const tempSpec = colorSpec;
Object.prototype.hasOwnProperty.call(tempSpec, "type") && (colorScaleSpec.type = tempSpec.type),
Object.prototype.hasOwnProperty.call(tempSpec, "domain") && (colorScaleSpec.domain = tempSpec.domain),
Object.prototype.hasOwnProperty.call(tempSpec, "range") && (colorScaleSpec.range = tempSpec.range),
Object.prototype.hasOwnProperty.call(tempSpec, "specified") && (colorScaleSpec.specified = tempSpec.specified),
Object.prototype.hasOwnProperty.call(tempSpec, "clamp") && (colorScaleSpec.clamp = tempSpec.clamp);
}
}
return (null === (_a = colorScaleSpec.range) || void 0 === _a ? void 0 : _a.length) || (colorScaleSpec.range = (0,
util_2.getDataScheme)(colorScheme), colorScaleSpec.rangeTheme = !0), scales;
}
_createGlobalScale() {
this._globalScale = new global_scale_1.GlobalScale(this._transformSpecScale(), this),
this._modelOption.globalScale = this._globalScale;
}
updateGlobalScaleDomain() {
const domainSet = new Set;
this._series.forEach((s => {
const keys = s.getSeriesKeys();
keys && keys.forEach((k => domainSet.add(k)));
}));
const domain = Array.from(domainSet);
this._globalScale.updateScaleDomain(domain);
}
updateGlobalScale(result) {
(0, util_3.mergeUpdateResult)(result, this._globalScale.updateSpec(this._transformSpecScale()));
}
updateGlobalScaleTheme() {
const colorSpec = this._globalScale.getScaleSpec("color"), colorScheme = this.getColorScheme();
colorSpec.rangeTheme && (colorSpec.range = (0, util_2.getDataScheme)(colorScheme),
this._globalScale.getScale("color").range(colorSpec.range));
}
_getSpecKeys(spec) {
const ignoreKeys = {
width: !0,
height: !0,
xField: !0,
yField: !0
};
return Object.keys(spec).filter((key => !ignoreKeys[key])).sort();
}
_isSeriesRelatedSpecKey(key) {
var _a, _b;
return !!(null === (_b = null === (_a = this._specTransformer) || void 0 === _a ? void 0 : _a.getSeriesRelatedSpecKeys()) || void 0 === _b ? void 0 : _b[key]);
}
_canChangeSpecKeysWithoutRemake(currentKeys, nextKeys) {
const currentKeySet = new Set(currentKeys), nextKeySet = new Set(nextKeys), changedKeys = [ ...currentKeys.filter((key => !nextKeySet.has(key))), ...nextKeys.filter((key => !currentKeySet.has(key))) ];
return changedKeys.length > 0 && changedKeys.every((key => this._isSeriesRelatedSpecKey(key)));
}
updateSpec(spec) {
var _a, _b;
const result = {
change: !1,
reMake: !1,
reRender: !1,
reSize: !1,
reCompile: !1
};
if (spec.type !== this.type) return result.reMake = !0, this.setLayoutTag(!0, null, !1),
result;
const currentKeys = this._getSpecKeys(this._spec), nextKeys = this._getSpecKeys(spec);
if (!(0, vutils_1.isEqual)(currentKeys, nextKeys) && !this._canChangeSpecKeysWithoutRemake(currentKeys, nextKeys)) return result.reMake = !0,
this.setLayoutTag(!0, null, !1), result;
const specKeys = Array.from(new Set([ ...currentKeys, ...nextKeys ])).sort();
for (let i = 0; i < specKeys.length; i++) {
const key = specKeys[i], currentSpec = this._spec[key], nextSpec = spec[key];
if ((0, util_1.isArray)(currentSpec) && currentSpec.length !== (0, util_1.array)(nextSpec).length && !this._canChangeMarkerComponentsWithoutRemake(key, currentSpec, nextSpec)) return result.reMake = !0,
this.setLayoutTag(!0, null, !1), result;
}
const oldSpec = this._spec, onlyMarkerComponentsRemoved = this._isOnlyMarkerComponentsRemoved(this._spec, spec, specKeys), onlyComponentSpecsChanged = this._isOnlyComponentSpecsChanged(this._spec, spec, specKeys), onlySeriesSpecsChanged = this._isOnlySeriesSpecsChanged(this._spec, spec, specKeys), onlyComponentOrSeriesSpecsChanged = !(!onlyComponentSpecsChanged && !onlySeriesSpecsChanged) || this._isOnlyComponentOrSeriesSpecsChanged(this._spec, spec, specKeys);
if (this._spec = spec, onlyMarkerComponentsRemoved) return this._removeMarkerComponentsForEmptySpecs(result),
result;
if (this.updateChartConfig(result, oldSpec), result.reMake) return this.setLayoutTag(!0, null, !1),
result;
if (this.updateGlobalScale(result), result.reMake) return this.setLayoutTag(!0, null, !1),
result;
if (this.updateRegionSpec(result), result.reMake) return this.setLayoutTag(!0, null, !1),
result;
const componentUpdateResult = this.updateComponentSpec(result);
return result.reMake ? (this.setLayoutTag(!0, null, !1), result) : (!onlyComponentSpecsChanged && (null === (_a = result.effects) || void 0 === _a ? void 0 : _a.localOnly) && delete result.effects.localOnly,
(0, util_3.isUpdateSpecResultLocalOnly)(result) ? result : onlyComponentSpecsChanged && !componentUpdateResult.hasNonComponentOnlyUpdate && ((0,
util_3.isUpdateSpecResultComponentOnly)(result) || this._isComponentScaleDomainOnlyUpdate(result)) ? (componentUpdateResult.componentOnlyUpdatedComponents.forEach((component => {
component.reInit(component.getSpec());
})), (null === (_b = result.effects) || void 0 === _b ? void 0 : _b.layout) && this.setLayoutTag(!0, null, !1),
result) : (this.setLayoutTag(!0, null, !1), this.updateSeriesSpec(result), result.reMake || (this.reInit(),
onlyComponentOrSeriesSpecsChanged && this._canSkipChartDataStages(result) || (this.updateDataSpec(),
this.reDataFlow(), this._reRunStackDataFlow(), this.getAllModels().forEach((model => model.onDataUpdate())))),
result));
}
updateChartConfig(result, oldSpec) {
var _a, _b;
this._paddingSpec = (0, util_1.normalizeLayoutPaddingSpec)(null !== (_a = this._spec.padding) && void 0 !== _a ? _a : null === (_b = this._option) || void 0 === _b ? void 0 : _b.getTheme("padding")),
this._updateLayoutRect(this._viewBox);
}
updateDataSpec() {
this._spec.data && this._chartData.updateData(this._spec.data, !1, !0);
}
updateRegionSpec(result) {
var _a;
(null === (_a = this._spec) || void 0 === _a ? void 0 : _a.region) && (this._spec.region.length === this._regions.length ? this._regions.forEach((r => {
(0, util_3.mergeUpdateResult)(result, r.updateSpec(this._spec.region[r.getSpecIndex()]));
})) : result.reMake = !0);
}
updateComponentSpec(result) {
const componentOnlyUpdatedComponents = [];
let hasNonComponentOnlyUpdate = !1;
const componentCache = {}, checkVisibleComponents = {
[interface_1.ComponentTypeEnum.title]: !0,
[interface_1.ComponentTypeEnum.brush]: !0,
[interface_1.ComponentTypeEnum.indicator]: !0
}, removedComponents = [];
let hasNonLocalComponentRemoval = !1;
this._components.forEach((c => {
var _a, _b;
if (c.type === interface_1.ComponentTypeEnum.label || c.type === interface_1.ComponentTypeEnum.totalLabel) return void (c.getSpecInfo() || (removedComponents.push(c),
hasNonLocalComponentRemoval = !0, hasNonComponentOnlyUpdate = !0));
checkVisibleComponents[c.type] && (checkVisibleComponents[c.type] = !1);
const compSpecKey = c.specKey || c.type, cmpSpec = null !== (_a = this._spec[compSpecKey]) && void 0 !== _a ? _a : {};
if ((0, util_1.isArray)(cmpSpec)) {
if (componentCache[compSpecKey] = componentCache[compSpecKey] || {
specCount: cmpSpec.length,
componentCount: 0
}, this._canRemoveMarkerComponentsWithoutRemake(compSpecKey, [ c.getSpec() ], cmpSpec)) return void removedComponents.push(c);
componentCache[compSpecKey].componentCount++;
const componentSpec = null !== (_b = cmpSpec[c.getSpecIndex()]) && void 0 !== _b ? _b : {}, previousComponentSpec = c.getSpec(), componentResult = c.updateSpec(componentSpec, cmpSpec);
(0, util_3.isUpdateSpecResultComponentOnly)(componentResult) || this._isComponentScaleDomainOnlyUpdate(componentResult) ? componentOnlyUpdatedComponents.push(c) : (0,
vutils_1.isEqual)(previousComponentSpec, componentSpec) || (hasNonComponentOnlyUpdate = !0),
(0, util_3.mergeUpdateResult)(result, componentResult);
} else {
const previousComponentSpec = c.getSpec(), componentResult = c.updateSpec(cmpSpec);
(0, util_3.isUpdateSpecResultComponentOnly)(componentResult) || this._isComponentScaleDomainOnlyUpdate(componentResult) ? componentOnlyUpdatedComponents.push(c) : (0,
vutils_1.isEqual)(previousComponentSpec, cmpSpec) || (hasNonComponentOnlyUpdate = !0),
(0, util_3.mergeUpdateResult)(result, componentResult);
}
})), result.reMake || this._createMissingMarkerComponentsForSpecs(result, componentCache);
for (const key in componentCache) if (Object.prototype.hasOwnProperty.call(componentCache, key)) {
const element = componentCache[key];
element.componentCount !== element.specCount && (result.reMake = !0);
}
removedComponents.length && (removedComponents.forEach((component => {
this._removeComponent(component);
})), result.change = !0, result.effects = Object.assign(Object.assign(Object.assign({}, result.effects), {
component: !0
}), hasNonLocalComponentRemoval ? {
layout: !0,
render: !0
} : {
localOnly: !0
}));
const isVisible = compSpec => compSpec && !1 !== compSpec.visible;
return Object.keys(checkVisibleComponents).forEach((type => {
if (checkVisibleComponents[type]) {
const compSpec = this._spec[type];
((0, util_1.isArray)(compSpec) ? compSpec.some(isVisible) : isVisible(compSpec)) && (result.reMake = !0);
}
})), {
componentOnlyUpdatedComponents: componentOnlyUpdatedComponents,
hasNonComponentOnlyUpdate: hasNonComponentOnlyUpdate
};
}
_canChangeMarkerComponentsWithoutRemake(key, currentSpec, nextSpec) {
return this._canRemoveMarkerComponentsWithoutRemake(key, currentSpec, nextSpec) || this._canAddMarkerComponentsWithoutRemake(key, currentSpec, nextSpec);
}
_canAddMarkerComponentsWithoutRemake(key, currentSpec, nextSpec) {
return !!(MARKER_COMPONENT_SPEC_KEYS[key] && (0, util_1.isArray)(currentSpec) && (0,
util_1.isArray)(nextSpec)) && (!(nextSpec.length <= currentSpec.length) && nextSpec.slice(currentSpec.length).every(this._isMarkerAdditionSpecSafeWithoutRemake));
}
_isAutoRangeMarkerSpec(spec) {
return !!spec && "object" == typeof spec && !0 === spec.autoRange;
}
_canRemoveMarkerComponentsWithoutRemake(key, currentSpec, nextSpec) {
return MARKER_COMPONENT_SPEC_KEYS[key] && (0, util_1.isArray)(currentSpec) && currentSpec.length > 0 && (0,
util_1.isArray)(nextSpec) && 0 === nextSpec.length;
}
_isOnlyMarkerComponentsRemoved(currentSpec, nextSpec, specKeys) {
let hasMarkerRemoval = !1;
const onlyMarkerRemoval = specKeys.every((key => this._canRemoveMarkerComponentsWithoutRemake(key, currentSpec[key], nextSpec[key]) ? (hasMarkerRemoval = !0,
!0) : (0, vutils_1.isEqual)(currentSpec[key], nextSpec[key])));
return hasMarkerRemoval && onlyMarkerRemoval;
}
_isComponentSpecKey(key) {
return !!MARKER_COMPONENT_SPEC_KEYS[key] || this._components.some((component => (component.specKey || component.type) === key));
}
_isOnlyComponentSpecsChanged(currentSpec, nextSpec, specKeys) {
let hasComponentSpecChange = !1;
const currentSpecRecord = currentSpec, nextSpecRecord = nextSpec, onlyComponentSpecChange = specKeys.every((key => !!(0,
vutils_1.isEqual)(currentSpecRecord[key], nextSpecRecord[key]) || !!this._isComponentSpecKey(key) && (hasComponentSpecChange = !0,
!0)));
return hasComponentSpecChange && onlyComponentSpecChange;
}
_isOnlySeriesSpecsChanged(currentSpec, nextSpec, specKeys) {
var _a, _b;
let hasSeriesSpecChange = !1;
const currentSpecRecord = currentSpec, nextSpecRecord = nextSpec, seriesRelatedSpecKeys = null !== (_b = null === (_a = this._specTransformer) || void 0 === _a ? void 0 : _a.getSeriesRelatedSpecKeys()) && void 0 !== _b ? _b : {}, onlySeriesSpecChange = specKeys.every((key => !!(0,
vutils_1.isEqual)(currentSpecRecord[key], nextSpecRecord[key]) || !!seriesRelatedSpecKeys[key] && (hasSeriesSpecChange = !0,
!0)));
return hasSeriesSpecChange && onlySeriesSpecChange;
}
_isOnlyComponentOrSeriesSpecsChanged(currentSpec, nextSpec, specKeys) {
var _a, _b;
let hasComponentOrSeriesSpecChange = !1;
const currentSpecRecord = currentSpec, nextSpecRecord = nextSpec, seriesRelatedSpecKeys = null !== (_b = null === (_a = this._specTransformer) || void 0 === _a ? void 0 : _a.getSeriesRelatedSpecKeys()) && void 0 !== _b ? _b : {}, onlyComponentOrSeriesSpecChange = specKeys.every((key => !!(0,
vutils_1.isEqual)(currentSpecRecord[key], nextSpecRecord[key]) || !(!this._isComponentSpecKey(key) && !seriesRelatedSpecKeys[key]) && (hasComponentOrSeriesSpecChange = !0,
!0)));
return hasComponentOrSeriesSpecChange && onlyComponentOrSeriesSpecChange;
}
_canSkipChartDataStages(result) {
const effects = result.effects;
return !(!(null == effects ? void 0 : effects.series) || effects.remake || effects.data || effects.scaleDomain || result.reMake);
}
_isComponentScaleDomainOnlyUpdate(result) {
const effects = result.effects;
return !(!(null == effects ? void 0 : effects.component) || !effects.scaleDomain || result.reMake || result.reCompile || result.reSize || effects.remake || effects.compile || effects.data || effects.series || effects.animation || result.reTransformSpec || result.reAnimate || result.changeTheme || result.changeBackground);
}
_reRunStackDataFlow() {
var _a, _b;
this._series.some((series => {
var _a;
return null === (_a = series.getStack) || void 0 === _a ? void 0 : _a.call(series);
})) && (null === (_b = null === (_a = this._stack) || void 0 === _a ? void 0 : _a.stackAll) || void 0 === _b || _b.call(_a),
this._series.forEach((series => {
series.getViewDataFilter() && series.reTransformViewData();
})));
}
_getModelSpecIndex(specInfo) {
var _a;
const specPath = null !== (_a = specInfo.specPath) && void 0 !== _a ? _a : [], specIndex = specPath[specPath.length - 1];
return "number" == typeof specIndex ? specIndex : 0;
}
_hasComponentForSpecInfo(key, specInfo) {
const specIndex = this._getModelSpecIndex(specInfo);
return this._components.some((component => (component.specKey || component.type) === key && component.getSpecIndex() === specIndex));
}
_createMissingMarkerComponentsForSpecs(result, componentCache) {
var _a;
let createdCount = 0, hasAutoRangeMarker = !1;
null === (_a = this._specTransformer) || void 0 === _a || _a.forEachComponentInSpec(this._spec, ((constructor, specInfo) => {
if (result.reMake) return;
const compSpecKey = constructor.specKey || constructor.type;
MARKER_COMPONENT_SPEC_KEYS[compSpecKey] && !this._hasComponentForSpecInfo(compSpecKey, specInfo) && (this._isMarkerAdditionSpecSafeWithoutRemake(specInfo.spec) ? (this._createComponent(constructor, specInfo),
componentCache[compSpecKey] && componentCache[compSpecKey].componentCount++, createdCount++,
hasAutoRangeMarker = hasAutoRangeMarker || this._isAutoRangeMarkerSpec(specInfo.spec)) : result.reMake = !0);
}), this._option.getSpecInfo()), createdCount && (result.change = !0, result.effects = Object.assign(Object.assign(Object.assign(Object.assign({}, result.effects), {
component: !0
}), hasAutoRangeMarker ? {
scaleDomain: !0
} : null), {
layout: !0,
render: !0
}));
}
_removeMarkerComponentsForEmptySpecs(result) {
const removedComponents = this._components.filter((component => {
var _a;
const compSpecKey = component.specKey || component.type, cmpSpec = null !== (_a = this._spec[compSpecKey]) && void 0 !== _a ? _a : {};
return this._canRemoveMarkerComponentsWithoutRemake(compSpecKey, [ component.getSpec() ], cmpSpec);
}));
removedComponents.length && (removedComponents.forEach((component => {
this._removeComponent(component);
})), result.change = !0, result.effects = Object.assign(Object.assign({}, result.effects), {
component: !0,
localOnly: !0
}));
}
_removeComponent(component) {
this._components = this._components.filter((c => c !== component)), this._idMap.delete(component.id),
component.getMarks().forEach((mark => {
this.getCompiler().removeRootMark(mark);
})), component.release();
}
updateSeriesSpec(result) {
this._spec.series.length === this._series.length ? this._series.forEach((s => {
const spec = this._spec.series[s.getSpecIndex()];
(0, util_3.mergeUpdateResult)(result, s.updateSpec(spec));
})) : result.reMake = !0;
}
getCanvas() {
var _a, _b;
return null !== (_b = null === (_a = this.getCompiler()) || void 0 === _a ? void 0 : _a.getCanvas()) && void 0 !== _b ? _b : null;
}
_updateLayoutRect(viewBox) {
let viewRect = this.getCanvasRect();
if (viewBox) {
this._viewBox = viewBox;
const {x1: x1 = 0, y1: y1 = 0, x2: x2, y2: y2} = viewBox;
viewRect = {
width: x2 - x1,
height: y2 - y1
};
} else this._viewBox = {
x1: 0,
y1: 0,
x2: viewRect.width,
y2: viewRect.height
};
this._viewRect = viewRect, this.padding = (0, util_1.calcPadding)(this._paddingSpec, viewRect, viewRect),
this._layoutRect.width = viewRect.width - this.padding.left - this.padding.right,
this._layoutRect.height = viewRect.height - this.padding.top - this.padding.bottom,
this._layoutRect.x = this.padding.left, this._layoutRect.y = this.padding.top, this._event.emit(event_2.ChartEvent.layoutRectUpdate, {
chart: this
});
}
setCurrentTheme() {
this.updateChartConfig({
change: !0,
reMake: !1
}, this._spec), this.resetLayoutItemTag(), this.setLayoutTag(!0, null, !1), this.updateGlobalScaleTheme(),
this.reInit();
}
reInit() {
[ ...this._regions, ...this._series, ...this._components ].forEach((model => {
const specInfo = model.getSpecInfo();
specInfo && specInfo.spec && model.reInit(specInfo.spec);
}));
}
clear() {
this.getAllModels().forEach((i => {
var _a;
return null === (_a = i.clear) || void 0 === _a ? void 0 : _a.call(i);
}));
}
compile() {
this.compileBackground(), this.compileLayout(), this.compileRegions(), this.compileSeries(),
this.compileComponents();
}
afterCompile() {
this.getAllRegions().forEach((r => {
var _a;
null === (_a = r.afterCompile) || void 0 === _a || _a.call(r);
})), this.getAllSeries().forEach((s => {
var _a;
null === (_a = s.afterCompile) || void 0 === _a || _a.call(s);
})), this.getAllComponents().forEach((c => {
var _a;
null === (_a = c.afterCompile) || void 0 === _a || _a.call(c);
}));
}
compileLayout() {
const {width: width, height: height} = this.getCanvasRect();
this.getCompiler().setSize(width, height);
}
compileBackground() {
this._backgroundMark && this._backgroundMark.compile();
}
compileRegions() {
var _a, _b, _c, _d;
null === (_b = null === (_a = this._option.performanceHook) || void 0 === _a ? void 0 : _a.beforeRegionCompile) || void 0 === _b || _b.call(_a, this._option.globalInstance),
this.getAllRegions().forEach((r => {
r.compile();
})), null === (_d = null === (_c = this._option.performanceHook) || void 0 === _c ? void 0 : _c.afterRegionCompile) || void 0 === _d || _d.call(_c, this._option.globalInstance);
}
compileSeries() {
var _a, _b, _c, _d;
null === (_b = null === (_a = this._option.performanceHook) || void 0 === _a ? void 0 : _a.beforeSeriesCompile) || void 0 === _b || _b.call(_a, this._option.globalInstance),
this.getAllSeries().forEach((s => {
s.compile();
})), null === (_d = null === (_c = this._option.performanceHook) || void 0 === _c ? void 0 : _c.afterSeriesCompile) || void 0 === _d || _d.call(_c, this._option.globalInstance);
}
compileComponents() {
var _a, _b, _c, _d;
null === (_b = null === (_a = this._option.performanceHook) || void 0 === _a ? void 0 : _a.beforeComponentCompile) || void 0 === _b || _b.call(_a, this._option.globalInstance),
this.getAllComponents().forEach((c => {
c.compile();
})), null === (_d = null === (_c = this._option.performanceHook) || void 0 === _c ? void 0 : _c.afterComponentCompile) || void 0 === _d || _d.call(_c, this._option.globalInstance);
}
release(forceReleaseVRenderComponents = !0) {
forceReleaseVRenderComponents && [ ...this._components, ...this._regions, ...this._series ].forEach((m => {
m.beforeRelease();
})), this._event.release(), super.release(), this.clear(), [ ...this._components, ...this._regions, ...this._series ].forEach((m => {
m.release();
})), this._components = this._regions = this._series = [], this._spec = {}, this._dataSet = this._globalScale = this._layoutFunc = null,
this._layoutTag = !1, this._idMap.clear();
}
onLayout() {
this.layout();
}
updateState(state, filter) {
const seriesArr = this.getAllSeries();
for (const key in state) {
if ((0, vutils_1.isEmpty)(state[key])) continue;
const stateSpec = state[key];
let stateInfo = {
stateValue: key
};
stateInfo = (0, vutils_1.isFunction)(stateSpec.filter) ? Object.assign({
filter: stateSpec.filter
}, stateInfo) : Object.assign(Object.assign({}, stateSpec.filter), stateInfo), stateSpec.level && (stateInfo.level = stateSpec.level),
seriesArr.forEach((series => {
series.getMarks().forEach((m => {
m.stateStyle[key] && (filter && !filter(series, m, key) || (m.state.changeStateInfo(stateInfo),
m.updateMarkState(key)));
}));
}));
}
}
setSelected(datum, filter, region) {
this._setStateInDatum(interface_2.STATE_VALUE_ENUM.STATE_SELECTED, datum, filter, region);
}
setHovered(datum, filter, region) {
this._setStateInDatum(interface_2.STATE_VALUE_ENUM.STATE_HOVER, datum, filter, region);
}
clearState(state) {
this._interaction.clearByState(state);
}
clearAllStates() {
this._interaction.clearAllStates();
}
clearSelected() {
this.clearState(interface_2.STATE_VALUE_ENUM.STATE_SELECTED);
}
clearHovered() {
this.clearState(interface_2.STATE_VALUE_ENUM.STATE_HOVER);
}
_initEvent() {
[ event_2.ChartEvent.dataZoomChange, event_2.ChartEvent.scrollBarChange ].forEach((event => {
this._event.on(event, (({value: value}) => {
this._disableMarkAnimation([ "exit", "update" ]);
const enableMarkAnimate = () => {
this._enableMarkAnimation([ "exit", "update" ]), this._event.off(event_2.HOOK_EVENT.AFTER_MARK_RENDER_END, enableMarkAnimate);
};
this._event.on(event_2.HOOK_EVENT.AFTER_MARK_RENDER_END, enableMarkAnimate);
}));
}));
}
_enableMarkAnimation(states) {
this.getAllMarks().forEach((mark => mark.enableAnimationByState(states)));
}
_disableMarkAnimation(states) {
this.getAllMarks().forEach((mark => mark.disableAnimationByState(states)));
}
filterGraphicsByDatum(datum, opt = {}) {
var _a;
const keys = (datum = datum ? (0, util_1.array)(datum) : null) ? Object.keys(datum[0]) : null, allElements = [], getDatumOfElement = null !== (_a = opt.getDatum) && void 0 !== _a ? _a : util_1.getDatumOfGraphic;
return this.getRegionsInQuerier(opt.region).forEach((r => {
const pickElements = [];
datum && r.getSeries().forEach((s => {
s.getMarks().forEach((m => {
const graphics = m.getGraphics();
if (graphics && graphics.length && (!opt.filter || (0, vutils_1.isFunction)(opt.filter) && opt.filter(s, m))) {
if ((0, util_1.isCollectionMark)(m.type)) graphics.filter((e => {
const elDatum = getDatumOfElement(e, m, s, r);
elDatum && datum.every(((d, index) => keys.every((k => d[k] == elDatum[index][k])))) && (pickElements.push(e),
allElements.push(e), opt.callback && opt.callback(e, m, s, r));
})); else if (datum.length > 1) {
const datumTemp = datum.slice();
graphics.forEach((e => {
const elDatum = getDatumOfElement(e, m, s, r), index = elDatum && datumTemp.findIndex((d => keys.every((k => d[k] == elDatum[k]))));
index >= 0 && (datumTemp.splice(index, 1), pickElements.push(e), allElements.push(e),
opt.callback && opt.callback(e, m, s, r));
}));
} else {
const el = graphics.find((e => {
const elDatum = getDatumOfElement(e, m, s, r);
return elDatum && keys.every((k => datum[0][k] == elDatum[k]));
}));
el && (pickElements.push(el), allElements.push(el), opt.callback && opt.callback(el, m, s, r));
}
}
}));
})), opt.regionCallback && opt.regionCallback(pickElements, r);
})), allElements;
}
_setStateInDatum(stateKey, d, filter, region) {
if (!d) return void this._interaction.clearByState(stateKey);
const pickGraphics = this.filterGraphicsByDatum(d, {
filter: filter,
region: region
});
this._interaction.updateStateOfGraphics(stateKey, pickGraphics);
}
setDimensionIndex(value, opt) {
var _a, _b;
let dimensionInfo = null;
Array.from(this._event.getComposedEventMap().values()).forEach((e => {
const {eventType: eventType, event: event} = e;
if (eventType === interface_3.DimensionEventEnum.dimensionHover || eventType === interface_3.DimensionEventEnum.dimensionClick) {
const info = event.dispatch(value, opt);
(null == info ? void 0 : info.length) && (dimensionInfo = info);
}
}));
const isUnableValue = (0, vutils_1.isNil)(value) || !dimensionInfo || dimensionInfo.every((d => (0,
vscale_1.isDiscrete)(d.axis.getScale().type) && (0, vutils_1.isNil)(d.index))), isUnableTooltip = isUnableValue || dimensionInfo.every((d => (0,
vscale_1.isDiscrete)(d.axis.getScale().type) && d.data.every((_data => 0 === _data.datum.length))));
if (!1 !== opt.tooltip) {
const tooltip = this.getComponentsByType(interface_1.ComponentTypeEnum.tooltip)[0];
if (null == tooltip ? void 0 : tooltip.getVisible()) if (isUnableValue || isUnableTooltip) null === (_b = (_a = tooltip).hideTooltip) || void 0 === _b || _b.call(_a); else {
const dataFilter = {};
dimensionInfo.forEach((d => {
const {axis: axis, value: value, data: data} = d, isY = "left" === axis.getOrient() || "right" === axis.getOrient();
data.forEach((d => {
var _a, _b, _c;
const field = isY ? d.series.fieldY[0] : d.series.fieldX[0];
dataFilter[field] = null !== (_c = null === (_b = null === (_a = d.datum) || void 0 === _a ? void 0 : _a[0]) || void 0 === _b ? void 0 : _b[field]) && void 0 !== _c ? _c : value;
}));
})), tooltip.showTooltip(dataFilter, opt.showTooltipOption);
}
}
if (!1 !== opt.crosshair) {
const crosshair = this.getComponentsByType(interface_1.ComponentTypeEnum.cartesianCrosshair)[0];
crosshair && crosshair.clearAxisValue && crosshair.setAxisValue && (isUnableValue ? crosshair.hideCrosshair() : crosshair.showCrosshair(dimensionInfo));
}
}
showCrosshair(cb) {
var _a;
const crosshair = null !== (_a = this.getComponentsByType(interface_1.ComponentTypeEnum.cartesianCrosshair)[0]) && void 0 !== _a ? _a : this.getComponentsByType(interface_1.ComponentTypeEnum.polarCrosshair)[0];
if (!crosshair) return;
const axes = this.getComponentsByKey("axes"), dimInfo = [];
axes.forEach((axis => {
const value = cb(axis);
!1 !== value && dimInfo.push({
axis: axis,
value: value
});
})), crosshair.showCrosshair(dimInfo);
}
getColorScheme() {
var _a, _b;
return null === (_b = (_a = this._option).getTheme) || void 0 === _b ? void 0 : _b.call(_a, "colorScheme");
}
}
exports.BaseChart = BaseChart;
//# sourceMappingURL=base-chart.js.map