|
@@ -1,2273 +0,0 @@
|
|
|
-
|
|
|
-/*
|
|
|
-* Licensed to the Apache Software Foundation (ASF) under one
|
|
|
-* or more contributor license agreements. See the NOTICE file
|
|
|
-* distributed with this work for additional information
|
|
|
-* regarding copyright ownership. The ASF licenses this file
|
|
|
-* to you under the Apache License, Version 2.0 (the
|
|
|
-* "License"); you may not use this file except in compliance
|
|
|
-* with the License. You may obtain a copy of the License at
|
|
|
-*
|
|
|
-* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
-*
|
|
|
-* Unless required by applicable law or agreed to in writing,
|
|
|
-* software distributed under the License is distributed on an
|
|
|
-* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
|
-* KIND, either express or implied. See the License for the
|
|
|
-* specific language governing permissions and limitations
|
|
|
-* under the License.
|
|
|
-*/
|
|
|
-
|
|
|
-
|
|
|
-/**
|
|
|
- * AUTO-GENERATED FILE. DO NOT MODIFY.
|
|
|
- */
|
|
|
-
|
|
|
-import { __extends } from "tslib";
|
|
|
-/*
|
|
|
-* Licensed to the Apache Software Foundation (ASF) under one
|
|
|
-* or more contributor license agreements. See the NOTICE file
|
|
|
-* distributed with this work for additional information
|
|
|
-* regarding copyright ownership. The ASF licenses this file
|
|
|
-* to you under the Apache License, Version 2.0 (the
|
|
|
-* "License"); you may not use this file except in compliance
|
|
|
-* with the License. You may obtain a copy of the License at
|
|
|
-*
|
|
|
-* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
-*
|
|
|
-* Unless required by applicable law or agreed to in writing,
|
|
|
-* software distributed under the License is distributed on an
|
|
|
-* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
|
-* KIND, either express or implied. See the License for the
|
|
|
-* specific language governing permissions and limitations
|
|
|
-* under the License.
|
|
|
-*/
|
|
|
-import * as zrender from 'zrender/lib/zrender.js';
|
|
|
-import { assert, each, isFunction, isObject, indexOf, bind, clone, setAsPrimitive, extend, createHashMap, map, defaults, isDom, isArray, noop, isString, retrieve2 } from 'zrender/lib/core/util.js';
|
|
|
-import env from 'zrender/lib/core/env.js';
|
|
|
-import timsort from 'zrender/lib/core/timsort.js';
|
|
|
-import Eventful from 'zrender/lib/core/Eventful.js';
|
|
|
-import GlobalModel from '../model/Global.js';
|
|
|
-import ExtensionAPI from './ExtensionAPI.js';
|
|
|
-import CoordinateSystemManager from './CoordinateSystem.js';
|
|
|
-import OptionManager from '../model/OptionManager.js';
|
|
|
-import backwardCompat from '../preprocessor/backwardCompat.js';
|
|
|
-import dataStack from '../processor/dataStack.js';
|
|
|
-import SeriesModel from '../model/Series.js';
|
|
|
-import ComponentView from '../view/Component.js';
|
|
|
-import ChartView from '../view/Chart.js';
|
|
|
-import * as graphic from '../util/graphic.js';
|
|
|
-import { getECData } from '../util/innerStore.js';
|
|
|
-import { isHighDownDispatcher, HOVER_STATE_EMPHASIS, HOVER_STATE_BLUR, blurSeriesFromHighlightPayload, toggleSelectionFromPayload, updateSeriesElementSelection, getAllSelectedIndices, isSelectChangePayload, isHighDownPayload, HIGHLIGHT_ACTION_TYPE, DOWNPLAY_ACTION_TYPE, SELECT_ACTION_TYPE, UNSELECT_ACTION_TYPE, TOGGLE_SELECT_ACTION_TYPE, savePathStates, enterEmphasis, leaveEmphasis, leaveBlur, enterSelect, leaveSelect, enterBlur, allLeaveBlur, findComponentHighDownDispatchers, blurComponent, handleGlobalMouseOverForHighDown, handleGlobalMouseOutForHighDown } from '../util/states.js';
|
|
|
-import * as modelUtil from '../util/model.js';
|
|
|
-import { throttle } from '../util/throttle.js';
|
|
|
-import { seriesStyleTask, dataStyleTask, dataColorPaletteTask } from '../visual/style.js';
|
|
|
-import loadingDefault from '../loading/default.js';
|
|
|
-import Scheduler from './Scheduler.js';
|
|
|
-import lightTheme from '../theme/light.js';
|
|
|
-import darkTheme from '../theme/dark.js';
|
|
|
-import { parseClassType } from '../util/clazz.js';
|
|
|
-import { ECEventProcessor } from '../util/ECEventProcessor.js';
|
|
|
-import { seriesSymbolTask, dataSymbolTask } from '../visual/symbol.js';
|
|
|
-import { getVisualFromData, getItemVisualFromData } from '../visual/helper.js';
|
|
|
-import { deprecateLog, deprecateReplaceLog, error, warn } from '../util/log.js';
|
|
|
-import { handleLegacySelectEvents } from '../legacy/dataSelectAction.js';
|
|
|
-import { registerExternalTransform } from '../data/helper/transform.js';
|
|
|
-import { createLocaleObject, SYSTEM_LANG } from './locale.js';
|
|
|
-import { findEventDispatcher } from '../util/event.js';
|
|
|
-import decal from '../visual/decal.js';
|
|
|
-import lifecycle from './lifecycle.js';
|
|
|
-import { platformApi, setPlatformAPI } from 'zrender/lib/core/platform.js';
|
|
|
-import { getImpl } from './impl.js';
|
|
|
-export var version = '5.5.1';
|
|
|
-export var dependencies = {
|
|
|
- zrender: '5.6.0'
|
|
|
-};
|
|
|
-var TEST_FRAME_REMAIN_TIME = 1;
|
|
|
-var PRIORITY_PROCESSOR_SERIES_FILTER = 800;
|
|
|
-// Some data processors depends on the stack result dimension (to calculate data extent).
|
|
|
-// So data stack stage should be in front of data processing stage.
|
|
|
-var PRIORITY_PROCESSOR_DATASTACK = 900;
|
|
|
-// "Data filter" will block the stream, so it should be
|
|
|
-// put at the beginning of data processing.
|
|
|
-var PRIORITY_PROCESSOR_FILTER = 1000;
|
|
|
-var PRIORITY_PROCESSOR_DEFAULT = 2000;
|
|
|
-var PRIORITY_PROCESSOR_STATISTIC = 5000;
|
|
|
-var PRIORITY_VISUAL_LAYOUT = 1000;
|
|
|
-var PRIORITY_VISUAL_PROGRESSIVE_LAYOUT = 1100;
|
|
|
-var PRIORITY_VISUAL_GLOBAL = 2000;
|
|
|
-var PRIORITY_VISUAL_CHART = 3000;
|
|
|
-var PRIORITY_VISUAL_COMPONENT = 4000;
|
|
|
-// Visual property in data. Greater than `PRIORITY_VISUAL_COMPONENT` to enable to
|
|
|
-// overwrite the viusal result of component (like `visualMap`)
|
|
|
-// using data item specific setting (like itemStyle.xxx on data item)
|
|
|
-var PRIORITY_VISUAL_CHART_DATA_CUSTOM = 4500;
|
|
|
-// Greater than `PRIORITY_VISUAL_CHART_DATA_CUSTOM` to enable to layout based on
|
|
|
-// visual result like `symbolSize`.
|
|
|
-var PRIORITY_VISUAL_POST_CHART_LAYOUT = 4600;
|
|
|
-var PRIORITY_VISUAL_BRUSH = 5000;
|
|
|
-var PRIORITY_VISUAL_ARIA = 6000;
|
|
|
-var PRIORITY_VISUAL_DECAL = 7000;
|
|
|
-export var PRIORITY = {
|
|
|
- PROCESSOR: {
|
|
|
- FILTER: PRIORITY_PROCESSOR_FILTER,
|
|
|
- SERIES_FILTER: PRIORITY_PROCESSOR_SERIES_FILTER,
|
|
|
- STATISTIC: PRIORITY_PROCESSOR_STATISTIC
|
|
|
- },
|
|
|
- VISUAL: {
|
|
|
- LAYOUT: PRIORITY_VISUAL_LAYOUT,
|
|
|
- PROGRESSIVE_LAYOUT: PRIORITY_VISUAL_PROGRESSIVE_LAYOUT,
|
|
|
- GLOBAL: PRIORITY_VISUAL_GLOBAL,
|
|
|
- CHART: PRIORITY_VISUAL_CHART,
|
|
|
- POST_CHART_LAYOUT: PRIORITY_VISUAL_POST_CHART_LAYOUT,
|
|
|
- COMPONENT: PRIORITY_VISUAL_COMPONENT,
|
|
|
- BRUSH: PRIORITY_VISUAL_BRUSH,
|
|
|
- CHART_ITEM: PRIORITY_VISUAL_CHART_DATA_CUSTOM,
|
|
|
- ARIA: PRIORITY_VISUAL_ARIA,
|
|
|
- DECAL: PRIORITY_VISUAL_DECAL
|
|
|
- }
|
|
|
-};
|
|
|
-// Main process have three entries: `setOption`, `dispatchAction` and `resize`,
|
|
|
-// where they must not be invoked nestedly, except the only case: invoke
|
|
|
-// dispatchAction with updateMethod "none" in main process.
|
|
|
-// This flag is used to carry out this rule.
|
|
|
-// All events will be triggered out side main process (i.e. when !this[IN_MAIN_PROCESS]).
|
|
|
-var IN_MAIN_PROCESS_KEY = '__flagInMainProcess';
|
|
|
-var PENDING_UPDATE = '__pendingUpdate';
|
|
|
-var STATUS_NEEDS_UPDATE_KEY = '__needsUpdateStatus';
|
|
|
-var ACTION_REG = /^[a-zA-Z0-9_]+$/;
|
|
|
-var CONNECT_STATUS_KEY = '__connectUpdateStatus';
|
|
|
-var CONNECT_STATUS_PENDING = 0;
|
|
|
-var CONNECT_STATUS_UPDATING = 1;
|
|
|
-var CONNECT_STATUS_UPDATED = 2;
|
|
|
-;
|
|
|
-;
|
|
|
-function createRegisterEventWithLowercaseECharts(method) {
|
|
|
- return function () {
|
|
|
- var args = [];
|
|
|
- for (var _i = 0; _i < arguments.length; _i++) {
|
|
|
- args[_i] = arguments[_i];
|
|
|
- }
|
|
|
- if (this.isDisposed()) {
|
|
|
- disposedWarning(this.id);
|
|
|
- return;
|
|
|
- }
|
|
|
- return toLowercaseNameAndCallEventful(this, method, args);
|
|
|
- };
|
|
|
-}
|
|
|
-function createRegisterEventWithLowercaseMessageCenter(method) {
|
|
|
- return function () {
|
|
|
- var args = [];
|
|
|
- for (var _i = 0; _i < arguments.length; _i++) {
|
|
|
- args[_i] = arguments[_i];
|
|
|
- }
|
|
|
- return toLowercaseNameAndCallEventful(this, method, args);
|
|
|
- };
|
|
|
-}
|
|
|
-function toLowercaseNameAndCallEventful(host, method, args) {
|
|
|
- // `args[0]` is event name. Event name is all lowercase.
|
|
|
- args[0] = args[0] && args[0].toLowerCase();
|
|
|
- return Eventful.prototype[method].apply(host, args);
|
|
|
-}
|
|
|
-var MessageCenter = /** @class */function (_super) {
|
|
|
- __extends(MessageCenter, _super);
|
|
|
- function MessageCenter() {
|
|
|
- return _super !== null && _super.apply(this, arguments) || this;
|
|
|
- }
|
|
|
- return MessageCenter;
|
|
|
-}(Eventful);
|
|
|
-var messageCenterProto = MessageCenter.prototype;
|
|
|
-messageCenterProto.on = createRegisterEventWithLowercaseMessageCenter('on');
|
|
|
-messageCenterProto.off = createRegisterEventWithLowercaseMessageCenter('off');
|
|
|
-// ---------------------------------------
|
|
|
-// Internal method names for class ECharts
|
|
|
-// ---------------------------------------
|
|
|
-var prepare;
|
|
|
-var prepareView;
|
|
|
-var updateDirectly;
|
|
|
-var updateMethods;
|
|
|
-var doConvertPixel;
|
|
|
-var updateStreamModes;
|
|
|
-var doDispatchAction;
|
|
|
-var flushPendingActions;
|
|
|
-var triggerUpdatedEvent;
|
|
|
-var bindRenderedEvent;
|
|
|
-var bindMouseEvent;
|
|
|
-var render;
|
|
|
-var renderComponents;
|
|
|
-var renderSeries;
|
|
|
-var createExtensionAPI;
|
|
|
-var enableConnect;
|
|
|
-var markStatusToUpdate;
|
|
|
-var applyChangedStates;
|
|
|
-var ECharts = /** @class */function (_super) {
|
|
|
- __extends(ECharts, _super);
|
|
|
- function ECharts(dom,
|
|
|
- // Theme name or themeOption.
|
|
|
- theme, opts) {
|
|
|
- var _this = _super.call(this, new ECEventProcessor()) || this;
|
|
|
- _this._chartsViews = [];
|
|
|
- _this._chartsMap = {};
|
|
|
- _this._componentsViews = [];
|
|
|
- _this._componentsMap = {};
|
|
|
- // Can't dispatch action during rendering procedure
|
|
|
- _this._pendingActions = [];
|
|
|
- opts = opts || {};
|
|
|
- // Get theme by name
|
|
|
- if (isString(theme)) {
|
|
|
- theme = themeStorage[theme];
|
|
|
- }
|
|
|
- _this._dom = dom;
|
|
|
- var defaultRenderer = 'canvas';
|
|
|
- var defaultCoarsePointer = 'auto';
|
|
|
- var defaultUseDirtyRect = false;
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
- var root = /* eslint-disable-next-line */
|
|
|
- env.hasGlobalWindow ? window : global;
|
|
|
- if (root) {
|
|
|
- defaultRenderer = retrieve2(root.__ECHARTS__DEFAULT__RENDERER__, defaultRenderer);
|
|
|
- defaultCoarsePointer = retrieve2(root.__ECHARTS__DEFAULT__COARSE_POINTER, defaultCoarsePointer);
|
|
|
- defaultUseDirtyRect = retrieve2(root.__ECHARTS__DEFAULT__USE_DIRTY_RECT__, defaultUseDirtyRect);
|
|
|
- }
|
|
|
- }
|
|
|
- if (opts.ssr) {
|
|
|
- zrender.registerSSRDataGetter(function (el) {
|
|
|
- var ecData = getECData(el);
|
|
|
- var dataIndex = ecData.dataIndex;
|
|
|
- if (dataIndex == null) {
|
|
|
- return;
|
|
|
- }
|
|
|
- var hashMap = createHashMap();
|
|
|
- hashMap.set('series_index', ecData.seriesIndex);
|
|
|
- hashMap.set('data_index', dataIndex);
|
|
|
- ecData.ssrType && hashMap.set('ssr_type', ecData.ssrType);
|
|
|
- return hashMap;
|
|
|
- });
|
|
|
- }
|
|
|
- var zr = _this._zr = zrender.init(dom, {
|
|
|
- renderer: opts.renderer || defaultRenderer,
|
|
|
- devicePixelRatio: opts.devicePixelRatio,
|
|
|
- width: opts.width,
|
|
|
- height: opts.height,
|
|
|
- ssr: opts.ssr,
|
|
|
- useDirtyRect: retrieve2(opts.useDirtyRect, defaultUseDirtyRect),
|
|
|
- useCoarsePointer: retrieve2(opts.useCoarsePointer, defaultCoarsePointer),
|
|
|
- pointerSize: opts.pointerSize
|
|
|
- });
|
|
|
- _this._ssr = opts.ssr;
|
|
|
- // Expect 60 fps.
|
|
|
- _this._throttledZrFlush = throttle(bind(zr.flush, zr), 17);
|
|
|
- theme = clone(theme);
|
|
|
- theme && backwardCompat(theme, true);
|
|
|
- _this._theme = theme;
|
|
|
- _this._locale = createLocaleObject(opts.locale || SYSTEM_LANG);
|
|
|
- _this._coordSysMgr = new CoordinateSystemManager();
|
|
|
- var api = _this._api = createExtensionAPI(_this);
|
|
|
- // Sort on demand
|
|
|
- function prioritySortFunc(a, b) {
|
|
|
- return a.__prio - b.__prio;
|
|
|
- }
|
|
|
- timsort(visualFuncs, prioritySortFunc);
|
|
|
- timsort(dataProcessorFuncs, prioritySortFunc);
|
|
|
- _this._scheduler = new Scheduler(_this, api, dataProcessorFuncs, visualFuncs);
|
|
|
- _this._messageCenter = new MessageCenter();
|
|
|
- // Init mouse events
|
|
|
- _this._initEvents();
|
|
|
- // In case some people write `window.onresize = chart.resize`
|
|
|
- _this.resize = bind(_this.resize, _this);
|
|
|
- zr.animation.on('frame', _this._onframe, _this);
|
|
|
- bindRenderedEvent(zr, _this);
|
|
|
- bindMouseEvent(zr, _this);
|
|
|
- // ECharts instance can be used as value.
|
|
|
- setAsPrimitive(_this);
|
|
|
- return _this;
|
|
|
- }
|
|
|
- ECharts.prototype._onframe = function () {
|
|
|
- if (this._disposed) {
|
|
|
- return;
|
|
|
- }
|
|
|
- applyChangedStates(this);
|
|
|
- var scheduler = this._scheduler;
|
|
|
- // Lazy update
|
|
|
- if (this[PENDING_UPDATE]) {
|
|
|
- var silent = this[PENDING_UPDATE].silent;
|
|
|
- this[IN_MAIN_PROCESS_KEY] = true;
|
|
|
- try {
|
|
|
- prepare(this);
|
|
|
- updateMethods.update.call(this, null, this[PENDING_UPDATE].updateParams);
|
|
|
- } catch (e) {
|
|
|
- this[IN_MAIN_PROCESS_KEY] = false;
|
|
|
- this[PENDING_UPDATE] = null;
|
|
|
- throw e;
|
|
|
- }
|
|
|
- // At present, in each frame, zrender performs:
|
|
|
- // (1) animation step forward.
|
|
|
- // (2) trigger('frame') (where this `_onframe` is called)
|
|
|
- // (3) zrender flush (render).
|
|
|
- // If we do nothing here, since we use `setToFinal: true`, the step (3) above
|
|
|
- // will render the final state of the elements before the real animation started.
|
|
|
- this._zr.flush();
|
|
|
- this[IN_MAIN_PROCESS_KEY] = false;
|
|
|
- this[PENDING_UPDATE] = null;
|
|
|
- flushPendingActions.call(this, silent);
|
|
|
- triggerUpdatedEvent.call(this, silent);
|
|
|
- }
|
|
|
- // Avoid do both lazy update and progress in one frame.
|
|
|
- else if (scheduler.unfinished) {
|
|
|
- // Stream progress.
|
|
|
- var remainTime = TEST_FRAME_REMAIN_TIME;
|
|
|
- var ecModel = this._model;
|
|
|
- var api = this._api;
|
|
|
- scheduler.unfinished = false;
|
|
|
- do {
|
|
|
- var startTime = +new Date();
|
|
|
- scheduler.performSeriesTasks(ecModel);
|
|
|
- // Currently dataProcessorFuncs do not check threshold.
|
|
|
- scheduler.performDataProcessorTasks(ecModel);
|
|
|
- updateStreamModes(this, ecModel);
|
|
|
- // Do not update coordinate system here. Because that coord system update in
|
|
|
- // each frame is not a good user experience. So we follow the rule that
|
|
|
- // the extent of the coordinate system is determined in the first frame (the
|
|
|
- // frame is executed immediately after task reset.
|
|
|
- // this._coordSysMgr.update(ecModel, api);
|
|
|
- // console.log('--- ec frame visual ---', remainTime);
|
|
|
- scheduler.performVisualTasks(ecModel);
|
|
|
- renderSeries(this, this._model, api, 'remain', {});
|
|
|
- remainTime -= +new Date() - startTime;
|
|
|
- } while (remainTime > 0 && scheduler.unfinished);
|
|
|
- // Call flush explicitly for trigger finished event.
|
|
|
- if (!scheduler.unfinished) {
|
|
|
- this._zr.flush();
|
|
|
- }
|
|
|
- // Else, zr flushing be ensue within the same frame,
|
|
|
- // because zr flushing is after onframe event.
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- ECharts.prototype.getDom = function () {
|
|
|
- return this._dom;
|
|
|
- };
|
|
|
- ECharts.prototype.getId = function () {
|
|
|
- return this.id;
|
|
|
- };
|
|
|
- ECharts.prototype.getZr = function () {
|
|
|
- return this._zr;
|
|
|
- };
|
|
|
- ECharts.prototype.isSSR = function () {
|
|
|
- return this._ssr;
|
|
|
- };
|
|
|
- /* eslint-disable-next-line */
|
|
|
- ECharts.prototype.setOption = function (option, notMerge, lazyUpdate) {
|
|
|
- if (this[IN_MAIN_PROCESS_KEY]) {
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
- error('`setOption` should not be called during main process.');
|
|
|
- }
|
|
|
- return;
|
|
|
- }
|
|
|
- if (this._disposed) {
|
|
|
- disposedWarning(this.id);
|
|
|
- return;
|
|
|
- }
|
|
|
- var silent;
|
|
|
- var replaceMerge;
|
|
|
- var transitionOpt;
|
|
|
- if (isObject(notMerge)) {
|
|
|
- lazyUpdate = notMerge.lazyUpdate;
|
|
|
- silent = notMerge.silent;
|
|
|
- replaceMerge = notMerge.replaceMerge;
|
|
|
- transitionOpt = notMerge.transition;
|
|
|
- notMerge = notMerge.notMerge;
|
|
|
- }
|
|
|
- this[IN_MAIN_PROCESS_KEY] = true;
|
|
|
- if (!this._model || notMerge) {
|
|
|
- var optionManager = new OptionManager(this._api);
|
|
|
- var theme = this._theme;
|
|
|
- var ecModel = this._model = new GlobalModel();
|
|
|
- ecModel.scheduler = this._scheduler;
|
|
|
- ecModel.ssr = this._ssr;
|
|
|
- ecModel.init(null, null, null, theme, this._locale, optionManager);
|
|
|
- }
|
|
|
- this._model.setOption(option, {
|
|
|
- replaceMerge: replaceMerge
|
|
|
- }, optionPreprocessorFuncs);
|
|
|
- var updateParams = {
|
|
|
- seriesTransition: transitionOpt,
|
|
|
- optionChanged: true
|
|
|
- };
|
|
|
- if (lazyUpdate) {
|
|
|
- this[PENDING_UPDATE] = {
|
|
|
- silent: silent,
|
|
|
- updateParams: updateParams
|
|
|
- };
|
|
|
- this[IN_MAIN_PROCESS_KEY] = false;
|
|
|
- // `setOption(option, {lazyMode: true})` may be called when zrender has been slept.
|
|
|
- // It should wake it up to make sure zrender start to render at the next frame.
|
|
|
- this.getZr().wakeUp();
|
|
|
- } else {
|
|
|
- try {
|
|
|
- prepare(this);
|
|
|
- updateMethods.update.call(this, null, updateParams);
|
|
|
- } catch (e) {
|
|
|
- this[PENDING_UPDATE] = null;
|
|
|
- this[IN_MAIN_PROCESS_KEY] = false;
|
|
|
- throw e;
|
|
|
- }
|
|
|
- // Ensure zr refresh sychronously, and then pixel in canvas can be
|
|
|
- // fetched after `setOption`.
|
|
|
- if (!this._ssr) {
|
|
|
- // not use flush when using ssr mode.
|
|
|
- this._zr.flush();
|
|
|
- }
|
|
|
- this[PENDING_UPDATE] = null;
|
|
|
- this[IN_MAIN_PROCESS_KEY] = false;
|
|
|
- flushPendingActions.call(this, silent);
|
|
|
- triggerUpdatedEvent.call(this, silent);
|
|
|
- }
|
|
|
- };
|
|
|
- /**
|
|
|
- * @deprecated
|
|
|
- */
|
|
|
- ECharts.prototype.setTheme = function () {
|
|
|
- deprecateLog('ECharts#setTheme() is DEPRECATED in ECharts 3.0');
|
|
|
- };
|
|
|
- // We don't want developers to use getModel directly.
|
|
|
- ECharts.prototype.getModel = function () {
|
|
|
- return this._model;
|
|
|
- };
|
|
|
- ECharts.prototype.getOption = function () {
|
|
|
- return this._model && this._model.getOption();
|
|
|
- };
|
|
|
- ECharts.prototype.getWidth = function () {
|
|
|
- return this._zr.getWidth();
|
|
|
- };
|
|
|
- ECharts.prototype.getHeight = function () {
|
|
|
- return this._zr.getHeight();
|
|
|
- };
|
|
|
- ECharts.prototype.getDevicePixelRatio = function () {
|
|
|
- return this._zr.painter.dpr
|
|
|
- /* eslint-disable-next-line */ || env.hasGlobalWindow && window.devicePixelRatio || 1;
|
|
|
- };
|
|
|
- /**
|
|
|
- * Get canvas which has all thing rendered
|
|
|
- * @deprecated Use renderToCanvas instead.
|
|
|
- */
|
|
|
- ECharts.prototype.getRenderedCanvas = function (opts) {
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
- deprecateReplaceLog('getRenderedCanvas', 'renderToCanvas');
|
|
|
- }
|
|
|
- return this.renderToCanvas(opts);
|
|
|
- };
|
|
|
- ECharts.prototype.renderToCanvas = function (opts) {
|
|
|
- opts = opts || {};
|
|
|
- var painter = this._zr.painter;
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
- if (painter.type !== 'canvas') {
|
|
|
- throw new Error('renderToCanvas can only be used in the canvas renderer.');
|
|
|
- }
|
|
|
- }
|
|
|
- return painter.getRenderedCanvas({
|
|
|
- backgroundColor: opts.backgroundColor || this._model.get('backgroundColor'),
|
|
|
- pixelRatio: opts.pixelRatio || this.getDevicePixelRatio()
|
|
|
- });
|
|
|
- };
|
|
|
- ECharts.prototype.renderToSVGString = function (opts) {
|
|
|
- opts = opts || {};
|
|
|
- var painter = this._zr.painter;
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
- if (painter.type !== 'svg') {
|
|
|
- throw new Error('renderToSVGString can only be used in the svg renderer.');
|
|
|
- }
|
|
|
- }
|
|
|
- return painter.renderToString({
|
|
|
- useViewBox: opts.useViewBox
|
|
|
- });
|
|
|
- };
|
|
|
- /**
|
|
|
- * Get svg data url
|
|
|
- */
|
|
|
- ECharts.prototype.getSvgDataURL = function () {
|
|
|
- if (!env.svgSupported) {
|
|
|
- return;
|
|
|
- }
|
|
|
- var zr = this._zr;
|
|
|
- var list = zr.storage.getDisplayList();
|
|
|
- // Stop animations
|
|
|
- each(list, function (el) {
|
|
|
- el.stopAnimation(null, true);
|
|
|
- });
|
|
|
- return zr.painter.toDataURL();
|
|
|
- };
|
|
|
- ECharts.prototype.getDataURL = function (opts) {
|
|
|
- if (this._disposed) {
|
|
|
- disposedWarning(this.id);
|
|
|
- return;
|
|
|
- }
|
|
|
- opts = opts || {};
|
|
|
- var excludeComponents = opts.excludeComponents;
|
|
|
- var ecModel = this._model;
|
|
|
- var excludesComponentViews = [];
|
|
|
- var self = this;
|
|
|
- each(excludeComponents, function (componentType) {
|
|
|
- ecModel.eachComponent({
|
|
|
- mainType: componentType
|
|
|
- }, function (component) {
|
|
|
- var view = self._componentsMap[component.__viewId];
|
|
|
- if (!view.group.ignore) {
|
|
|
- excludesComponentViews.push(view);
|
|
|
- view.group.ignore = true;
|
|
|
- }
|
|
|
- });
|
|
|
- });
|
|
|
- var url = this._zr.painter.getType() === 'svg' ? this.getSvgDataURL() : this.renderToCanvas(opts).toDataURL('image/' + (opts && opts.type || 'png'));
|
|
|
- each(excludesComponentViews, function (view) {
|
|
|
- view.group.ignore = false;
|
|
|
- });
|
|
|
- return url;
|
|
|
- };
|
|
|
- ECharts.prototype.getConnectedDataURL = function (opts) {
|
|
|
- if (this._disposed) {
|
|
|
- disposedWarning(this.id);
|
|
|
- return;
|
|
|
- }
|
|
|
- var isSvg = opts.type === 'svg';
|
|
|
- var groupId = this.group;
|
|
|
- var mathMin = Math.min;
|
|
|
- var mathMax = Math.max;
|
|
|
- var MAX_NUMBER = Infinity;
|
|
|
- if (connectedGroups[groupId]) {
|
|
|
- var left_1 = MAX_NUMBER;
|
|
|
- var top_1 = MAX_NUMBER;
|
|
|
- var right_1 = -MAX_NUMBER;
|
|
|
- var bottom_1 = -MAX_NUMBER;
|
|
|
- var canvasList_1 = [];
|
|
|
- var dpr_1 = opts && opts.pixelRatio || this.getDevicePixelRatio();
|
|
|
- each(instances, function (chart, id) {
|
|
|
- if (chart.group === groupId) {
|
|
|
- var canvas = isSvg ? chart.getZr().painter.getSvgDom().innerHTML : chart.renderToCanvas(clone(opts));
|
|
|
- var boundingRect = chart.getDom().getBoundingClientRect();
|
|
|
- left_1 = mathMin(boundingRect.left, left_1);
|
|
|
- top_1 = mathMin(boundingRect.top, top_1);
|
|
|
- right_1 = mathMax(boundingRect.right, right_1);
|
|
|
- bottom_1 = mathMax(boundingRect.bottom, bottom_1);
|
|
|
- canvasList_1.push({
|
|
|
- dom: canvas,
|
|
|
- left: boundingRect.left,
|
|
|
- top: boundingRect.top
|
|
|
- });
|
|
|
- }
|
|
|
- });
|
|
|
- left_1 *= dpr_1;
|
|
|
- top_1 *= dpr_1;
|
|
|
- right_1 *= dpr_1;
|
|
|
- bottom_1 *= dpr_1;
|
|
|
- var width = right_1 - left_1;
|
|
|
- var height = bottom_1 - top_1;
|
|
|
- var targetCanvas = platformApi.createCanvas();
|
|
|
- var zr_1 = zrender.init(targetCanvas, {
|
|
|
- renderer: isSvg ? 'svg' : 'canvas'
|
|
|
- });
|
|
|
- zr_1.resize({
|
|
|
- width: width,
|
|
|
- height: height
|
|
|
- });
|
|
|
- if (isSvg) {
|
|
|
- var content_1 = '';
|
|
|
- each(canvasList_1, function (item) {
|
|
|
- var x = item.left - left_1;
|
|
|
- var y = item.top - top_1;
|
|
|
- content_1 += '<g transform="translate(' + x + ',' + y + ')">' + item.dom + '</g>';
|
|
|
- });
|
|
|
- zr_1.painter.getSvgRoot().innerHTML = content_1;
|
|
|
- if (opts.connectedBackgroundColor) {
|
|
|
- zr_1.painter.setBackgroundColor(opts.connectedBackgroundColor);
|
|
|
- }
|
|
|
- zr_1.refreshImmediately();
|
|
|
- return zr_1.painter.toDataURL();
|
|
|
- } else {
|
|
|
- // Background between the charts
|
|
|
- if (opts.connectedBackgroundColor) {
|
|
|
- zr_1.add(new graphic.Rect({
|
|
|
- shape: {
|
|
|
- x: 0,
|
|
|
- y: 0,
|
|
|
- width: width,
|
|
|
- height: height
|
|
|
- },
|
|
|
- style: {
|
|
|
- fill: opts.connectedBackgroundColor
|
|
|
- }
|
|
|
- }));
|
|
|
- }
|
|
|
- each(canvasList_1, function (item) {
|
|
|
- var img = new graphic.Image({
|
|
|
- style: {
|
|
|
- x: item.left * dpr_1 - left_1,
|
|
|
- y: item.top * dpr_1 - top_1,
|
|
|
- image: item.dom
|
|
|
- }
|
|
|
- });
|
|
|
- zr_1.add(img);
|
|
|
- });
|
|
|
- zr_1.refreshImmediately();
|
|
|
- return targetCanvas.toDataURL('image/' + (opts && opts.type || 'png'));
|
|
|
- }
|
|
|
- } else {
|
|
|
- return this.getDataURL(opts);
|
|
|
- }
|
|
|
- };
|
|
|
- ECharts.prototype.convertToPixel = function (finder, value) {
|
|
|
- return doConvertPixel(this, 'convertToPixel', finder, value);
|
|
|
- };
|
|
|
- ECharts.prototype.convertFromPixel = function (finder, value) {
|
|
|
- return doConvertPixel(this, 'convertFromPixel', finder, value);
|
|
|
- };
|
|
|
- /**
|
|
|
- * Is the specified coordinate systems or components contain the given pixel point.
|
|
|
- * @param {Array|number} value
|
|
|
- * @return {boolean} result
|
|
|
- */
|
|
|
- ECharts.prototype.containPixel = function (finder, value) {
|
|
|
- if (this._disposed) {
|
|
|
- disposedWarning(this.id);
|
|
|
- return;
|
|
|
- }
|
|
|
- var ecModel = this._model;
|
|
|
- var result;
|
|
|
- var findResult = modelUtil.parseFinder(ecModel, finder);
|
|
|
- each(findResult, function (models, key) {
|
|
|
- key.indexOf('Models') >= 0 && each(models, function (model) {
|
|
|
- var coordSys = model.coordinateSystem;
|
|
|
- if (coordSys && coordSys.containPoint) {
|
|
|
- result = result || !!coordSys.containPoint(value);
|
|
|
- } else if (key === 'seriesModels') {
|
|
|
- var view = this._chartsMap[model.__viewId];
|
|
|
- if (view && view.containPoint) {
|
|
|
- result = result || view.containPoint(value, model);
|
|
|
- } else {
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
- warn(key + ': ' + (view ? 'The found component do not support containPoint.' : 'No view mapping to the found component.'));
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
- warn(key + ': containPoint is not supported');
|
|
|
- }
|
|
|
- }
|
|
|
- }, this);
|
|
|
- }, this);
|
|
|
- return !!result;
|
|
|
- };
|
|
|
- /**
|
|
|
- * Get visual from series or data.
|
|
|
- * @param finder
|
|
|
- * If string, e.g., 'series', means {seriesIndex: 0}.
|
|
|
- * If Object, could contain some of these properties below:
|
|
|
- * {
|
|
|
- * seriesIndex / seriesId / seriesName,
|
|
|
- * dataIndex / dataIndexInside
|
|
|
- * }
|
|
|
- * If dataIndex is not specified, series visual will be fetched,
|
|
|
- * but not data item visual.
|
|
|
- * If all of seriesIndex, seriesId, seriesName are not specified,
|
|
|
- * visual will be fetched from first series.
|
|
|
- * @param visualType 'color', 'symbol', 'symbolSize'
|
|
|
- */
|
|
|
- ECharts.prototype.getVisual = function (finder, visualType) {
|
|
|
- var ecModel = this._model;
|
|
|
- var parsedFinder = modelUtil.parseFinder(ecModel, finder, {
|
|
|
- defaultMainType: 'series'
|
|
|
- });
|
|
|
- var seriesModel = parsedFinder.seriesModel;
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
- if (!seriesModel) {
|
|
|
- warn('There is no specified series model');
|
|
|
- }
|
|
|
- }
|
|
|
- var data = seriesModel.getData();
|
|
|
- var dataIndexInside = parsedFinder.hasOwnProperty('dataIndexInside') ? parsedFinder.dataIndexInside : parsedFinder.hasOwnProperty('dataIndex') ? data.indexOfRawIndex(parsedFinder.dataIndex) : null;
|
|
|
- return dataIndexInside != null ? getItemVisualFromData(data, dataIndexInside, visualType) : getVisualFromData(data, visualType);
|
|
|
- };
|
|
|
- /**
|
|
|
- * Get view of corresponding component model
|
|
|
- */
|
|
|
- ECharts.prototype.getViewOfComponentModel = function (componentModel) {
|
|
|
- return this._componentsMap[componentModel.__viewId];
|
|
|
- };
|
|
|
- /**
|
|
|
- * Get view of corresponding series model
|
|
|
- */
|
|
|
- ECharts.prototype.getViewOfSeriesModel = function (seriesModel) {
|
|
|
- return this._chartsMap[seriesModel.__viewId];
|
|
|
- };
|
|
|
- ECharts.prototype._initEvents = function () {
|
|
|
- var _this = this;
|
|
|
- each(MOUSE_EVENT_NAMES, function (eveName) {
|
|
|
- var handler = function (e) {
|
|
|
- var ecModel = _this.getModel();
|
|
|
- var el = e.target;
|
|
|
- var params;
|
|
|
- var isGlobalOut = eveName === 'globalout';
|
|
|
- // no e.target when 'globalout'.
|
|
|
- if (isGlobalOut) {
|
|
|
- params = {};
|
|
|
- } else {
|
|
|
- el && findEventDispatcher(el, function (parent) {
|
|
|
- var ecData = getECData(parent);
|
|
|
- if (ecData && ecData.dataIndex != null) {
|
|
|
- var dataModel = ecData.dataModel || ecModel.getSeriesByIndex(ecData.seriesIndex);
|
|
|
- params = dataModel && dataModel.getDataParams(ecData.dataIndex, ecData.dataType, el) || {};
|
|
|
- return true;
|
|
|
- }
|
|
|
- // If element has custom eventData of components
|
|
|
- else if (ecData.eventData) {
|
|
|
- params = extend({}, ecData.eventData);
|
|
|
- return true;
|
|
|
- }
|
|
|
- }, true);
|
|
|
- }
|
|
|
- // Contract: if params prepared in mouse event,
|
|
|
- // these properties must be specified:
|
|
|
- // {
|
|
|
- // componentType: string (component main type)
|
|
|
- // componentIndex: number
|
|
|
- // }
|
|
|
- // Otherwise event query can not work.
|
|
|
- if (params) {
|
|
|
- var componentType = params.componentType;
|
|
|
- var componentIndex = params.componentIndex;
|
|
|
- // Special handling for historic reason: when trigger by
|
|
|
- // markLine/markPoint/markArea, the componentType is
|
|
|
- // 'markLine'/'markPoint'/'markArea', but we should better
|
|
|
- // enable them to be queried by seriesIndex, since their
|
|
|
- // option is set in each series.
|
|
|
- if (componentType === 'markLine' || componentType === 'markPoint' || componentType === 'markArea') {
|
|
|
- componentType = 'series';
|
|
|
- componentIndex = params.seriesIndex;
|
|
|
- }
|
|
|
- var model = componentType && componentIndex != null && ecModel.getComponent(componentType, componentIndex);
|
|
|
- var view = model && _this[model.mainType === 'series' ? '_chartsMap' : '_componentsMap'][model.__viewId];
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
- // `event.componentType` and `event[componentTpype + 'Index']` must not
|
|
|
- // be missed, otherwise there is no way to distinguish source component.
|
|
|
- // See `dataFormat.getDataParams`.
|
|
|
- if (!isGlobalOut && !(model && view)) {
|
|
|
- warn('model or view can not be found by params');
|
|
|
- }
|
|
|
- }
|
|
|
- params.event = e;
|
|
|
- params.type = eveName;
|
|
|
- _this._$eventProcessor.eventInfo = {
|
|
|
- targetEl: el,
|
|
|
- packedEvent: params,
|
|
|
- model: model,
|
|
|
- view: view
|
|
|
- };
|
|
|
- _this.trigger(eveName, params);
|
|
|
- }
|
|
|
- };
|
|
|
- // Consider that some component (like tooltip, brush, ...)
|
|
|
- // register zr event handler, but user event handler might
|
|
|
- // do anything, such as call `setOption` or `dispatchAction`,
|
|
|
- // which probably update any of the content and probably
|
|
|
- // cause problem if it is called previous other inner handlers.
|
|
|
- handler.zrEventfulCallAtLast = true;
|
|
|
- _this._zr.on(eveName, handler, _this);
|
|
|
- });
|
|
|
- each(eventActionMap, function (actionType, eventType) {
|
|
|
- _this._messageCenter.on(eventType, function (event) {
|
|
|
- this.trigger(eventType, event);
|
|
|
- }, _this);
|
|
|
- });
|
|
|
- // Extra events
|
|
|
- // TODO register?
|
|
|
- each(['selectchanged'], function (eventType) {
|
|
|
- _this._messageCenter.on(eventType, function (event) {
|
|
|
- this.trigger(eventType, event);
|
|
|
- }, _this);
|
|
|
- });
|
|
|
- handleLegacySelectEvents(this._messageCenter, this, this._api);
|
|
|
- };
|
|
|
- ECharts.prototype.isDisposed = function () {
|
|
|
- return this._disposed;
|
|
|
- };
|
|
|
- ECharts.prototype.clear = function () {
|
|
|
- if (this._disposed) {
|
|
|
- disposedWarning(this.id);
|
|
|
- return;
|
|
|
- }
|
|
|
- this.setOption({
|
|
|
- series: []
|
|
|
- }, true);
|
|
|
- };
|
|
|
- ECharts.prototype.dispose = function () {
|
|
|
- if (this._disposed) {
|
|
|
- disposedWarning(this.id);
|
|
|
- return;
|
|
|
- }
|
|
|
- this._disposed = true;
|
|
|
- var dom = this.getDom();
|
|
|
- if (dom) {
|
|
|
- modelUtil.setAttribute(this.getDom(), DOM_ATTRIBUTE_KEY, '');
|
|
|
- }
|
|
|
- var chart = this;
|
|
|
- var api = chart._api;
|
|
|
- var ecModel = chart._model;
|
|
|
- each(chart._componentsViews, function (component) {
|
|
|
- component.dispose(ecModel, api);
|
|
|
- });
|
|
|
- each(chart._chartsViews, function (chart) {
|
|
|
- chart.dispose(ecModel, api);
|
|
|
- });
|
|
|
- // Dispose after all views disposed
|
|
|
- chart._zr.dispose();
|
|
|
- // Set properties to null.
|
|
|
- // To reduce the memory cost in case the top code still holds this instance unexpectedly.
|
|
|
- chart._dom = chart._model = chart._chartsMap = chart._componentsMap = chart._chartsViews = chart._componentsViews = chart._scheduler = chart._api = chart._zr = chart._throttledZrFlush = chart._theme = chart._coordSysMgr = chart._messageCenter = null;
|
|
|
- delete instances[chart.id];
|
|
|
- };
|
|
|
- /**
|
|
|
- * Resize the chart
|
|
|
- */
|
|
|
- ECharts.prototype.resize = function (opts) {
|
|
|
- if (this[IN_MAIN_PROCESS_KEY]) {
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
- error('`resize` should not be called during main process.');
|
|
|
- }
|
|
|
- return;
|
|
|
- }
|
|
|
- if (this._disposed) {
|
|
|
- disposedWarning(this.id);
|
|
|
- return;
|
|
|
- }
|
|
|
- this._zr.resize(opts);
|
|
|
- var ecModel = this._model;
|
|
|
- // Resize loading effect
|
|
|
- this._loadingFX && this._loadingFX.resize();
|
|
|
- if (!ecModel) {
|
|
|
- return;
|
|
|
- }
|
|
|
- var needPrepare = ecModel.resetOption('media');
|
|
|
- var silent = opts && opts.silent;
|
|
|
- // There is some real cases that:
|
|
|
- // chart.setOption(option, { lazyUpdate: true });
|
|
|
- // chart.resize();
|
|
|
- if (this[PENDING_UPDATE]) {
|
|
|
- if (silent == null) {
|
|
|
- silent = this[PENDING_UPDATE].silent;
|
|
|
- }
|
|
|
- needPrepare = true;
|
|
|
- this[PENDING_UPDATE] = null;
|
|
|
- }
|
|
|
- this[IN_MAIN_PROCESS_KEY] = true;
|
|
|
- try {
|
|
|
- needPrepare && prepare(this);
|
|
|
- updateMethods.update.call(this, {
|
|
|
- type: 'resize',
|
|
|
- animation: extend({
|
|
|
- // Disable animation
|
|
|
- duration: 0
|
|
|
- }, opts && opts.animation)
|
|
|
- });
|
|
|
- } catch (e) {
|
|
|
- this[IN_MAIN_PROCESS_KEY] = false;
|
|
|
- throw e;
|
|
|
- }
|
|
|
- this[IN_MAIN_PROCESS_KEY] = false;
|
|
|
- flushPendingActions.call(this, silent);
|
|
|
- triggerUpdatedEvent.call(this, silent);
|
|
|
- };
|
|
|
- ECharts.prototype.showLoading = function (name, cfg) {
|
|
|
- if (this._disposed) {
|
|
|
- disposedWarning(this.id);
|
|
|
- return;
|
|
|
- }
|
|
|
- if (isObject(name)) {
|
|
|
- cfg = name;
|
|
|
- name = '';
|
|
|
- }
|
|
|
- name = name || 'default';
|
|
|
- this.hideLoading();
|
|
|
- if (!loadingEffects[name]) {
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
- warn('Loading effects ' + name + ' not exists.');
|
|
|
- }
|
|
|
- return;
|
|
|
- }
|
|
|
- var el = loadingEffects[name](this._api, cfg);
|
|
|
- var zr = this._zr;
|
|
|
- this._loadingFX = el;
|
|
|
- zr.add(el);
|
|
|
- };
|
|
|
- /**
|
|
|
- * Hide loading effect
|
|
|
- */
|
|
|
- ECharts.prototype.hideLoading = function () {
|
|
|
- if (this._disposed) {
|
|
|
- disposedWarning(this.id);
|
|
|
- return;
|
|
|
- }
|
|
|
- this._loadingFX && this._zr.remove(this._loadingFX);
|
|
|
- this._loadingFX = null;
|
|
|
- };
|
|
|
- ECharts.prototype.makeActionFromEvent = function (eventObj) {
|
|
|
- var payload = extend({}, eventObj);
|
|
|
- payload.type = eventActionMap[eventObj.type];
|
|
|
- return payload;
|
|
|
- };
|
|
|
- /**
|
|
|
- * @param opt If pass boolean, means opt.silent
|
|
|
- * @param opt.silent Default `false`. Whether trigger events.
|
|
|
- * @param opt.flush Default `undefined`.
|
|
|
- * true: Flush immediately, and then pixel in canvas can be fetched
|
|
|
- * immediately. Caution: it might affect performance.
|
|
|
- * false: Not flush.
|
|
|
- * undefined: Auto decide whether perform flush.
|
|
|
- */
|
|
|
- ECharts.prototype.dispatchAction = function (payload, opt) {
|
|
|
- if (this._disposed) {
|
|
|
- disposedWarning(this.id);
|
|
|
- return;
|
|
|
- }
|
|
|
- if (!isObject(opt)) {
|
|
|
- opt = {
|
|
|
- silent: !!opt
|
|
|
- };
|
|
|
- }
|
|
|
- if (!actions[payload.type]) {
|
|
|
- return;
|
|
|
- }
|
|
|
- // Avoid dispatch action before setOption. Especially in `connect`.
|
|
|
- if (!this._model) {
|
|
|
- return;
|
|
|
- }
|
|
|
- // May dispatchAction in rendering procedure
|
|
|
- if (this[IN_MAIN_PROCESS_KEY]) {
|
|
|
- this._pendingActions.push(payload);
|
|
|
- return;
|
|
|
- }
|
|
|
- var silent = opt.silent;
|
|
|
- doDispatchAction.call(this, payload, silent);
|
|
|
- var flush = opt.flush;
|
|
|
- if (flush) {
|
|
|
- this._zr.flush();
|
|
|
- } else if (flush !== false && env.browser.weChat) {
|
|
|
- // In WeChat embedded browser, `requestAnimationFrame` and `setInterval`
|
|
|
- // hang when sliding page (on touch event), which cause that zr does not
|
|
|
- // refresh until user interaction finished, which is not expected.
|
|
|
- // But `dispatchAction` may be called too frequently when pan on touch
|
|
|
- // screen, which impacts performance if do not throttle them.
|
|
|
- this._throttledZrFlush();
|
|
|
- }
|
|
|
- flushPendingActions.call(this, silent);
|
|
|
- triggerUpdatedEvent.call(this, silent);
|
|
|
- };
|
|
|
- ECharts.prototype.updateLabelLayout = function () {
|
|
|
- lifecycle.trigger('series:layoutlabels', this._model, this._api, {
|
|
|
- // Not adding series labels.
|
|
|
- // TODO
|
|
|
- updatedSeries: []
|
|
|
- });
|
|
|
- };
|
|
|
- ECharts.prototype.appendData = function (params) {
|
|
|
- if (this._disposed) {
|
|
|
- disposedWarning(this.id);
|
|
|
- return;
|
|
|
- }
|
|
|
- var seriesIndex = params.seriesIndex;
|
|
|
- var ecModel = this.getModel();
|
|
|
- var seriesModel = ecModel.getSeriesByIndex(seriesIndex);
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
- assert(params.data && seriesModel);
|
|
|
- }
|
|
|
- seriesModel.appendData(params);
|
|
|
- // Note: `appendData` does not support that update extent of coordinate
|
|
|
- // system, util some scenario require that. In the expected usage of
|
|
|
- // `appendData`, the initial extent of coordinate system should better
|
|
|
- // be fixed by axis `min`/`max` setting or initial data, otherwise if
|
|
|
- // the extent changed while `appendData`, the location of the painted
|
|
|
- // graphic elements have to be changed, which make the usage of
|
|
|
- // `appendData` meaningless.
|
|
|
- this._scheduler.unfinished = true;
|
|
|
- this.getZr().wakeUp();
|
|
|
- };
|
|
|
- // A work around for no `internal` modifier in ts yet but
|
|
|
- // need to strictly hide private methods to JS users.
|
|
|
- ECharts.internalField = function () {
|
|
|
- prepare = function (ecIns) {
|
|
|
- var scheduler = ecIns._scheduler;
|
|
|
- scheduler.restorePipelines(ecIns._model);
|
|
|
- scheduler.prepareStageTasks();
|
|
|
- prepareView(ecIns, true);
|
|
|
- prepareView(ecIns, false);
|
|
|
- scheduler.plan();
|
|
|
- };
|
|
|
- /**
|
|
|
- * Prepare view instances of charts and components
|
|
|
- */
|
|
|
- prepareView = function (ecIns, isComponent) {
|
|
|
- var ecModel = ecIns._model;
|
|
|
- var scheduler = ecIns._scheduler;
|
|
|
- var viewList = isComponent ? ecIns._componentsViews : ecIns._chartsViews;
|
|
|
- var viewMap = isComponent ? ecIns._componentsMap : ecIns._chartsMap;
|
|
|
- var zr = ecIns._zr;
|
|
|
- var api = ecIns._api;
|
|
|
- for (var i = 0; i < viewList.length; i++) {
|
|
|
- viewList[i].__alive = false;
|
|
|
- }
|
|
|
- isComponent ? ecModel.eachComponent(function (componentType, model) {
|
|
|
- componentType !== 'series' && doPrepare(model);
|
|
|
- }) : ecModel.eachSeries(doPrepare);
|
|
|
- function doPrepare(model) {
|
|
|
- // By default view will be reused if possible for the case that `setOption` with "notMerge"
|
|
|
- // mode and need to enable transition animation. (Usually, when they have the same id, or
|
|
|
- // especially no id but have the same type & name & index. See the `model.id` generation
|
|
|
- // rule in `makeIdAndName` and `viewId` generation rule here).
|
|
|
- // But in `replaceMerge` mode, this feature should be able to disabled when it is clear that
|
|
|
- // the new model has nothing to do with the old model.
|
|
|
- var requireNewView = model.__requireNewView;
|
|
|
- // This command should not work twice.
|
|
|
- model.__requireNewView = false;
|
|
|
- // Consider: id same and type changed.
|
|
|
- var viewId = '_ec_' + model.id + '_' + model.type;
|
|
|
- var view = !requireNewView && viewMap[viewId];
|
|
|
- if (!view) {
|
|
|
- var classType = parseClassType(model.type);
|
|
|
- var Clazz = isComponent ? ComponentView.getClass(classType.main, classType.sub) :
|
|
|
- // FIXME:TS
|
|
|
- // (ChartView as ChartViewConstructor).getClass('series', classType.sub)
|
|
|
- // For backward compat, still support a chart type declared as only subType
|
|
|
- // like "liquidfill", but recommend "series.liquidfill"
|
|
|
- // But need a base class to make a type series.
|
|
|
- ChartView.getClass(classType.sub);
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
- assert(Clazz, classType.sub + ' does not exist.');
|
|
|
- }
|
|
|
- view = new Clazz();
|
|
|
- view.init(ecModel, api);
|
|
|
- viewMap[viewId] = view;
|
|
|
- viewList.push(view);
|
|
|
- zr.add(view.group);
|
|
|
- }
|
|
|
- model.__viewId = view.__id = viewId;
|
|
|
- view.__alive = true;
|
|
|
- view.__model = model;
|
|
|
- view.group.__ecComponentInfo = {
|
|
|
- mainType: model.mainType,
|
|
|
- index: model.componentIndex
|
|
|
- };
|
|
|
- !isComponent && scheduler.prepareView(view, model, ecModel, api);
|
|
|
- }
|
|
|
- for (var i = 0; i < viewList.length;) {
|
|
|
- var view = viewList[i];
|
|
|
- if (!view.__alive) {
|
|
|
- !isComponent && view.renderTask.dispose();
|
|
|
- zr.remove(view.group);
|
|
|
- view.dispose(ecModel, api);
|
|
|
- viewList.splice(i, 1);
|
|
|
- if (viewMap[view.__id] === view) {
|
|
|
- delete viewMap[view.__id];
|
|
|
- }
|
|
|
- view.__id = view.group.__ecComponentInfo = null;
|
|
|
- } else {
|
|
|
- i++;
|
|
|
- }
|
|
|
- }
|
|
|
- };
|
|
|
- updateDirectly = function (ecIns, method, payload, mainType, subType) {
|
|
|
- var ecModel = ecIns._model;
|
|
|
- ecModel.setUpdatePayload(payload);
|
|
|
- // broadcast
|
|
|
- if (!mainType) {
|
|
|
- // FIXME
|
|
|
- // Chart will not be update directly here, except set dirty.
|
|
|
- // But there is no such scenario now.
|
|
|
- each([].concat(ecIns._componentsViews).concat(ecIns._chartsViews), callView);
|
|
|
- return;
|
|
|
- }
|
|
|
- var query = {};
|
|
|
- query[mainType + 'Id'] = payload[mainType + 'Id'];
|
|
|
- query[mainType + 'Index'] = payload[mainType + 'Index'];
|
|
|
- query[mainType + 'Name'] = payload[mainType + 'Name'];
|
|
|
- var condition = {
|
|
|
- mainType: mainType,
|
|
|
- query: query
|
|
|
- };
|
|
|
- subType && (condition.subType = subType); // subType may be '' by parseClassType;
|
|
|
- var excludeSeriesId = payload.excludeSeriesId;
|
|
|
- var excludeSeriesIdMap;
|
|
|
- if (excludeSeriesId != null) {
|
|
|
- excludeSeriesIdMap = createHashMap();
|
|
|
- each(modelUtil.normalizeToArray(excludeSeriesId), function (id) {
|
|
|
- var modelId = modelUtil.convertOptionIdName(id, null);
|
|
|
- if (modelId != null) {
|
|
|
- excludeSeriesIdMap.set(modelId, true);
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- // If dispatchAction before setOption, do nothing.
|
|
|
- ecModel && ecModel.eachComponent(condition, function (model) {
|
|
|
- var isExcluded = excludeSeriesIdMap && excludeSeriesIdMap.get(model.id) != null;
|
|
|
- if (isExcluded) {
|
|
|
- return;
|
|
|
- }
|
|
|
- ;
|
|
|
- if (isHighDownPayload(payload)) {
|
|
|
- if (model instanceof SeriesModel) {
|
|
|
- if (payload.type === HIGHLIGHT_ACTION_TYPE && !payload.notBlur && !model.get(['emphasis', 'disabled'])) {
|
|
|
- blurSeriesFromHighlightPayload(model, payload, ecIns._api);
|
|
|
- }
|
|
|
- } else {
|
|
|
- var _a = findComponentHighDownDispatchers(model.mainType, model.componentIndex, payload.name, ecIns._api),
|
|
|
- focusSelf = _a.focusSelf,
|
|
|
- dispatchers = _a.dispatchers;
|
|
|
- if (payload.type === HIGHLIGHT_ACTION_TYPE && focusSelf && !payload.notBlur) {
|
|
|
- blurComponent(model.mainType, model.componentIndex, ecIns._api);
|
|
|
- }
|
|
|
- // PENDING:
|
|
|
- // Whether to put this "enter emphasis" code in `ComponentView`,
|
|
|
- // which will be the same as `ChartView` but might be not necessary
|
|
|
- // and will be far from this logic.
|
|
|
- if (dispatchers) {
|
|
|
- each(dispatchers, function (dispatcher) {
|
|
|
- payload.type === HIGHLIGHT_ACTION_TYPE ? enterEmphasis(dispatcher) : leaveEmphasis(dispatcher);
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
- } else if (isSelectChangePayload(payload)) {
|
|
|
- // TODO geo
|
|
|
- if (model instanceof SeriesModel) {
|
|
|
- toggleSelectionFromPayload(model, payload, ecIns._api);
|
|
|
- updateSeriesElementSelection(model);
|
|
|
- markStatusToUpdate(ecIns);
|
|
|
- }
|
|
|
- }
|
|
|
- }, ecIns);
|
|
|
- ecModel && ecModel.eachComponent(condition, function (model) {
|
|
|
- var isExcluded = excludeSeriesIdMap && excludeSeriesIdMap.get(model.id) != null;
|
|
|
- if (isExcluded) {
|
|
|
- return;
|
|
|
- }
|
|
|
- ;
|
|
|
- callView(ecIns[mainType === 'series' ? '_chartsMap' : '_componentsMap'][model.__viewId]);
|
|
|
- }, ecIns);
|
|
|
- function callView(view) {
|
|
|
- view && view.__alive && view[method] && view[method](view.__model, ecModel, ecIns._api, payload);
|
|
|
- }
|
|
|
- };
|
|
|
- updateMethods = {
|
|
|
- prepareAndUpdate: function (payload) {
|
|
|
- prepare(this);
|
|
|
- updateMethods.update.call(this, payload, {
|
|
|
- // Needs to mark option changed if newOption is given.
|
|
|
- // It's from MagicType.
|
|
|
- // TODO If use a separate flag optionChanged in payload?
|
|
|
- optionChanged: payload.newOption != null
|
|
|
- });
|
|
|
- },
|
|
|
- update: function (payload, updateParams) {
|
|
|
- var ecModel = this._model;
|
|
|
- var api = this._api;
|
|
|
- var zr = this._zr;
|
|
|
- var coordSysMgr = this._coordSysMgr;
|
|
|
- var scheduler = this._scheduler;
|
|
|
- // update before setOption
|
|
|
- if (!ecModel) {
|
|
|
- return;
|
|
|
- }
|
|
|
- ecModel.setUpdatePayload(payload);
|
|
|
- scheduler.restoreData(ecModel, payload);
|
|
|
- scheduler.performSeriesTasks(ecModel);
|
|
|
- // TODO
|
|
|
- // Save total ecModel here for undo/redo (after restoring data and before processing data).
|
|
|
- // Undo (restoration of total ecModel) can be carried out in 'action' or outside API call.
|
|
|
- // Create new coordinate system each update
|
|
|
- // In LineView may save the old coordinate system and use it to get the original point.
|
|
|
- coordSysMgr.create(ecModel, api);
|
|
|
- scheduler.performDataProcessorTasks(ecModel, payload);
|
|
|
- // Current stream render is not supported in data process. So we can update
|
|
|
- // stream modes after data processing, where the filtered data is used to
|
|
|
- // determine whether to use progressive rendering.
|
|
|
- updateStreamModes(this, ecModel);
|
|
|
- // We update stream modes before coordinate system updated, then the modes info
|
|
|
- // can be fetched when coord sys updating (consider the barGrid extent fix). But
|
|
|
- // the drawback is the full coord info can not be fetched. Fortunately this full
|
|
|
- // coord is not required in stream mode updater currently.
|
|
|
- coordSysMgr.update(ecModel, api);
|
|
|
- clearColorPalette(ecModel);
|
|
|
- scheduler.performVisualTasks(ecModel, payload);
|
|
|
- render(this, ecModel, api, payload, updateParams);
|
|
|
- // Set background
|
|
|
- var backgroundColor = ecModel.get('backgroundColor') || 'transparent';
|
|
|
- var darkMode = ecModel.get('darkMode');
|
|
|
- zr.setBackgroundColor(backgroundColor);
|
|
|
- // Force set dark mode.
|
|
|
- if (darkMode != null && darkMode !== 'auto') {
|
|
|
- zr.setDarkMode(darkMode);
|
|
|
- }
|
|
|
- lifecycle.trigger('afterupdate', ecModel, api);
|
|
|
- },
|
|
|
- updateTransform: function (payload) {
|
|
|
- var _this = this;
|
|
|
- var ecModel = this._model;
|
|
|
- var api = this._api;
|
|
|
- // update before setOption
|
|
|
- if (!ecModel) {
|
|
|
- return;
|
|
|
- }
|
|
|
- ecModel.setUpdatePayload(payload);
|
|
|
- // ChartView.markUpdateMethod(payload, 'updateTransform');
|
|
|
- var componentDirtyList = [];
|
|
|
- ecModel.eachComponent(function (componentType, componentModel) {
|
|
|
- if (componentType === 'series') {
|
|
|
- return;
|
|
|
- }
|
|
|
- var componentView = _this.getViewOfComponentModel(componentModel);
|
|
|
- if (componentView && componentView.__alive) {
|
|
|
- if (componentView.updateTransform) {
|
|
|
- var result = componentView.updateTransform(componentModel, ecModel, api, payload);
|
|
|
- result && result.update && componentDirtyList.push(componentView);
|
|
|
- } else {
|
|
|
- componentDirtyList.push(componentView);
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- var seriesDirtyMap = createHashMap();
|
|
|
- ecModel.eachSeries(function (seriesModel) {
|
|
|
- var chartView = _this._chartsMap[seriesModel.__viewId];
|
|
|
- if (chartView.updateTransform) {
|
|
|
- var result = chartView.updateTransform(seriesModel, ecModel, api, payload);
|
|
|
- result && result.update && seriesDirtyMap.set(seriesModel.uid, 1);
|
|
|
- } else {
|
|
|
- seriesDirtyMap.set(seriesModel.uid, 1);
|
|
|
- }
|
|
|
- });
|
|
|
- clearColorPalette(ecModel);
|
|
|
- // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
|
|
|
- // this._scheduler.performVisualTasks(ecModel, payload, 'layout', true);
|
|
|
- this._scheduler.performVisualTasks(ecModel, payload, {
|
|
|
- setDirty: true,
|
|
|
- dirtyMap: seriesDirtyMap
|
|
|
- });
|
|
|
- // Currently, not call render of components. Geo render cost a lot.
|
|
|
- // renderComponents(ecIns, ecModel, api, payload, componentDirtyList);
|
|
|
- renderSeries(this, ecModel, api, payload, {}, seriesDirtyMap);
|
|
|
- lifecycle.trigger('afterupdate', ecModel, api);
|
|
|
- },
|
|
|
- updateView: function (payload) {
|
|
|
- var ecModel = this._model;
|
|
|
- // update before setOption
|
|
|
- if (!ecModel) {
|
|
|
- return;
|
|
|
- }
|
|
|
- ecModel.setUpdatePayload(payload);
|
|
|
- ChartView.markUpdateMethod(payload, 'updateView');
|
|
|
- clearColorPalette(ecModel);
|
|
|
- // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
|
|
|
- this._scheduler.performVisualTasks(ecModel, payload, {
|
|
|
- setDirty: true
|
|
|
- });
|
|
|
- render(this, ecModel, this._api, payload, {});
|
|
|
- lifecycle.trigger('afterupdate', ecModel, this._api);
|
|
|
- },
|
|
|
- updateVisual: function (payload) {
|
|
|
- // updateMethods.update.call(this, payload);
|
|
|
- var _this = this;
|
|
|
- var ecModel = this._model;
|
|
|
- // update before setOption
|
|
|
- if (!ecModel) {
|
|
|
- return;
|
|
|
- }
|
|
|
- ecModel.setUpdatePayload(payload);
|
|
|
- // clear all visual
|
|
|
- ecModel.eachSeries(function (seriesModel) {
|
|
|
- seriesModel.getData().clearAllVisual();
|
|
|
- });
|
|
|
- // Perform visual
|
|
|
- ChartView.markUpdateMethod(payload, 'updateVisual');
|
|
|
- clearColorPalette(ecModel);
|
|
|
- // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
|
|
|
- this._scheduler.performVisualTasks(ecModel, payload, {
|
|
|
- visualType: 'visual',
|
|
|
- setDirty: true
|
|
|
- });
|
|
|
- ecModel.eachComponent(function (componentType, componentModel) {
|
|
|
- if (componentType !== 'series') {
|
|
|
- var componentView = _this.getViewOfComponentModel(componentModel);
|
|
|
- componentView && componentView.__alive && componentView.updateVisual(componentModel, ecModel, _this._api, payload);
|
|
|
- }
|
|
|
- });
|
|
|
- ecModel.eachSeries(function (seriesModel) {
|
|
|
- var chartView = _this._chartsMap[seriesModel.__viewId];
|
|
|
- chartView.updateVisual(seriesModel, ecModel, _this._api, payload);
|
|
|
- });
|
|
|
- lifecycle.trigger('afterupdate', ecModel, this._api);
|
|
|
- },
|
|
|
- updateLayout: function (payload) {
|
|
|
- updateMethods.update.call(this, payload);
|
|
|
- }
|
|
|
- };
|
|
|
- doConvertPixel = function (ecIns, methodName, finder, value) {
|
|
|
- if (ecIns._disposed) {
|
|
|
- disposedWarning(ecIns.id);
|
|
|
- return;
|
|
|
- }
|
|
|
- var ecModel = ecIns._model;
|
|
|
- var coordSysList = ecIns._coordSysMgr.getCoordinateSystems();
|
|
|
- var result;
|
|
|
- var parsedFinder = modelUtil.parseFinder(ecModel, finder);
|
|
|
- for (var i = 0; i < coordSysList.length; i++) {
|
|
|
- var coordSys = coordSysList[i];
|
|
|
- if (coordSys[methodName] && (result = coordSys[methodName](ecModel, parsedFinder, value)) != null) {
|
|
|
- return result;
|
|
|
- }
|
|
|
- }
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
- warn('No coordinate system that supports ' + methodName + ' found by the given finder.');
|
|
|
- }
|
|
|
- };
|
|
|
- updateStreamModes = function (ecIns, ecModel) {
|
|
|
- var chartsMap = ecIns._chartsMap;
|
|
|
- var scheduler = ecIns._scheduler;
|
|
|
- ecModel.eachSeries(function (seriesModel) {
|
|
|
- scheduler.updateStreamModes(seriesModel, chartsMap[seriesModel.__viewId]);
|
|
|
- });
|
|
|
- };
|
|
|
- doDispatchAction = function (payload, silent) {
|
|
|
- var _this = this;
|
|
|
- var ecModel = this.getModel();
|
|
|
- var payloadType = payload.type;
|
|
|
- var escapeConnect = payload.escapeConnect;
|
|
|
- var actionWrap = actions[payloadType];
|
|
|
- var actionInfo = actionWrap.actionInfo;
|
|
|
- var cptTypeTmp = (actionInfo.update || 'update').split(':');
|
|
|
- var updateMethod = cptTypeTmp.pop();
|
|
|
- var cptType = cptTypeTmp[0] != null && parseClassType(cptTypeTmp[0]);
|
|
|
- this[IN_MAIN_PROCESS_KEY] = true;
|
|
|
- var payloads = [payload];
|
|
|
- var batched = false;
|
|
|
- // Batch action
|
|
|
- if (payload.batch) {
|
|
|
- batched = true;
|
|
|
- payloads = map(payload.batch, function (item) {
|
|
|
- item = defaults(extend({}, item), payload);
|
|
|
- item.batch = null;
|
|
|
- return item;
|
|
|
- });
|
|
|
- }
|
|
|
- var eventObjBatch = [];
|
|
|
- var eventObj;
|
|
|
- var isSelectChange = isSelectChangePayload(payload);
|
|
|
- var isHighDown = isHighDownPayload(payload);
|
|
|
- // Only leave blur once if there are multiple batches.
|
|
|
- if (isHighDown) {
|
|
|
- allLeaveBlur(this._api);
|
|
|
- }
|
|
|
- each(payloads, function (batchItem) {
|
|
|
- // Action can specify the event by return it.
|
|
|
- eventObj = actionWrap.action(batchItem, _this._model, _this._api);
|
|
|
- // Emit event outside
|
|
|
- eventObj = eventObj || extend({}, batchItem);
|
|
|
- // Convert type to eventType
|
|
|
- eventObj.type = actionInfo.event || eventObj.type;
|
|
|
- eventObjBatch.push(eventObj);
|
|
|
- // light update does not perform data process, layout and visual.
|
|
|
- if (isHighDown) {
|
|
|
- var _a = modelUtil.preParseFinder(payload),
|
|
|
- queryOptionMap = _a.queryOptionMap,
|
|
|
- mainTypeSpecified = _a.mainTypeSpecified;
|
|
|
- var componentMainType = mainTypeSpecified ? queryOptionMap.keys()[0] : 'series';
|
|
|
- updateDirectly(_this, updateMethod, batchItem, componentMainType);
|
|
|
- markStatusToUpdate(_this);
|
|
|
- } else if (isSelectChange) {
|
|
|
- // At present `dispatchAction({ type: 'select', ... })` is not supported on components.
|
|
|
- // geo still use 'geoselect'.
|
|
|
- updateDirectly(_this, updateMethod, batchItem, 'series');
|
|
|
- markStatusToUpdate(_this);
|
|
|
- } else if (cptType) {
|
|
|
- updateDirectly(_this, updateMethod, batchItem, cptType.main, cptType.sub);
|
|
|
- }
|
|
|
- });
|
|
|
- if (updateMethod !== 'none' && !isHighDown && !isSelectChange && !cptType) {
|
|
|
- try {
|
|
|
- // Still dirty
|
|
|
- if (this[PENDING_UPDATE]) {
|
|
|
- prepare(this);
|
|
|
- updateMethods.update.call(this, payload);
|
|
|
- this[PENDING_UPDATE] = null;
|
|
|
- } else {
|
|
|
- updateMethods[updateMethod].call(this, payload);
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- this[IN_MAIN_PROCESS_KEY] = false;
|
|
|
- throw e;
|
|
|
- }
|
|
|
- }
|
|
|
- // Follow the rule of action batch
|
|
|
- if (batched) {
|
|
|
- eventObj = {
|
|
|
- type: actionInfo.event || payloadType,
|
|
|
- escapeConnect: escapeConnect,
|
|
|
- batch: eventObjBatch
|
|
|
- };
|
|
|
- } else {
|
|
|
- eventObj = eventObjBatch[0];
|
|
|
- }
|
|
|
- this[IN_MAIN_PROCESS_KEY] = false;
|
|
|
- if (!silent) {
|
|
|
- var messageCenter = this._messageCenter;
|
|
|
- messageCenter.trigger(eventObj.type, eventObj);
|
|
|
- // Extra triggered 'selectchanged' event
|
|
|
- if (isSelectChange) {
|
|
|
- var newObj = {
|
|
|
- type: 'selectchanged',
|
|
|
- escapeConnect: escapeConnect,
|
|
|
- selected: getAllSelectedIndices(ecModel),
|
|
|
- isFromClick: payload.isFromClick || false,
|
|
|
- fromAction: payload.type,
|
|
|
- fromActionPayload: payload
|
|
|
- };
|
|
|
- messageCenter.trigger(newObj.type, newObj);
|
|
|
- }
|
|
|
- }
|
|
|
- };
|
|
|
- flushPendingActions = function (silent) {
|
|
|
- var pendingActions = this._pendingActions;
|
|
|
- while (pendingActions.length) {
|
|
|
- var payload = pendingActions.shift();
|
|
|
- doDispatchAction.call(this, payload, silent);
|
|
|
- }
|
|
|
- };
|
|
|
- triggerUpdatedEvent = function (silent) {
|
|
|
- !silent && this.trigger('updated');
|
|
|
- };
|
|
|
- /**
|
|
|
- * Event `rendered` is triggered when zr
|
|
|
- * rendered. It is useful for realtime
|
|
|
- * snapshot (reflect animation).
|
|
|
- *
|
|
|
- * Event `finished` is triggered when:
|
|
|
- * (1) zrender rendering finished.
|
|
|
- * (2) initial animation finished.
|
|
|
- * (3) progressive rendering finished.
|
|
|
- * (4) no pending action.
|
|
|
- * (5) no delayed setOption needs to be processed.
|
|
|
- */
|
|
|
- bindRenderedEvent = function (zr, ecIns) {
|
|
|
- zr.on('rendered', function (params) {
|
|
|
- ecIns.trigger('rendered', params);
|
|
|
- // The `finished` event should not be triggered repeatedly,
|
|
|
- // so it should only be triggered when rendering indeed happens
|
|
|
- // in zrender. (Consider the case that dipatchAction is keep
|
|
|
- // triggering when mouse move).
|
|
|
- if (
|
|
|
- // Although zr is dirty if initial animation is not finished
|
|
|
- // and this checking is called on frame, we also check
|
|
|
- // animation finished for robustness.
|
|
|
- zr.animation.isFinished() && !ecIns[PENDING_UPDATE] && !ecIns._scheduler.unfinished && !ecIns._pendingActions.length) {
|
|
|
- ecIns.trigger('finished');
|
|
|
- }
|
|
|
- });
|
|
|
- };
|
|
|
- bindMouseEvent = function (zr, ecIns) {
|
|
|
- zr.on('mouseover', function (e) {
|
|
|
- var el = e.target;
|
|
|
- var dispatcher = findEventDispatcher(el, isHighDownDispatcher);
|
|
|
- if (dispatcher) {
|
|
|
- handleGlobalMouseOverForHighDown(dispatcher, e, ecIns._api);
|
|
|
- markStatusToUpdate(ecIns);
|
|
|
- }
|
|
|
- }).on('mouseout', function (e) {
|
|
|
- var el = e.target;
|
|
|
- var dispatcher = findEventDispatcher(el, isHighDownDispatcher);
|
|
|
- if (dispatcher) {
|
|
|
- handleGlobalMouseOutForHighDown(dispatcher, e, ecIns._api);
|
|
|
- markStatusToUpdate(ecIns);
|
|
|
- }
|
|
|
- }).on('click', function (e) {
|
|
|
- var el = e.target;
|
|
|
- var dispatcher = findEventDispatcher(el, function (target) {
|
|
|
- return getECData(target).dataIndex != null;
|
|
|
- }, true);
|
|
|
- if (dispatcher) {
|
|
|
- var actionType = dispatcher.selected ? 'unselect' : 'select';
|
|
|
- var ecData = getECData(dispatcher);
|
|
|
- ecIns._api.dispatchAction({
|
|
|
- type: actionType,
|
|
|
- dataType: ecData.dataType,
|
|
|
- dataIndexInside: ecData.dataIndex,
|
|
|
- seriesIndex: ecData.seriesIndex,
|
|
|
- isFromClick: true
|
|
|
- });
|
|
|
- }
|
|
|
- });
|
|
|
- };
|
|
|
- function clearColorPalette(ecModel) {
|
|
|
- ecModel.clearColorPalette();
|
|
|
- ecModel.eachSeries(function (seriesModel) {
|
|
|
- seriesModel.clearColorPalette();
|
|
|
- });
|
|
|
- }
|
|
|
- ;
|
|
|
- // Allocate zlevels for series and components
|
|
|
- function allocateZlevels(ecModel) {
|
|
|
- ;
|
|
|
- var componentZLevels = [];
|
|
|
- var seriesZLevels = [];
|
|
|
- var hasSeparateZLevel = false;
|
|
|
- ecModel.eachComponent(function (componentType, componentModel) {
|
|
|
- var zlevel = componentModel.get('zlevel') || 0;
|
|
|
- var z = componentModel.get('z') || 0;
|
|
|
- var zlevelKey = componentModel.getZLevelKey();
|
|
|
- hasSeparateZLevel = hasSeparateZLevel || !!zlevelKey;
|
|
|
- (componentType === 'series' ? seriesZLevels : componentZLevels).push({
|
|
|
- zlevel: zlevel,
|
|
|
- z: z,
|
|
|
- idx: componentModel.componentIndex,
|
|
|
- type: componentType,
|
|
|
- key: zlevelKey
|
|
|
- });
|
|
|
- });
|
|
|
- if (hasSeparateZLevel) {
|
|
|
- // Series after component
|
|
|
- var zLevels = componentZLevels.concat(seriesZLevels);
|
|
|
- var lastSeriesZLevel_1;
|
|
|
- var lastSeriesKey_1;
|
|
|
- timsort(zLevels, function (a, b) {
|
|
|
- if (a.zlevel === b.zlevel) {
|
|
|
- return a.z - b.z;
|
|
|
- }
|
|
|
- return a.zlevel - b.zlevel;
|
|
|
- });
|
|
|
- each(zLevels, function (item) {
|
|
|
- var componentModel = ecModel.getComponent(item.type, item.idx);
|
|
|
- var zlevel = item.zlevel;
|
|
|
- var key = item.key;
|
|
|
- if (lastSeriesZLevel_1 != null) {
|
|
|
- zlevel = Math.max(lastSeriesZLevel_1, zlevel);
|
|
|
- }
|
|
|
- if (key) {
|
|
|
- if (zlevel === lastSeriesZLevel_1 && key !== lastSeriesKey_1) {
|
|
|
- zlevel++;
|
|
|
- }
|
|
|
- lastSeriesKey_1 = key;
|
|
|
- } else if (lastSeriesKey_1) {
|
|
|
- if (zlevel === lastSeriesZLevel_1) {
|
|
|
- zlevel++;
|
|
|
- }
|
|
|
- lastSeriesKey_1 = '';
|
|
|
- }
|
|
|
- lastSeriesZLevel_1 = zlevel;
|
|
|
- componentModel.setZLevel(zlevel);
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
- render = function (ecIns, ecModel, api, payload, updateParams) {
|
|
|
- allocateZlevels(ecModel);
|
|
|
- renderComponents(ecIns, ecModel, api, payload, updateParams);
|
|
|
- each(ecIns._chartsViews, function (chart) {
|
|
|
- chart.__alive = false;
|
|
|
- });
|
|
|
- renderSeries(ecIns, ecModel, api, payload, updateParams);
|
|
|
- // Remove groups of unrendered charts
|
|
|
- each(ecIns._chartsViews, function (chart) {
|
|
|
- if (!chart.__alive) {
|
|
|
- chart.remove(ecModel, api);
|
|
|
- }
|
|
|
- });
|
|
|
- };
|
|
|
- renderComponents = function (ecIns, ecModel, api, payload, updateParams, dirtyList) {
|
|
|
- each(dirtyList || ecIns._componentsViews, function (componentView) {
|
|
|
- var componentModel = componentView.__model;
|
|
|
- clearStates(componentModel, componentView);
|
|
|
- componentView.render(componentModel, ecModel, api, payload);
|
|
|
- updateZ(componentModel, componentView);
|
|
|
- updateStates(componentModel, componentView);
|
|
|
- });
|
|
|
- };
|
|
|
- /**
|
|
|
- * Render each chart and component
|
|
|
- */
|
|
|
- renderSeries = function (ecIns, ecModel, api, payload, updateParams, dirtyMap) {
|
|
|
- // Render all charts
|
|
|
- var scheduler = ecIns._scheduler;
|
|
|
- updateParams = extend(updateParams || {}, {
|
|
|
- updatedSeries: ecModel.getSeries()
|
|
|
- });
|
|
|
- // TODO progressive?
|
|
|
- lifecycle.trigger('series:beforeupdate', ecModel, api, updateParams);
|
|
|
- var unfinished = false;
|
|
|
- ecModel.eachSeries(function (seriesModel) {
|
|
|
- var chartView = ecIns._chartsMap[seriesModel.__viewId];
|
|
|
- chartView.__alive = true;
|
|
|
- var renderTask = chartView.renderTask;
|
|
|
- scheduler.updatePayload(renderTask, payload);
|
|
|
- // TODO states on marker.
|
|
|
- clearStates(seriesModel, chartView);
|
|
|
- if (dirtyMap && dirtyMap.get(seriesModel.uid)) {
|
|
|
- renderTask.dirty();
|
|
|
- }
|
|
|
- if (renderTask.perform(scheduler.getPerformArgs(renderTask))) {
|
|
|
- unfinished = true;
|
|
|
- }
|
|
|
- chartView.group.silent = !!seriesModel.get('silent');
|
|
|
- // Should not call markRedraw on group, because it will disable zrender
|
|
|
- // incremental render (always render from the __startIndex each frame)
|
|
|
- // chartView.group.markRedraw();
|
|
|
- updateBlend(seriesModel, chartView);
|
|
|
- updateSeriesElementSelection(seriesModel);
|
|
|
- });
|
|
|
- scheduler.unfinished = unfinished || scheduler.unfinished;
|
|
|
- lifecycle.trigger('series:layoutlabels', ecModel, api, updateParams);
|
|
|
- // transition after label is layouted.
|
|
|
- lifecycle.trigger('series:transition', ecModel, api, updateParams);
|
|
|
- ecModel.eachSeries(function (seriesModel) {
|
|
|
- var chartView = ecIns._chartsMap[seriesModel.__viewId];
|
|
|
- // Update Z after labels updated. Before applying states.
|
|
|
- updateZ(seriesModel, chartView);
|
|
|
- // NOTE: Update states after label is updated.
|
|
|
- // label should be in normal status when layouting.
|
|
|
- updateStates(seriesModel, chartView);
|
|
|
- });
|
|
|
- // If use hover layer
|
|
|
- updateHoverLayerStatus(ecIns, ecModel);
|
|
|
- lifecycle.trigger('series:afterupdate', ecModel, api, updateParams);
|
|
|
- };
|
|
|
- markStatusToUpdate = function (ecIns) {
|
|
|
- ecIns[STATUS_NEEDS_UPDATE_KEY] = true;
|
|
|
- // Wake up zrender if it's sleep. Let it update states in the next frame.
|
|
|
- ecIns.getZr().wakeUp();
|
|
|
- };
|
|
|
- applyChangedStates = function (ecIns) {
|
|
|
- if (!ecIns[STATUS_NEEDS_UPDATE_KEY]) {
|
|
|
- return;
|
|
|
- }
|
|
|
- ecIns.getZr().storage.traverse(function (el) {
|
|
|
- // Not applied on removed elements, it may still in fading.
|
|
|
- if (graphic.isElementRemoved(el)) {
|
|
|
- return;
|
|
|
- }
|
|
|
- applyElementStates(el);
|
|
|
- });
|
|
|
- ecIns[STATUS_NEEDS_UPDATE_KEY] = false;
|
|
|
- };
|
|
|
- function applyElementStates(el) {
|
|
|
- var newStates = [];
|
|
|
- var oldStates = el.currentStates;
|
|
|
- // Keep other states.
|
|
|
- for (var i = 0; i < oldStates.length; i++) {
|
|
|
- var stateName = oldStates[i];
|
|
|
- if (!(stateName === 'emphasis' || stateName === 'blur' || stateName === 'select')) {
|
|
|
- newStates.push(stateName);
|
|
|
- }
|
|
|
- }
|
|
|
- // Only use states when it's exists.
|
|
|
- if (el.selected && el.states.select) {
|
|
|
- newStates.push('select');
|
|
|
- }
|
|
|
- if (el.hoverState === HOVER_STATE_EMPHASIS && el.states.emphasis) {
|
|
|
- newStates.push('emphasis');
|
|
|
- } else if (el.hoverState === HOVER_STATE_BLUR && el.states.blur) {
|
|
|
- newStates.push('blur');
|
|
|
- }
|
|
|
- el.useStates(newStates);
|
|
|
- }
|
|
|
- function updateHoverLayerStatus(ecIns, ecModel) {
|
|
|
- var zr = ecIns._zr;
|
|
|
- var storage = zr.storage;
|
|
|
- var elCount = 0;
|
|
|
- storage.traverse(function (el) {
|
|
|
- if (!el.isGroup) {
|
|
|
- elCount++;
|
|
|
- }
|
|
|
- });
|
|
|
- if (elCount > ecModel.get('hoverLayerThreshold') && !env.node && !env.worker) {
|
|
|
- ecModel.eachSeries(function (seriesModel) {
|
|
|
- if (seriesModel.preventUsingHoverLayer) {
|
|
|
- return;
|
|
|
- }
|
|
|
- var chartView = ecIns._chartsMap[seriesModel.__viewId];
|
|
|
- if (chartView.__alive) {
|
|
|
- chartView.eachRendered(function (el) {
|
|
|
- if (el.states.emphasis) {
|
|
|
- el.states.emphasis.hoverLayer = true;
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
- ;
|
|
|
- /**
|
|
|
- * Update chart and blend.
|
|
|
- */
|
|
|
- function updateBlend(seriesModel, chartView) {
|
|
|
- var blendMode = seriesModel.get('blendMode') || null;
|
|
|
- chartView.eachRendered(function (el) {
|
|
|
- // FIXME marker and other components
|
|
|
- if (!el.isGroup) {
|
|
|
- // DON'T mark the element dirty. In case element is incremental and don't want to rerender.
|
|
|
- el.style.blend = blendMode;
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- ;
|
|
|
- function updateZ(model, view) {
|
|
|
- if (model.preventAutoZ) {
|
|
|
- return;
|
|
|
- }
|
|
|
- var z = model.get('z') || 0;
|
|
|
- var zlevel = model.get('zlevel') || 0;
|
|
|
- // Set z and zlevel
|
|
|
- view.eachRendered(function (el) {
|
|
|
- doUpdateZ(el, z, zlevel, -Infinity);
|
|
|
- // Don't traverse the children because it has been traversed in _updateZ.
|
|
|
- return true;
|
|
|
- });
|
|
|
- }
|
|
|
- ;
|
|
|
- function doUpdateZ(el, z, zlevel, maxZ2) {
|
|
|
- // Group may also have textContent
|
|
|
- var label = el.getTextContent();
|
|
|
- var labelLine = el.getTextGuideLine();
|
|
|
- var isGroup = el.isGroup;
|
|
|
- if (isGroup) {
|
|
|
- // set z & zlevel of children elements of Group
|
|
|
- var children = el.childrenRef();
|
|
|
- for (var i = 0; i < children.length; i++) {
|
|
|
- maxZ2 = Math.max(doUpdateZ(children[i], z, zlevel, maxZ2), maxZ2);
|
|
|
- }
|
|
|
- } else {
|
|
|
- // not Group
|
|
|
- el.z = z;
|
|
|
- el.zlevel = zlevel;
|
|
|
- maxZ2 = Math.max(el.z2, maxZ2);
|
|
|
- }
|
|
|
- // always set z and zlevel if label/labelLine exists
|
|
|
- if (label) {
|
|
|
- label.z = z;
|
|
|
- label.zlevel = zlevel;
|
|
|
- // lift z2 of text content
|
|
|
- // TODO if el.emphasis.z2 is spcefied, what about textContent.
|
|
|
- isFinite(maxZ2) && (label.z2 = maxZ2 + 2);
|
|
|
- }
|
|
|
- if (labelLine) {
|
|
|
- var textGuideLineConfig = el.textGuideLineConfig;
|
|
|
- labelLine.z = z;
|
|
|
- labelLine.zlevel = zlevel;
|
|
|
- isFinite(maxZ2) && (labelLine.z2 = maxZ2 + (textGuideLineConfig && textGuideLineConfig.showAbove ? 1 : -1));
|
|
|
- }
|
|
|
- return maxZ2;
|
|
|
- }
|
|
|
- // Clear states without animation.
|
|
|
- // TODO States on component.
|
|
|
- function clearStates(model, view) {
|
|
|
- view.eachRendered(function (el) {
|
|
|
- // Not applied on removed elements, it may still in fading.
|
|
|
- if (graphic.isElementRemoved(el)) {
|
|
|
- return;
|
|
|
- }
|
|
|
- var textContent = el.getTextContent();
|
|
|
- var textGuide = el.getTextGuideLine();
|
|
|
- if (el.stateTransition) {
|
|
|
- el.stateTransition = null;
|
|
|
- }
|
|
|
- if (textContent && textContent.stateTransition) {
|
|
|
- textContent.stateTransition = null;
|
|
|
- }
|
|
|
- if (textGuide && textGuide.stateTransition) {
|
|
|
- textGuide.stateTransition = null;
|
|
|
- }
|
|
|
- // TODO If el is incremental.
|
|
|
- if (el.hasState()) {
|
|
|
- el.prevStates = el.currentStates;
|
|
|
- el.clearStates();
|
|
|
- } else if (el.prevStates) {
|
|
|
- el.prevStates = null;
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- function updateStates(model, view) {
|
|
|
- var stateAnimationModel = model.getModel('stateAnimation');
|
|
|
- var enableAnimation = model.isAnimationEnabled();
|
|
|
- var duration = stateAnimationModel.get('duration');
|
|
|
- var stateTransition = duration > 0 ? {
|
|
|
- duration: duration,
|
|
|
- delay: stateAnimationModel.get('delay'),
|
|
|
- easing: stateAnimationModel.get('easing')
|
|
|
- // additive: stateAnimationModel.get('additive')
|
|
|
- } : null;
|
|
|
- view.eachRendered(function (el) {
|
|
|
- if (el.states && el.states.emphasis) {
|
|
|
- // Not applied on removed elements, it may still in fading.
|
|
|
- if (graphic.isElementRemoved(el)) {
|
|
|
- return;
|
|
|
- }
|
|
|
- if (el instanceof graphic.Path) {
|
|
|
- savePathStates(el);
|
|
|
- }
|
|
|
- // Only updated on changed element. In case element is incremental and don't want to rerender.
|
|
|
- // TODO, a more proper way?
|
|
|
- if (el.__dirty) {
|
|
|
- var prevStates = el.prevStates;
|
|
|
- // Restore states without animation
|
|
|
- if (prevStates) {
|
|
|
- el.useStates(prevStates);
|
|
|
- }
|
|
|
- }
|
|
|
- // Update state transition and enable animation again.
|
|
|
- if (enableAnimation) {
|
|
|
- el.stateTransition = stateTransition;
|
|
|
- var textContent = el.getTextContent();
|
|
|
- var textGuide = el.getTextGuideLine();
|
|
|
- // TODO Is it necessary to animate label?
|
|
|
- if (textContent) {
|
|
|
- textContent.stateTransition = stateTransition;
|
|
|
- }
|
|
|
- if (textGuide) {
|
|
|
- textGuide.stateTransition = stateTransition;
|
|
|
- }
|
|
|
- }
|
|
|
- // Use highlighted and selected flag to toggle states.
|
|
|
- if (el.__dirty) {
|
|
|
- applyElementStates(el);
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- ;
|
|
|
- createExtensionAPI = function (ecIns) {
|
|
|
- return new ( /** @class */function (_super) {
|
|
|
- __extends(class_1, _super);
|
|
|
- function class_1() {
|
|
|
- return _super !== null && _super.apply(this, arguments) || this;
|
|
|
- }
|
|
|
- class_1.prototype.getCoordinateSystems = function () {
|
|
|
- return ecIns._coordSysMgr.getCoordinateSystems();
|
|
|
- };
|
|
|
- class_1.prototype.getComponentByElement = function (el) {
|
|
|
- while (el) {
|
|
|
- var modelInfo = el.__ecComponentInfo;
|
|
|
- if (modelInfo != null) {
|
|
|
- return ecIns._model.getComponent(modelInfo.mainType, modelInfo.index);
|
|
|
- }
|
|
|
- el = el.parent;
|
|
|
- }
|
|
|
- };
|
|
|
- class_1.prototype.enterEmphasis = function (el, highlightDigit) {
|
|
|
- enterEmphasis(el, highlightDigit);
|
|
|
- markStatusToUpdate(ecIns);
|
|
|
- };
|
|
|
- class_1.prototype.leaveEmphasis = function (el, highlightDigit) {
|
|
|
- leaveEmphasis(el, highlightDigit);
|
|
|
- markStatusToUpdate(ecIns);
|
|
|
- };
|
|
|
- class_1.prototype.enterBlur = function (el) {
|
|
|
- enterBlur(el);
|
|
|
- markStatusToUpdate(ecIns);
|
|
|
- };
|
|
|
- class_1.prototype.leaveBlur = function (el) {
|
|
|
- leaveBlur(el);
|
|
|
- markStatusToUpdate(ecIns);
|
|
|
- };
|
|
|
- class_1.prototype.enterSelect = function (el) {
|
|
|
- enterSelect(el);
|
|
|
- markStatusToUpdate(ecIns);
|
|
|
- };
|
|
|
- class_1.prototype.leaveSelect = function (el) {
|
|
|
- leaveSelect(el);
|
|
|
- markStatusToUpdate(ecIns);
|
|
|
- };
|
|
|
- class_1.prototype.getModel = function () {
|
|
|
- return ecIns.getModel();
|
|
|
- };
|
|
|
- class_1.prototype.getViewOfComponentModel = function (componentModel) {
|
|
|
- return ecIns.getViewOfComponentModel(componentModel);
|
|
|
- };
|
|
|
- class_1.prototype.getViewOfSeriesModel = function (seriesModel) {
|
|
|
- return ecIns.getViewOfSeriesModel(seriesModel);
|
|
|
- };
|
|
|
- return class_1;
|
|
|
- }(ExtensionAPI))(ecIns);
|
|
|
- };
|
|
|
- enableConnect = function (chart) {
|
|
|
- function updateConnectedChartsStatus(charts, status) {
|
|
|
- for (var i = 0; i < charts.length; i++) {
|
|
|
- var otherChart = charts[i];
|
|
|
- otherChart[CONNECT_STATUS_KEY] = status;
|
|
|
- }
|
|
|
- }
|
|
|
- each(eventActionMap, function (actionType, eventType) {
|
|
|
- chart._messageCenter.on(eventType, function (event) {
|
|
|
- if (connectedGroups[chart.group] && chart[CONNECT_STATUS_KEY] !== CONNECT_STATUS_PENDING) {
|
|
|
- if (event && event.escapeConnect) {
|
|
|
- return;
|
|
|
- }
|
|
|
- var action_1 = chart.makeActionFromEvent(event);
|
|
|
- var otherCharts_1 = [];
|
|
|
- each(instances, function (otherChart) {
|
|
|
- if (otherChart !== chart && otherChart.group === chart.group) {
|
|
|
- otherCharts_1.push(otherChart);
|
|
|
- }
|
|
|
- });
|
|
|
- updateConnectedChartsStatus(otherCharts_1, CONNECT_STATUS_PENDING);
|
|
|
- each(otherCharts_1, function (otherChart) {
|
|
|
- if (otherChart[CONNECT_STATUS_KEY] !== CONNECT_STATUS_UPDATING) {
|
|
|
- otherChart.dispatchAction(action_1);
|
|
|
- }
|
|
|
- });
|
|
|
- updateConnectedChartsStatus(otherCharts_1, CONNECT_STATUS_UPDATED);
|
|
|
- }
|
|
|
- });
|
|
|
- });
|
|
|
- };
|
|
|
- }();
|
|
|
- return ECharts;
|
|
|
-}(Eventful);
|
|
|
-var echartsProto = ECharts.prototype;
|
|
|
-echartsProto.on = createRegisterEventWithLowercaseECharts('on');
|
|
|
-echartsProto.off = createRegisterEventWithLowercaseECharts('off');
|
|
|
-/**
|
|
|
- * @deprecated
|
|
|
- */
|
|
|
-// @ts-ignore
|
|
|
-echartsProto.one = function (eventName, cb, ctx) {
|
|
|
- var self = this;
|
|
|
- deprecateLog('ECharts#one is deprecated.');
|
|
|
- function wrapped() {
|
|
|
- var args2 = [];
|
|
|
- for (var _i = 0; _i < arguments.length; _i++) {
|
|
|
- args2[_i] = arguments[_i];
|
|
|
- }
|
|
|
- cb && cb.apply && cb.apply(this, args2);
|
|
|
- // @ts-ignore
|
|
|
- self.off(eventName, wrapped);
|
|
|
- }
|
|
|
- ;
|
|
|
- // @ts-ignore
|
|
|
- this.on.call(this, eventName, wrapped, ctx);
|
|
|
-};
|
|
|
-var MOUSE_EVENT_NAMES = ['click', 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'mouseup', 'globalout', 'contextmenu'];
|
|
|
-function disposedWarning(id) {
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
- warn('Instance ' + id + ' has been disposed');
|
|
|
- }
|
|
|
-}
|
|
|
-var actions = {};
|
|
|
-/**
|
|
|
- * Map eventType to actionType
|
|
|
- */
|
|
|
-var eventActionMap = {};
|
|
|
-var dataProcessorFuncs = [];
|
|
|
-var optionPreprocessorFuncs = [];
|
|
|
-var visualFuncs = [];
|
|
|
-var themeStorage = {};
|
|
|
-var loadingEffects = {};
|
|
|
-var instances = {};
|
|
|
-var connectedGroups = {};
|
|
|
-var idBase = +new Date() - 0;
|
|
|
-var groupIdBase = +new Date() - 0;
|
|
|
-var DOM_ATTRIBUTE_KEY = '_echarts_instance_';
|
|
|
-/**
|
|
|
- * @param opts.devicePixelRatio Use window.devicePixelRatio by default
|
|
|
- * @param opts.renderer Can choose 'canvas' or 'svg' to render the chart.
|
|
|
- * @param opts.width Use clientWidth of the input `dom` by default.
|
|
|
- * Can be 'auto' (the same as null/undefined)
|
|
|
- * @param opts.height Use clientHeight of the input `dom` by default.
|
|
|
- * Can be 'auto' (the same as null/undefined)
|
|
|
- * @param opts.locale Specify the locale.
|
|
|
- * @param opts.useDirtyRect Enable dirty rectangle rendering or not.
|
|
|
- */
|
|
|
-export function init(dom, theme, opts) {
|
|
|
- var isClient = !(opts && opts.ssr);
|
|
|
- if (isClient) {
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
- if (!dom) {
|
|
|
- throw new Error('Initialize failed: invalid dom.');
|
|
|
- }
|
|
|
- }
|
|
|
- var existInstance = getInstanceByDom(dom);
|
|
|
- if (existInstance) {
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
- warn('There is a chart instance already initialized on the dom.');
|
|
|
- }
|
|
|
- return existInstance;
|
|
|
- }
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
- if (isDom(dom) && dom.nodeName.toUpperCase() !== 'CANVAS' && (!dom.clientWidth && (!opts || opts.width == null) || !dom.clientHeight && (!opts || opts.height == null))) {
|
|
|
- warn('Can\'t get DOM width or height. Please check ' + 'dom.clientWidth and dom.clientHeight. They should not be 0.' + 'For example, you may need to call this in the callback ' + 'of window.onload.');
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- var chart = new ECharts(dom, theme, opts);
|
|
|
- chart.id = 'ec_' + idBase++;
|
|
|
- instances[chart.id] = chart;
|
|
|
- isClient && modelUtil.setAttribute(dom, DOM_ATTRIBUTE_KEY, chart.id);
|
|
|
- enableConnect(chart);
|
|
|
- lifecycle.trigger('afterinit', chart);
|
|
|
- return chart;
|
|
|
-}
|
|
|
-/**
|
|
|
- * @usage
|
|
|
- * (A)
|
|
|
- * ```js
|
|
|
- * let chart1 = echarts.init(dom1);
|
|
|
- * let chart2 = echarts.init(dom2);
|
|
|
- * chart1.group = 'xxx';
|
|
|
- * chart2.group = 'xxx';
|
|
|
- * echarts.connect('xxx');
|
|
|
- * ```
|
|
|
- * (B)
|
|
|
- * ```js
|
|
|
- * let chart1 = echarts.init(dom1);
|
|
|
- * let chart2 = echarts.init(dom2);
|
|
|
- * echarts.connect('xxx', [chart1, chart2]);
|
|
|
- * ```
|
|
|
- */
|
|
|
-export function connect(groupId) {
|
|
|
- // Is array of charts
|
|
|
- if (isArray(groupId)) {
|
|
|
- var charts = groupId;
|
|
|
- groupId = null;
|
|
|
- // If any chart has group
|
|
|
- each(charts, function (chart) {
|
|
|
- if (chart.group != null) {
|
|
|
- groupId = chart.group;
|
|
|
- }
|
|
|
- });
|
|
|
- groupId = groupId || 'g_' + groupIdBase++;
|
|
|
- each(charts, function (chart) {
|
|
|
- chart.group = groupId;
|
|
|
- });
|
|
|
- }
|
|
|
- connectedGroups[groupId] = true;
|
|
|
- return groupId;
|
|
|
-}
|
|
|
-export function disconnect(groupId) {
|
|
|
- connectedGroups[groupId] = false;
|
|
|
-}
|
|
|
-/**
|
|
|
- * Alias and backward compatibility
|
|
|
- * @deprecated
|
|
|
- */
|
|
|
-export var disConnect = disconnect;
|
|
|
-/**
|
|
|
- * Dispose a chart instance
|
|
|
- */
|
|
|
-export function dispose(chart) {
|
|
|
- if (isString(chart)) {
|
|
|
- chart = instances[chart];
|
|
|
- } else if (!(chart instanceof ECharts)) {
|
|
|
- // Try to treat as dom
|
|
|
- chart = getInstanceByDom(chart);
|
|
|
- }
|
|
|
- if (chart instanceof ECharts && !chart.isDisposed()) {
|
|
|
- chart.dispose();
|
|
|
- }
|
|
|
-}
|
|
|
-export function getInstanceByDom(dom) {
|
|
|
- return instances[modelUtil.getAttribute(dom, DOM_ATTRIBUTE_KEY)];
|
|
|
-}
|
|
|
-export function getInstanceById(key) {
|
|
|
- return instances[key];
|
|
|
-}
|
|
|
-/**
|
|
|
- * Register theme
|
|
|
- */
|
|
|
-export function registerTheme(name, theme) {
|
|
|
- themeStorage[name] = theme;
|
|
|
-}
|
|
|
-/**
|
|
|
- * Register option preprocessor
|
|
|
- */
|
|
|
-export function registerPreprocessor(preprocessorFunc) {
|
|
|
- if (indexOf(optionPreprocessorFuncs, preprocessorFunc) < 0) {
|
|
|
- optionPreprocessorFuncs.push(preprocessorFunc);
|
|
|
- }
|
|
|
-}
|
|
|
-export function registerProcessor(priority, processor) {
|
|
|
- normalizeRegister(dataProcessorFuncs, priority, processor, PRIORITY_PROCESSOR_DEFAULT);
|
|
|
-}
|
|
|
-/**
|
|
|
- * Register postIniter
|
|
|
- * @param {Function} postInitFunc
|
|
|
- */
|
|
|
-export function registerPostInit(postInitFunc) {
|
|
|
- registerUpdateLifecycle('afterinit', postInitFunc);
|
|
|
-}
|
|
|
-/**
|
|
|
- * Register postUpdater
|
|
|
- * @param {Function} postUpdateFunc
|
|
|
- */
|
|
|
-export function registerPostUpdate(postUpdateFunc) {
|
|
|
- registerUpdateLifecycle('afterupdate', postUpdateFunc);
|
|
|
-}
|
|
|
-export function registerUpdateLifecycle(name, cb) {
|
|
|
- lifecycle.on(name, cb);
|
|
|
-}
|
|
|
-export function registerAction(actionInfo, eventName, action) {
|
|
|
- if (isFunction(eventName)) {
|
|
|
- action = eventName;
|
|
|
- eventName = '';
|
|
|
- }
|
|
|
- var actionType = isObject(actionInfo) ? actionInfo.type : [actionInfo, actionInfo = {
|
|
|
- event: eventName
|
|
|
- }][0];
|
|
|
- // Event name is all lowercase
|
|
|
- actionInfo.event = (actionInfo.event || actionType).toLowerCase();
|
|
|
- eventName = actionInfo.event;
|
|
|
- if (eventActionMap[eventName]) {
|
|
|
- // Already registered.
|
|
|
- return;
|
|
|
- }
|
|
|
- // Validate action type and event name.
|
|
|
- assert(ACTION_REG.test(actionType) && ACTION_REG.test(eventName));
|
|
|
- if (!actions[actionType]) {
|
|
|
- actions[actionType] = {
|
|
|
- action: action,
|
|
|
- actionInfo: actionInfo
|
|
|
- };
|
|
|
- }
|
|
|
- eventActionMap[eventName] = actionType;
|
|
|
-}
|
|
|
-export function registerCoordinateSystem(type, coordSysCreator) {
|
|
|
- CoordinateSystemManager.register(type, coordSysCreator);
|
|
|
-}
|
|
|
-/**
|
|
|
- * Get dimensions of specified coordinate system.
|
|
|
- * @param {string} type
|
|
|
- * @return {Array.<string|Object>}
|
|
|
- */
|
|
|
-export function getCoordinateSystemDimensions(type) {
|
|
|
- var coordSysCreator = CoordinateSystemManager.get(type);
|
|
|
- if (coordSysCreator) {
|
|
|
- return coordSysCreator.getDimensionsInfo ? coordSysCreator.getDimensionsInfo() : coordSysCreator.dimensions.slice();
|
|
|
- }
|
|
|
-}
|
|
|
-export { registerLocale } from './locale.js';
|
|
|
-function registerLayout(priority, layoutTask) {
|
|
|
- normalizeRegister(visualFuncs, priority, layoutTask, PRIORITY_VISUAL_LAYOUT, 'layout');
|
|
|
-}
|
|
|
-function registerVisual(priority, visualTask) {
|
|
|
- normalizeRegister(visualFuncs, priority, visualTask, PRIORITY_VISUAL_CHART, 'visual');
|
|
|
-}
|
|
|
-export { registerLayout, registerVisual };
|
|
|
-var registeredTasks = [];
|
|
|
-function normalizeRegister(targetList, priority, fn, defaultPriority, visualType) {
|
|
|
- if (isFunction(priority) || isObject(priority)) {
|
|
|
- fn = priority;
|
|
|
- priority = defaultPriority;
|
|
|
- }
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
- if (isNaN(priority) || priority == null) {
|
|
|
- throw new Error('Illegal priority');
|
|
|
- }
|
|
|
- // Check duplicate
|
|
|
- each(targetList, function (wrap) {
|
|
|
- assert(wrap.__raw !== fn);
|
|
|
- });
|
|
|
- }
|
|
|
- // Already registered
|
|
|
- if (indexOf(registeredTasks, fn) >= 0) {
|
|
|
- return;
|
|
|
- }
|
|
|
- registeredTasks.push(fn);
|
|
|
- var stageHandler = Scheduler.wrapStageHandler(fn, visualType);
|
|
|
- stageHandler.__prio = priority;
|
|
|
- stageHandler.__raw = fn;
|
|
|
- targetList.push(stageHandler);
|
|
|
-}
|
|
|
-export function registerLoading(name, loadingFx) {
|
|
|
- loadingEffects[name] = loadingFx;
|
|
|
-}
|
|
|
-/**
|
|
|
- * ZRender need a canvas context to do measureText.
|
|
|
- * But in node environment canvas may be created by node-canvas.
|
|
|
- * So we need to specify how to create a canvas instead of using document.createElement('canvas')
|
|
|
- *
|
|
|
- *
|
|
|
- * @deprecated use setPlatformAPI({ createCanvas }) instead.
|
|
|
- *
|
|
|
- * @example
|
|
|
- * let Canvas = require('canvas');
|
|
|
- * let echarts = require('echarts');
|
|
|
- * echarts.setCanvasCreator(function () {
|
|
|
- * // Small size is enough.
|
|
|
- * return new Canvas(32, 32);
|
|
|
- * });
|
|
|
- */
|
|
|
-export function setCanvasCreator(creator) {
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
- deprecateLog('setCanvasCreator is deprecated. Use setPlatformAPI({ createCanvas }) instead.');
|
|
|
- }
|
|
|
- setPlatformAPI({
|
|
|
- createCanvas: creator
|
|
|
- });
|
|
|
-}
|
|
|
-/**
|
|
|
- * The parameters and usage: see `geoSourceManager.registerMap`.
|
|
|
- * Compatible with previous `echarts.registerMap`.
|
|
|
- */
|
|
|
-export function registerMap(mapName, geoJson, specialAreas) {
|
|
|
- var registerMap = getImpl('registerMap');
|
|
|
- registerMap && registerMap(mapName, geoJson, specialAreas);
|
|
|
-}
|
|
|
-export function getMap(mapName) {
|
|
|
- var getMap = getImpl('getMap');
|
|
|
- return getMap && getMap(mapName);
|
|
|
-}
|
|
|
-export var registerTransform = registerExternalTransform;
|
|
|
-/**
|
|
|
- * Globa dispatchAction to a specified chart instance.
|
|
|
- */
|
|
|
-// export function dispatchAction(payload: { chartId: string } & Payload, opt?: Parameters<ECharts['dispatchAction']>[1]) {
|
|
|
-// if (!payload || !payload.chartId) {
|
|
|
-// // Must have chartId to find chart
|
|
|
-// return;
|
|
|
-// }
|
|
|
-// const chart = instances[payload.chartId];
|
|
|
-// if (chart) {
|
|
|
-// chart.dispatchAction(payload, opt);
|
|
|
-// }
|
|
|
-// }
|
|
|
-// Builtin global visual
|
|
|
-registerVisual(PRIORITY_VISUAL_GLOBAL, seriesStyleTask);
|
|
|
-registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataStyleTask);
|
|
|
-registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataColorPaletteTask);
|
|
|
-registerVisual(PRIORITY_VISUAL_GLOBAL, seriesSymbolTask);
|
|
|
-registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataSymbolTask);
|
|
|
-registerVisual(PRIORITY_VISUAL_DECAL, decal);
|
|
|
-registerPreprocessor(backwardCompat);
|
|
|
-registerProcessor(PRIORITY_PROCESSOR_DATASTACK, dataStack);
|
|
|
-registerLoading('default', loadingDefault);
|
|
|
-// Default actions
|
|
|
-registerAction({
|
|
|
- type: HIGHLIGHT_ACTION_TYPE,
|
|
|
- event: HIGHLIGHT_ACTION_TYPE,
|
|
|
- update: HIGHLIGHT_ACTION_TYPE
|
|
|
-}, noop);
|
|
|
-registerAction({
|
|
|
- type: DOWNPLAY_ACTION_TYPE,
|
|
|
- event: DOWNPLAY_ACTION_TYPE,
|
|
|
- update: DOWNPLAY_ACTION_TYPE
|
|
|
-}, noop);
|
|
|
-registerAction({
|
|
|
- type: SELECT_ACTION_TYPE,
|
|
|
- event: SELECT_ACTION_TYPE,
|
|
|
- update: SELECT_ACTION_TYPE
|
|
|
-}, noop);
|
|
|
-registerAction({
|
|
|
- type: UNSELECT_ACTION_TYPE,
|
|
|
- event: UNSELECT_ACTION_TYPE,
|
|
|
- update: UNSELECT_ACTION_TYPE
|
|
|
-}, noop);
|
|
|
-registerAction({
|
|
|
- type: TOGGLE_SELECT_ACTION_TYPE,
|
|
|
- event: TOGGLE_SELECT_ACTION_TYPE,
|
|
|
- update: TOGGLE_SELECT_ACTION_TYPE
|
|
|
-}, noop);
|
|
|
-// Default theme
|
|
|
-registerTheme('light', lightTheme);
|
|
|
-registerTheme('dark', darkTheme);
|
|
|
-// For backward compatibility, where the namespace `dataTool` will
|
|
|
-// be mounted on `echarts` is the extension `dataTool` is imported.
|
|
|
-export var dataTool = {};
|