@visactor/vchart
Version:
charts lib based @visactor/VGrammar
965 lines (919 loc) • 48.7 kB
JavaScript
var __awaiter = this && this.__awaiter || function(thisArg, _arguments, P, generator) {
return new (P || (P = Promise))((function(resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
}
function step(result) {
var value;
result.done ? resolve(result.value) : (value = result.value, value instanceof P ? value : new P((function(resolve) {
resolve(value);
}))).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
}));
}, __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;
};
import { arrayParser } from "../data/parser/array";
import { RenderModeEnum } from "../typings/spec/common";
import { ComponentTypeEnum } from "../component/interface/type";
import { DataSet, dataViewParser, DataView } from "@visactor/vdataset";
import { vglobal } from "@visactor/vrender-core";
import { isString, isValid, isNil, array, specTransform, functionTransform } from "../util";
import { createID } from "../util/id";
import { convertPoint } from "../util/space";
import { isTrueBrowser } from "../util/env";
import { warn } from "../util/debug";
import { getThemeObject } from "../util/theme/common";
import { mergeSpec, mergeSpecWithFilter } from "@visactor/vutils-extension";
import { Factory } from "./factory";
import { Event } from "../event/event";
import { EventDispatcher } from "../event/event-dispatcher";
import { getMapSource } from "../series/map/geo-source";
import { registerDataSetInstanceParser, registerDataSetInstanceTransform } from "../data/register";
import { dataToDataView } from "../data/initialize";
import { copyDataView } from "../data/transforms/copy-data-view";
import { AnimationStateEnum } from "../animation/interface";
import { ThemeManager } from "../theme/theme-manager";
import { Compiler } from "../compile/compiler";
import { getCanvasDataURL, URLToImage } from "../util/image";
import { ChartEvent } from "../constant/event";
import { DEFAULT_CHART_HEIGHT, DEFAULT_CHART_WIDTH } from "../constant/base";
import { isArray, isEmpty, Logger, isFunction, LoggerLevel, isEqual, cloneDeep, isObject, throttle } from "@visactor/vutils";
import { InstanceManager } from "./instance-manager";
import { setPoptipTheme } from "@visactor/vrender-components";
import { calculateChartSize, mergeUpdateResult } from "../chart/util";
import { Region } from "../region/region";
import { Layout } from "../layout/base-layout";
import { registerGroupMark } from "../mark/group";
import { VCHART_UTILS } from "./util";
import { ExpressionFunction } from "./expression-function";
import { registerBrowserEnv, registerNodeEnv } from "../env";
import { mergeTheme, preprocessTheme } from "../util/theme";
import { darkTheme, registerTheme } from "../theme/builtin";
import { ChartPluginService } from "../plugin/chart/plugin-service";
import { registerGesturePlugin } from "../plugin/other";
import { registerElementHighlight } from "../interaction/triggers/element-highlight";
import { registerElementSelect } from "../interaction/triggers/element-select";
export class VChart {
static useRegisters(comps) {
comps.forEach((fn => {
"function" == typeof fn ? fn() : console.error("Invalid function:", fn);
}));
}
static useChart(charts) {
charts.forEach((c => Factory.registerChart(c.type, c)));
}
static useSeries(series) {
series.forEach((s => Factory.registerSeries(s.type, s)));
}
static useComponent(components) {
components.forEach((c => Factory.registerComponent(c.type, c)));
}
static useMark(marks) {
marks.forEach((m => {
var _a;
return Factory.registerMark(null !== (_a = m.constructorType) && void 0 !== _a ? _a : m.type, m);
}));
}
static useLayout(layouts) {
layouts.forEach((l => Factory.registerLayout(l.type, l)));
}
static registerDataSetTransform(name, transform) {
Factory.registerTransform(name, transform);
}
static registerFunction(key, fun) {
key && fun && ExpressionFunction.instance().registerFunction(key, fun);
}
static unregisterFunction(key) {
key && ExpressionFunction.instance().unregisterFunction(key);
}
static getFunction(key) {
return key ? ExpressionFunction.instance().getFunction(key) : null;
}
static getFunctionList() {
return ExpressionFunction.instance().getFunctionNameList();
}
static registerMap(key, source, option) {
const impl = Factory.getImplementInKey("registerMap");
impl && impl(key, source, option);
}
static unregisterMap(key) {
const impl = Factory.getImplementInKey("unregisterMap");
impl && impl(key);
}
static getMap(key) {
return getMapSource(key);
}
static registerSVG(key, source, option) {
const impl = Factory.getImplementInKey("registerSVG");
impl && impl(key, source, option);
}
static unregisterSVG(key) {
const impl = Factory.getImplementInKey("unregisterSVG");
impl && impl(key);
}
static hideTooltip(excludeId = []) {
InstanceManager.forEach((instance => {
var _a;
return null === (_a = null == instance ? void 0 : instance.hideTooltip) || void 0 === _a ? void 0 : _a.call(instance);
}), excludeId);
}
static getLogger() {
return Logger.getInstance();
}
getSpec() {
return this._spec;
}
getSpecInfo() {
return this._specInfo;
}
getDataSet() {
return this._dataSet;
}
constructor(spec, options) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
this.id = createID(), this._userEvents = [], this._autoSize = !0, this._option = {
mode: RenderModeEnum["desktop-browser"],
onError: msg => {
throw new Error(msg);
},
optimize: {
disableCheckGraphicWidthOutRange: !0
}
}, this._observer = null, this._context = {}, this._doResize = () => {
const {width: width, height: height} = this.getCurrentSize();
this._currentSize.width === width && this._currentSize.height === height || (this._currentSize = {
width: width,
height: height
}, this.resizeSync(width, height));
}, this._renderSync = (option = {}) => {
var _a;
const self = this;
return this._beforeRender(option) ? (this._updateAnimateState(!0), null === (_a = this._compiler) || void 0 === _a || _a.render(option.morphConfig),
this._updateAnimateState(!1), this._afterRender(), self) : self;
}, this._updateSpec = (spec, forceMerge = !1, userUpdateOptions) => {
var _a;
const lastSpec = this._spec, result = {
changeBackground: !1,
reTransformSpec: !1,
change: !1,
reMake: !1,
reCompile: !1,
reSize: !1,
changeTheme: !1
};
if (!this._setNewSpec(spec, forceMerge)) return;
isEqual(lastSpec.theme, this._spec.theme) ? isEqual(this._spec.background, lastSpec.background) || (result.reMake = !0,
result.changeBackground = !0) : result.changeTheme = !0;
const reSize = this._shouldChartResize(lastSpec);
if (result.reSize = reSize, this._spec.type !== lastSpec.type) return null === (_a = this._compiler) || void 0 === _a || _a.updateLayoutTag(),
result.reMake = !0, result.reTransformSpec = !0, result.change = !0, result.changeTheme = !0,
result;
this._initChartSpec(this._spec, "updateSpec");
const res = mergeUpdateResult(this._chart.updateSpec(this._spec), result);
return userUpdateOptions ? Object.assign(Object.assign({}, res), userUpdateOptions) : res;
}, this.getTheme = (...keys) => {
if (!this._currentTheme || !keys || !keys.length) return;
this._cachedProcessedTheme || (this._cachedProcessedTheme = {});
const cacheKey = keys.join(".");
if (this._cachedProcessedTheme[cacheKey]) return this._cachedProcessedTheme[cacheKey];
let theme = this._currentTheme;
return keys.forEach(((key, index) => {
if (1 !== index || "series" !== keys[0] && "component" !== keys[0]) theme = null == theme ? void 0 : theme[key]; else {
const buildInTheme = "series" === keys[0] ? Factory.getSeriesBuiltInTheme(key) : Factory.getComponentBuiltInTheme(key);
theme = theme ? mergeSpec({}, buildInTheme, theme[key]) : buildInTheme;
}
index === keys.length - 1 && isValid(theme) && (theme = preprocessTheme({
[key]: theme
}, this._currentTheme.colorScheme, this._currentTheme.token)[key]);
})), this._cachedProcessedTheme[cacheKey] = theme, theme;
}, this._option = Object.assign(Object.assign(Object.assign({}, this._option), {
animation: !1 !== spec.animation
}), options), (null == options ? void 0 : options.optimize) && (this._option.optimize = Object.assign(Object.assign({}, this._option.optimize), options.optimize)),
this._onError = null === (_a = this._option) || void 0 === _a ? void 0 : _a.onError;
const _k = this._option, {dom: dom, renderCanvas: renderCanvas, mode: mode, stage: stage, poptip: poptip} = _k, restOptions = __rest(_k, [ "dom", "renderCanvas", "mode", "stage", "poptip" ]), isTrueBrowseEnv = isTrueBrowser(mode);
if (isTrueBrowseEnv ? registerBrowserEnv() : "node" === mode && registerNodeEnv(),
isTrueBrowseEnv && dom && (this._container = isString(dom) ? vglobal.getElementById(dom) : dom),
renderCanvas && (this._canvas = renderCanvas), stage && (this._stage = stage), "node" !== mode && !this._container && !this._canvas && !this._stage) return void (null === (_b = this._option) || void 0 === _b || _b.onError("please specify container or renderCanvas!"));
this._viewBox = this._option.viewBox, this._currentThemeName = ThemeManager.getCurrentThemeName(),
this._setNewSpec(spec), this._updateCurrentTheme(), this._currentSize = this.getCurrentSize();
const pluginList = [];
!1 !== poptip && pluginList.push("poptipForText"), "sankey" === spec.type && pluginList.push("scrollbar");
const logger = new Logger(null !== (_c = this._option.logLevel) && void 0 !== _c ? _c : LoggerLevel.Error);
Logger.setInstance(logger), (null === (_d = this._option) || void 0 === _d ? void 0 : _d.onError) && logger.addErrorHandler(((...args) => {
var _a, _b;
null === (_b = null === (_a = this._option) || void 0 === _a ? void 0 : _a.onError) || void 0 === _b || _b.call(_a, ...args);
})), this._compiler = new Compiler({
dom: null !== (_e = this._container) && void 0 !== _e ? _e : "none",
canvas: renderCanvas
}, Object.assign(Object.assign({
mode: this._option.mode,
stage: stage,
pluginList: pluginList
}, restOptions), {
background: this._getBackground(),
onError: this._onError
})), this._compiler.setSize(this._currentSize.width, this._currentSize.height),
this._eventDispatcher = new EventDispatcher(this, this._compiler), this._event = new Event(this._eventDispatcher, mode),
this._compiler.initView(), this._compiler.updateLayoutTag(), this._setFontFamilyTheme(this.getTheme("fontFamily")),
this._initDataSet(this._option.dataSet), this._autoSize = !!isTrueBrowseEnv && (null === (_g = null !== (_f = spec.autoFit) && void 0 !== _f ? _f : this._option.autoFit) || void 0 === _g || _g),
this._bindResizeEvent(), this._bindViewEvent(), this._initChartPlugin(), InstanceManager.registerInstance(this),
null === (_j = null === (_h = this._option.performanceHook) || void 0 === _h ? void 0 : _h.afterCreateVChart) || void 0 === _j || _j.call(_h, this);
}
_setNewSpec(spec, forceMerge) {
return !!spec && (isString(spec) && (spec = JSON.parse(spec)), forceMerge && this._originalSpec && (spec = mergeSpec({}, this._originalSpec, spec)),
this._originalSpec = spec, this._spec = this._getSpecFromOriginalSpec(), !0);
}
_getSpecFromOriginalSpec() {
var _a;
const spec = specTransform(this._originalSpec);
return spec.data = null !== (_a = spec.data) && void 0 !== _a ? _a : [], spec;
}
_initChartSpec(spec, actionSource) {
var _a, _b;
VChart.getFunctionList() && VChart.getFunctionList().length && (spec = functionTransform(spec, VChart)),
this._spec = spec, this._chartSpecTransformer || (this._chartSpecTransformer = Factory.createChartSpecTransformer(this._spec.type, this._getChartOption(this._spec.type))),
null === (_a = this._chartSpecTransformer) || void 0 === _a || _a.transformSpec(this._spec),
this._chartPluginApply("onAfterChartSpecTransform", this._spec, actionSource), this._specInfo = null === (_b = this._chartSpecTransformer) || void 0 === _b ? void 0 : _b.transformModelSpec(this._spec),
this._chartPluginApply("onAfterModelSpecTransform", this._spec, this._specInfo, actionSource);
}
_updateSpecInfo() {
var _a;
this._chartSpecTransformer || (this._chartSpecTransformer = Factory.createChartSpecTransformer(this._spec.type, this._getChartOption(this._spec.type))),
this._specInfo = null === (_a = this._chartSpecTransformer) || void 0 === _a ? void 0 : _a.createSpecInfo(this._spec);
}
_initChart(spec) {
var _a, _b, _c;
if (!this._compiler) return void (null === (_a = this._option) || void 0 === _a || _a.onError("compiler is not initialized"));
if (this._chart) return void (null === (_b = this._option) || void 0 === _b || _b.onError("chart is already initialized"));
const chart = Factory.createChart(spec.type, spec, this._getChartOption(spec.type));
chart ? (this._chart = chart, this._chart.setCanvasRect(this._currentSize.width, this._currentSize.height),
this._chart.created(this._chartSpecTransformer), this._chart.init(), this._event.emit(ChartEvent.initialized, {
chart: chart,
vchart: this
})) : null === (_c = this._option) || void 0 === _c || _c.onError("init chart fail");
}
_releaseData() {
this._dataSet && (this._dataSet.dataViewMap = {}, this._dataSet = null);
}
_bindViewEvent() {
var _a, _b;
this._compiler && (null === (_b = null === (_a = this._compiler.getStage()) || void 0 === _a ? void 0 : _a.getTimeline()) || void 0 === _b || _b.on("animationEnd", (() => {
this._event.emit(ChartEvent.animationFinished, {
chart: this._chart,
vchart: this
});
})));
}
_bindResizeEvent() {
var _a, _b;
if (this._autoSize) {
if (this._onResize = throttle(this._doResize, null !== (_a = this._option.resizeDelay) && void 0 !== _a ? _a : 100),
this._container) {
const ResizeObserverWindow = window.ResizeObserver;
ResizeObserverWindow && (this._observer = new ResizeObserverWindow(this._onResize),
null === (_b = this._observer) || void 0 === _b || _b.observe(this._container));
}
window.addEventListener("resize", this._onResize);
}
}
_unBindResizeEvent() {
this._autoSize && (window.removeEventListener("resize", this._onResize), this._observer && (this._observer.disconnect(),
this._observer = null));
}
getCurrentSize() {
var _a, _b, _c, _d;
return calculateChartSize(this._spec, {
container: this._container,
canvas: this._canvas,
mode: this._getMode(),
modeParams: this._option.modeParams
}, {
width: null !== (_b = null === (_a = this._currentSize) || void 0 === _a ? void 0 : _a.width) && void 0 !== _b ? _b : DEFAULT_CHART_WIDTH,
height: null !== (_d = null === (_c = this._currentSize) || void 0 === _c ? void 0 : _c.height) && void 0 !== _d ? _d : DEFAULT_CHART_HEIGHT
});
}
_initDataSet(dataSet) {
this._dataSet = dataSet instanceof DataSet ? dataSet : new DataSet, registerDataSetInstanceParser(this._dataSet, "dataview", dataViewParser),
registerDataSetInstanceParser(this._dataSet, "array", arrayParser), registerDataSetInstanceTransform(this._dataSet, "copyDataView", copyDataView);
for (const key in Factory.transforms) registerDataSetInstanceTransform(this._dataSet, key, Factory.transforms[key]);
for (const key in Factory.dataParser) registerDataSetInstanceParser(this._dataSet, key, Factory.dataParser[key]);
}
updateCustomConfigAndRerender(updateSpecResult, sync, option = {}) {
if (!this._isReleased && updateSpecResult) return isFunction(updateSpecResult) && (updateSpecResult = updateSpecResult()),
updateSpecResult.reAnimate && (this.stopAnimation(), this._updateAnimateState(!0)),
this._reCompile(updateSpecResult), sync ? this._renderSync(option) : this._renderAsync(option);
}
_updateCustomConfigAndRecompile(updateSpecResult, option = {}) {
return !!updateSpecResult && (this._reCompile(updateSpecResult), this._beforeRender(option));
}
_reCompile(updateResult, morphConfig) {
var _a, _b, _c, _d, _e;
if (updateResult.reMake && (this._releaseData(), this._initDataSet(), null === (_a = this._chart) || void 0 === _a || _a.release(),
this._chart = null), updateResult.reTransformSpec && (this._chartSpecTransformer = null),
updateResult.changeTheme ? (this._setCurrentTheme(), this._setFontFamilyTheme(this.getTheme("fontFamily"))) : updateResult.changeBackground && (null === (_b = this._compiler) || void 0 === _b || _b.setBackground(this._getBackground())),
updateResult.reMake) null === (_c = this._compiler) || void 0 === _c || _c.releaseGrammar(),
this._userEvents.forEach((e => {
var _a;
return null === (_a = this._event) || void 0 === _a ? void 0 : _a.on(e.eType, e.query, e.handler);
})), updateResult.reSize && this._doResize(); else if (updateResult.reCompile && (null === (_d = this._compiler) || void 0 === _d || _d.clear({
chart: this._chart,
vChart: this
}), null === (_e = this._compiler) || void 0 === _e || _e.compile({
chart: this._chart,
vChart: this
})), updateResult.reSize) {
const {width: width, height: height} = this.getCurrentSize();
this._chart.onResize(width, height, !1), this._compiler.resize(width, height, !1);
}
}
_beforeRender(option = {}) {
var _a, _b, _c, _d, _e, _f, _g, _h;
if (this._isReleased) return !1;
if (this._chart) return !0;
const {transformSpec: transformSpec, actionSource: actionSource} = option;
return transformSpec && this._initChartSpec(this._spec, "render"), this._chartPluginApply("onBeforeInitChart", this._spec, actionSource),
null === (_b = null === (_a = this._option.performanceHook) || void 0 === _a ? void 0 : _a.beforeInitializeChart) || void 0 === _b || _b.call(_a, this),
this._initChart(this._spec), null === (_d = null === (_c = this._option.performanceHook) || void 0 === _c ? void 0 : _c.afterInitializeChart) || void 0 === _d || _d.call(_c, this),
!(!this._chart || !this._compiler) && (null === (_f = null === (_e = this._option.performanceHook) || void 0 === _e ? void 0 : _e.beforeCompileToVGrammar) || void 0 === _f || _f.call(_e, this),
this._compiler.compile({
chart: this._chart,
vChart: this
}, option), null === (_h = null === (_g = this._option.performanceHook) || void 0 === _g ? void 0 : _g.afterCompileToVGrammar) || void 0 === _h || _h.call(_g, this),
!0);
}
_afterRender() {
return !this._isReleased && (this._event.emit(ChartEvent.rendered, {
chart: this._chart,
vchart: this
}), !0);
}
renderSync(morphConfig) {
return this._renderSync({
morphConfig: morphConfig,
transformSpec: !0,
actionSource: "render"
});
}
renderAsync(morphConfig) {
return __awaiter(this, void 0, void 0, (function*() {
return this._renderAsync({
morphConfig: morphConfig,
transformSpec: !0,
actionSource: "render"
});
}));
}
_renderAsync(option = {}) {
return __awaiter(this, void 0, void 0, (function*() {
return this._renderSync(option);
}));
}
_updateAnimateState(initial) {
if (this._option.animation) {
const updateGraphicAnimationState = graphic => {
var _a;
const diffState = null === (_a = graphic.context) || void 0 === _a ? void 0 : _a.diffState;
return initial ? "exit" === diffState ? void 0 : AnimationStateEnum.appear : diffState;
};
this._compiler.getRootMarks().forEach((mark => {
mark.updateAnimationState(updateGraphicAnimationState);
}));
}
}
release() {
var _a, _b, _c, _d;
(null === (_a = this._onResize) || void 0 === _a ? void 0 : _a.cancel) && this._onResize.cancel(),
this._chartPluginApply("releaseAll"), this._chartPlugin = null, this._chartSpecTransformer = null,
null === (_b = this._chart) || void 0 === _b || _b.release(), null === (_c = this._eventDispatcher) || void 0 === _c || _c.release(),
null === (_d = this._compiler) || void 0 === _d || _d.release(), this._unBindResizeEvent(),
this._releaseData(), this._onError = null, this._onResize = null, this._container = null,
this._currentTheme = null, this._cachedProcessedTheme = null, this._option = null,
this._chart = null, this._compiler = null, this._spec = null, this._specInfo = null,
this._originalSpec = null, this._userEvents = null, this._event = null, this._eventDispatcher = null,
this._isReleased = !0, InstanceManager.unregisterInstance(this);
}
updateData(id, data, parserOptions, userUpdateOptions) {
return __awaiter(this, void 0, void 0, (function*() {
return this.updateDataSync(id, data, parserOptions, userUpdateOptions);
}));
}
_updateDataById(id, data, parserOptions) {
const preDV = this._spec.data.find((dv => dv.name === id || dv.id === id));
preDV ? preDV.id === id ? preDV.values = data : preDV.name === id && preDV.parse(data, parserOptions) : isArray(data) ? this._spec.data.push({
id: id,
values: data
}) : this._spec.data.push(data);
}
updateDataInBatches(list) {
return __awaiter(this, void 0, void 0, (function*() {
return this._chart ? (this._chart.updateFullData(list.map((({id: id, data: data, options: options}) => ({
id: id,
values: data,
parser: options
})))), this._chart.updateGlobalScaleDomain(), this._compiler.render(), this) : (this._spec.data = array(this._spec.data),
list.forEach((({id: id, data: data, options: options}) => {
this._updateDataById(id, data, options);
})), this);
}));
}
updateDataSync(id, data, parserOptions, userUpdateOptions) {
return isNil(this._dataSet) ? this : this._chart ? (this._chart.updateData(id, data, !0, parserOptions),
this._compiler.render(), (null == userUpdateOptions ? void 0 : userUpdateOptions.reAnimate) && (this.stopAnimation(),
this._updateAnimateState(!0)), this) : (this._spec.data = array(this._spec.data),
this._updateDataById(id, data, parserOptions), this);
}
updateFullDataSync(data, reRender = !0, userUpdateOptions) {
if (this._chart) return this._chart.updateFullData(data), reRender && (this._compiler.render(),
(null == userUpdateOptions ? void 0 : userUpdateOptions.reAnimate) && (this.stopAnimation(),
this._updateAnimateState(!0))), this;
const prevData = array(this._spec.data);
return array(data).forEach((d => {
const {id: id, values: values, parser: parser, fields: fields} = d, preDV = prevData.find((dv => dv.name === id));
if (preDV) preDV instanceof DataView ? (preDV.setFields(cloneDeep(fields)), preDV.parse(values, cloneDeep(parser))) : (preDV.values = values,
isValid(parser) && (preDV.parser = parser), isValid(fields) && (preDV.fields = fields)); else {
const dataView = dataToDataView(d, this._dataSet, prevData);
isArray(this._spec.data) && this._spec.data.push(dataView);
}
})), this;
}
updateFullData(data, reRender = !0) {
return __awaiter(this, void 0, void 0, (function*() {
return this.updateFullDataSync(data, reRender);
}));
}
updateSpec(spec, forceMerge = !1, morphConfig, userUpdateOptions) {
return __awaiter(this, void 0, void 0, (function*() {
const result = this._updateSpec(spec, forceMerge, userUpdateOptions);
return result ? (yield this.updateCustomConfigAndRerender(result, !1, {
morphConfig: morphConfig,
transformSpec: result.reTransformSpec,
actionSource: "updateSpec"
}), this) : this;
}));
}
updateSpecSync(spec, forceMerge = !1, morphConfig, userUpdateOptions) {
const result = this._updateSpec(spec, forceMerge, userUpdateOptions);
return result ? (this.updateCustomConfigAndRerender(result, !0, {
morphConfig: morphConfig,
transformSpec: result.reTransformSpec,
actionSource: "updateSpec"
}), this) : this;
}
updateSpecAndRecompile(spec, forceMerge = !1, option = {}) {
const result = this._updateSpec(spec, forceMerge);
return this._updateCustomConfigAndRecompile(result, Object.assign({
actionSource: "updateSpecAndRecompile"
}, option));
}
updateModelSpec(filter, spec, forceMerge = !1, morphConfig) {
return __awaiter(this, void 0, void 0, (function*() {
return this.updateModelSpecSync(filter, spec, forceMerge, morphConfig);
}));
}
updateModelSpecSync(filter, spec, forceMerge = !1, morphConfig) {
if (!spec || !this._spec) return this;
if (isString(spec) && (spec = JSON.parse(spec)), isFunction(filter) || mergeSpecWithFilter(this._spec, filter, spec, forceMerge),
this._chart) {
const model = this._chart.getModelInFilter(filter);
if (model) return this._updateModelSpec(model, spec, !0, forceMerge, morphConfig);
}
return this;
}
_updateModelSpec(model, spec, sync = !1, forceMerge = !1, morphConfig) {
forceMerge && (spec = mergeSpec({}, model.getSpec(), spec));
const result = model.updateSpec(spec);
return model.reInit(spec), (result.change || result.reCompile || result.reMake || result.reSize || result.reRender) && this._chart.reDataFlow(),
this.updateCustomConfigAndRerender(result, sync, {
morphConfig: morphConfig,
transformSpec: !1,
actionSource: "updateModelSpec"
});
}
resize(width, height) {
return __awaiter(this, void 0, void 0, (function*() {
return this.resizeSync(width, height);
}));
}
resizeSync(width, height) {
var _a, _b;
return this._beforeResize(width, height) ? (null === (_b = (_a = this._compiler).resize) || void 0 === _b || _b.call(_a, width, height),
this._afterResize()) : this;
}
_beforeResize(width, height) {
var _a, _b, _c, _d;
if (!this._chart || !this._compiler) return !1;
const chartCanvasRect = this._chart.getCanvasRect();
return (!chartCanvasRect || chartCanvasRect.width !== width || chartCanvasRect.height !== height) && (this._chartPluginApply("onBeforeResize", width, height),
null === (_b = null === (_a = this._option.performanceHook) || void 0 === _a ? void 0 : _a.beforeResizeWithUpdate) || void 0 === _b || _b.call(_a, this),
this._chart.onResize(width, height, !1), null === (_d = null === (_c = this._option.performanceHook) || void 0 === _c ? void 0 : _c.afterResizeWithUpdate) || void 0 === _d || _d.call(_c, this),
!0);
}
_afterResize() {
return this._isReleased || this._event.emit(ChartEvent.afterResize, {
chart: this._chart
}), this;
}
updateViewBox(viewBox, reRender = !0, reLayout = !0) {
return this._chart && this._compiler ? (this._viewBox = viewBox, this._chart.updateViewBox(viewBox, reLayout),
reLayout && (this._compiler.render(), this._chart.onEvaluateEnd()), this._compiler.updateViewBox(viewBox, reRender),
this) : this;
}
on(eType, query, handler) {
var _a;
this._userEvents && (this._userEvents.push({
eType: eType,
query: "function" == typeof query ? null : query,
handler: "function" == typeof query ? query : handler
}), null === (_a = this._event) || void 0 === _a || _a.on(eType, query, handler));
}
off(eType, handler) {
var _a;
if (this._userEvents && 0 !== this._userEvents.length) if (handler) {
const index = this._userEvents.findIndex((e => e.eType === eType && e.handler === handler));
index >= 0 && (this._userEvents.splice(index, 1), null === (_a = this._event) || void 0 === _a || _a.off(eType, handler));
} else this._userEvents.forEach((e => {
var _a;
e.eType === eType && (null === (_a = this._event) || void 0 === _a || _a.off(eType, e.handler));
})), this._userEvents = this._userEvents.filter((e => e.eType !== eType));
}
updateState(state, filter) {
this._chart && this._chart.updateState(state, filter);
}
setSelected(datum, filter, region) {
this._chart && this._chart.setSelected(datum, filter, region);
}
setHovered(datum, filter, region) {
this._chart && this._chart.setHovered(datum, filter, region);
}
clearState(state) {
this._chart && this._chart.clearState(state);
}
clearAllStates() {
this._chart && this._chart.clearAllStates();
}
clearSelected() {
this._chart && this._chart.clearSelected();
}
clearHovered() {
this._chart && this._chart.clearHovered();
}
_updateCurrentTheme(nextThemeName) {
var _a, _b, _c;
const optionTheme = this._option.theme, specTheme = null === (_a = this._spec) || void 0 === _a ? void 0 : _a.theme, chartType = null === (_b = this._spec) || void 0 === _b ? void 0 : _b.type;
nextThemeName && (this._currentThemeName = nextThemeName);
const processThemeByChartType = (type, theme) => {
var _a;
return (null === (_a = theme.chart) || void 0 === _a ? void 0 : _a[type]) && (theme = mergeTheme({}, theme, theme.chart[type])),
theme;
};
let currentTheme;
if (isEmpty(optionTheme) && isEmpty(specTheme)) currentTheme = getThemeObject(this._currentThemeName),
this._currentTheme = processThemeByChartType(chartType, currentTheme); else if (isString(optionTheme) && (!specTheme || isString(specTheme)) || isString(specTheme) && (!optionTheme || isString(optionTheme))) {
const finalTheme = mergeTheme({}, getThemeObject(this._currentThemeName), getThemeObject(optionTheme), getThemeObject(specTheme));
this._currentTheme = processThemeByChartType(chartType, finalTheme);
} else {
const finalTheme = mergeTheme({}, getThemeObject(this._currentThemeName), getThemeObject(optionTheme), getThemeObject(specTheme));
this._currentTheme = processThemeByChartType(chartType, finalTheme);
}
this._cachedProcessedTheme = null, setPoptipTheme(this.getTheme("component", "poptip")),
null === (_c = this._compiler) || void 0 === _c || _c.setBackground(this._getBackground());
}
_shouldChartResize(oldSpec) {
var _a, _b;
let resize = !1;
isNil(this._spec.width) ? !isNil(oldSpec.width) && (this._spec.width = oldSpec.width) : this._spec.width !== oldSpec.width && (resize = !0),
isNil(this._spec.height) ? !isNil(oldSpec.height) && (this._spec.height = oldSpec.height) : this._spec.height !== oldSpec.height && (resize = !0);
const lasAutoSize = this._autoSize;
return this._autoSize = !!isTrueBrowser(this._option.mode) && (null === (_b = null !== (_a = this._spec.autoFit) && void 0 !== _a ? _a : this._option.autoFit) || void 0 === _b || _b),
this._autoSize !== lasAutoSize && (resize = !0), resize;
}
_getBackground() {
return ("string" == typeof this._spec.background || isObject(this._spec.background) && this._spec.background.gradient ? this._spec.background : null) || this.getTheme("background") || this._option.background;
}
getCurrentTheme() {
return getThemeObject(this._currentThemeName);
}
getCurrentThemeName() {
return this._currentThemeName;
}
setCurrentTheme(name) {
return __awaiter(this, void 0, void 0, (function*() {
return this.setCurrentThemeSync(name);
}));
}
setCurrentThemeSync(name) {
if (!ThemeManager.themeExist(name)) return this;
const result = this._setCurrentTheme(name);
return this._setFontFamilyTheme(this.getTheme("fontFamily")), this.updateCustomConfigAndRerender(result, !0, {
transformSpec: !1,
actionSource: "setCurrentTheme"
}), this;
}
_setCurrentTheme(name) {
var _a;
return this._updateCurrentTheme(name), this._initChartSpec(this._getSpecFromOriginalSpec(), "setCurrentTheme"),
null === (_a = this._chart) || void 0 === _a || _a.setCurrentTheme(), {
change: !0,
reMake: !1
};
}
_setFontFamilyTheme(fontFamily) {
var _a;
fontFamily && (null === (_a = this.getStage()) || void 0 === _a || _a.setTheme({
text: {
fontFamily: fontFamily
},
richtext: {
fontFamily: fontFamily
}
}));
}
_getTooltipComponent() {
var _a;
return null === (_a = this._chart) || void 0 === _a ? void 0 : _a.getComponentsByType(ComponentTypeEnum.tooltip)[0];
}
setTooltipHandler(tooltipHandler) {
var _a, _b;
this._context.tooltipHandler = tooltipHandler;
const tooltip = this._getTooltipComponent();
tooltip && (null === (_b = null === (_a = tooltip.tooltipHandler) || void 0 === _a ? void 0 : _a.release) || void 0 === _b || _b.call(_a),
tooltip.tooltipHandler = tooltipHandler);
}
getTooltipHandlerByUser() {
var _a;
return null === (_a = this._context) || void 0 === _a ? void 0 : _a.tooltipHandler;
}
getTooltipHandler() {
const tooltip = this._getTooltipComponent();
return tooltip ? tooltip.tooltipHandler : this._context.tooltipHandler;
}
showTooltip(datum, options) {
var _a;
const tooltip = this._getTooltipComponent();
return null !== (_a = isValid(datum) && "none" !== (null == tooltip ? void 0 : tooltip.showTooltip(datum, options))) && void 0 !== _a && _a;
}
hideTooltip() {
var _a;
const tooltip = this._getTooltipComponent();
return null !== (_a = null == tooltip ? void 0 : tooltip.hideTooltip()) && void 0 !== _a && _a;
}
getLegendDataById(id) {
var _a;
const legendComponent = null === (_a = this._chart) || void 0 === _a ? void 0 : _a.getComponentByUserId(id);
return legendComponent ? legendComponent.getLegendData() : [];
}
getLegendDataByIndex(index = 0) {
var _a;
const legends = null === (_a = this._chart) || void 0 === _a ? void 0 : _a.getComponentsByType(ComponentTypeEnum.discreteLegend);
return legends && legends[index] ? legends[index].getLegendData() : [];
}
getLegendSelectedDataById(id) {
var _a;
const legendComponent = null === (_a = this._chart) || void 0 === _a ? void 0 : _a.getComponentByUserId(id);
return legendComponent ? legendComponent.getSelectedData() : [];
}
getLegendSelectedDataByIndex(index = 0) {
var _a;
const legends = null === (_a = this._chart) || void 0 === _a ? void 0 : _a.getComponentsByType(ComponentTypeEnum.discreteLegend);
return legends && legends[index] ? legends[index].getSelectedData() : [];
}
setLegendSelectedDataById(id, selectedData) {
var _a;
const legendComponent = null === (_a = this._chart) || void 0 === _a ? void 0 : _a.getComponentByUserId(id);
legendComponent && legendComponent.setSelectedData(selectedData);
}
setLegendSelectedDataByIndex(index = 0, selectedData) {
var _a;
const legends = null === (_a = this._chart) || void 0 === _a ? void 0 : _a.getComponentsByType(ComponentTypeEnum.discreteLegend);
legends && legends[index] && legends[index].setSelectedData(selectedData);
}
getDataURL() {
var _a;
return __awaiter(this, void 0, void 0, (function*() {
const stage = this.getStage();
if (this._chart && stage) {
stage.render();
const canvas = this._chart.getCanvas();
return yield getCanvasDataURL(canvas, {
onError: this._onError
});
}
return null === (_a = this._option) || void 0 === _a || _a.onError(new ReferenceError("render is not defined")),
null;
}));
}
exportImg(name) {
var _a, _b;
return __awaiter(this, void 0, void 0, (function*() {
if (!isTrueBrowser(this._option.mode)) return void (null === (_a = this._option) || void 0 === _a || _a.onError(new TypeError("non-browser environment can not export img")));
const dataURL = yield this.getDataURL();
dataURL ? URLToImage(name, dataURL) : null === (_b = this._option) || void 0 === _b || _b.onError(new ReferenceError("render is not defined"));
}));
}
exportCanvas() {
var _a;
const stage = this.getStage();
if (this._chart && stage) return stage.toCanvas();
null === (_a = this._option) || void 0 === _a || _a.onError(new ReferenceError("render is not defined"));
}
getImageBuffer() {
var _a, _b;
if ("node" !== this._option.mode) return void (null === (_a = this._option) || void 0 === _a || _a.onError(new TypeError("getImageBuffer() now only support node environment.")));
const stage = this.getStage();
if (stage) {
stage.render();
return stage.window.getImageBuffer();
}
return null === (_b = this._option) || void 0 === _b || _b.onError(new ReferenceError("render is not defined")),
null;
}
setLayout(layout) {
var _a;
this._option.layout = layout, null === (_a = this._chart) || void 0 === _a || _a.setLayout(layout);
}
reLayout() {
var _a;
this._chart.resetLayoutItemTag(), null === (_a = this._chart) || void 0 === _a || _a.setLayoutTag(!0);
}
getCompiler() {
return this._compiler;
}
getChart() {
return this._chart;
}
getStage() {
return this._compiler.getStage();
}
getCanvas() {
var _a;
return null === (_a = this._compiler) || void 0 === _a ? void 0 : _a.getCanvas();
}
getContainer() {
var _a;
if (isValid(this._container)) return this._container;
let canvasNode;
return canvasNode = isString(this._canvas) ? vglobal.getElementById(this._canvas) : this._canvas,
isValid(canvasNode) ? canvasNode.parentElement : null === (_a = this.getCanvas()) || void 0 === _a ? void 0 : _a.parentElement;
}
getComponents() {
return this._chart.getAllComponents();
}
getScale(scaleId) {
var _a;
const globalScale = null === (_a = this._chart) || void 0 === _a ? void 0 : _a.getGlobalScale();
return null == globalScale ? void 0 : globalScale.getScale(scaleId);
}
setDimensionIndex(value, opt = {}) {
var _a;
return null === (_a = this._chart) || void 0 === _a ? void 0 : _a.setDimensionIndex(value, opt);
}
stopAnimation() {}
pauseAnimation() {}
resumeAnimation() {}
convertDatumToPosition(datum, dataLinkInfo = {}, isRelativeToCanvas = !1, checkInViewData) {
var _a;
if (!this._chart) return null;
if (isEmpty(datum)) return null;
const {seriesId: seriesId, seriesIndex: seriesIndex = 0} = dataLinkInfo;
let series;
if (isValid(seriesId) ? series = this._chart.getSeriesInUserId(seriesId) : isValid(seriesIndex) && (series = null === (_a = this._chart.getSeriesInIndex([ seriesIndex ])) || void 0 === _a ? void 0 : _a[0]),
series) {
const keys = Object.keys(datum), handledDatum = series.getViewData().latestData.find((viewDatum => keys.every((k => viewDatum[k] == datum[k])))), seriesLayoutStartPoint = series.getRegion().getLayoutStartPoint();
let point;
return point = handledDatum ? series.dataToPosition(handledDatum, checkInViewData) : series.dataToPosition(datum, checkInViewData),
point ? convertPoint(point, seriesLayoutStartPoint, isRelativeToCanvas) : null;
}
return null;
}
convertValueToPosition(value, dataLinkInfo, isRelativeToCanvas = !1) {
var _a, _b;
if (!this._chart || isNil(value) || isEmpty(dataLinkInfo)) return null;
if (!isArray(value)) {
const {axisId: axisId, axisIndex: axisIndex} = dataLinkInfo;
let axis;
if (isValid(axisId) ? axis = this._chart.getComponentsByKey("axes").find((s => s.userId === axisId)) : isValid(axisIndex) && (axis = null === (_a = this._chart.getComponentsByKey("axes")) || void 0 === _a ? void 0 : _a[axisIndex]),
!axis) return warn("Please check whether the `axisId` or `axisIndex` is set!"),
null;
const pointValue = null == axis ? void 0 : axis.valueToPosition(value);
if (isRelativeToCanvas) {
const axisLayoutStartPoint = axis.getLayoutStartPoint(), axisOrient = axis.getOrient();
return pointValue + ("bottom" === axisOrient || "top" === axisOrient ? axisLayoutStartPoint.x : axisLayoutStartPoint.y);
}
return pointValue;
}
const {seriesId: seriesId, seriesIndex: seriesIndex} = dataLinkInfo;
let series;
return isValid(seriesId) ? series = this._chart.getSeriesInUserId(seriesId) : isValid(seriesIndex) && (series = null === (_b = this._chart.getSeriesInIndex([ seriesIndex ])) || void 0 === _b ? void 0 : _b[0]),
series ? convertPoint(series.valueToPosition(value[0], value[1]), series.getRegion().getLayoutStartPoint(), isRelativeToCanvas) : (warn("Please check whether the `seriesId` or `seriesIndex` is set!"),
null);
}
getFunction(key) {
return ExpressionFunction.instance().getFunction(key);
}
registerFunction(key, fun) {
key && fun && ExpressionFunction.instance().registerFunction(key, fun);
}
unregisterFunction(key) {
key && ExpressionFunction.instance().unregisterFunction(key);
}
getFunctionList() {
return ExpressionFunction.instance().getFunctionNameList();
}
setRuntimeSpec(spec) {
this._spec = spec, this._updateSpecInfo();
}
updateIndicatorDataById(id, datum) {
var _a;
const indicator = null === (_a = this._chart) || void 0 === _a ? void 0 : _a.getComponentByUserId(id);
indicator && indicator.updateDatum(datum);
}
updateIndicatorDataByIndex(index = 0, datum) {
var _a;
const indicators = null === (_a = this._chart) || void 0 === _a ? void 0 : _a.getComponentsByType(ComponentTypeEnum.indicator);
indicators && indicators[index] && indicators[index].updateDatum(datum);
}
geoZoomByIndex(regionIndex = 0, zoom, center) {
this._geoZoomByQuery({
regionIndex: regionIndex
}, zoom, center);
}
geoZoomById(regionId, zoom, center) {
this._geoZoomByQuery({
regionId: regionId
}, zoom, center);
}
_geoZoomByQuery(query, zoom, center) {
var _a, _b;
const region = null === (_a = this._chart) || void 0 === _a ? void 0 : _a.getRegionsInQuerier(query)[0], geoCoordinates = null === (_b = this._chart) || void 0 === _b ? void 0 : _b.getComponentsByType(ComponentTypeEnum.geoCoordinate), coord = null == geoCoordinates ? void 0 : geoCoordinates.find((coord => {
var _a;
return null === (_a = coord.getRegions()) || void 0 === _a ? void 0 : _a.includes(region);
}));
coord && coord.dispatchZoom(zoom, center);
}
_initChartPlugin() {
const pluginList = Factory.getChartPlugins();
pluginList.length > 0 && (this._chartPlugin = new ChartPluginService(this), this._chartPlugin.load(pluginList.map((p => new p))),
this._chartPluginApply("onInit", this._spec));
}
_chartPluginApply(funcName, ...args) {
this._chartPlugin && this._chartPlugin[funcName] && this._chartPlugin[funcName].apply(this._chartPlugin, args);
}
_getMode() {
return this._option.mode || RenderModeEnum["desktop-browser"];
}
_getChartOption(type) {
return {
type: type,
globalInstance: this,
eventDispatcher: this._eventDispatcher,
dataSet: this._dataSet,
container: this._container,
canvas: this._canvas,
map: new Map,
mode: this._getMode(),
modeParams: this._option.modeParams,
getCompiler: () => this._compiler,
viewBox: this._viewBox,
animation: this._option.animation,
getTheme: this.getTheme,
getSpecInfo: () => {
var _a;
return null !== (_a = this._specInfo) && void 0 !== _a ? _a : {};
},
layout: this._option.layout,
onError: this._onError,
disableTriggerEvent: !0 === this._option.disableTriggerEvent
};
}
}
VChart.InstanceManager = InstanceManager, VChart.ThemeManager = ThemeManager, VChart.globalConfig = {
uniqueTooltip: !0
}, VChart.Utils = VCHART_UTILS, VChart.vglobal = vglobal;
export const registerVChartCore = () => {
Factory.registerRegion("region", Region), Factory.registerLayout("base", Layout),
registerGroupMark(), registerGesturePlugin(), registerElementHighlight(), registerElementSelect(),
registerTheme(darkTheme.name, darkTheme);
};
Factory.registerRegion("region", Region), Factory.registerLayout("base", Layout),
registerGroupMark(), registerGesturePlugin(), registerElementHighlight(), registerElementSelect(),
registerTheme(darkTheme.name, darkTheme);
//# sourceMappingURL=vchart.js.map