echarts.js 79 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. /**
  20. * AUTO-GENERATED FILE. DO NOT MODIFY.
  21. */
  22. import { __extends } from "tslib";
  23. /*
  24. * Licensed to the Apache Software Foundation (ASF) under one
  25. * or more contributor license agreements. See the NOTICE file
  26. * distributed with this work for additional information
  27. * regarding copyright ownership. The ASF licenses this file
  28. * to you under the Apache License, Version 2.0 (the
  29. * "License"); you may not use this file except in compliance
  30. * with the License. You may obtain a copy of the License at
  31. *
  32. * http://www.apache.org/licenses/LICENSE-2.0
  33. *
  34. * Unless required by applicable law or agreed to in writing,
  35. * software distributed under the License is distributed on an
  36. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  37. * KIND, either express or implied. See the License for the
  38. * specific language governing permissions and limitations
  39. * under the License.
  40. */
  41. import * as zrender from 'zrender/lib/zrender';
  42. import { assert, each, isFunction, isObject, indexOf, bind, clone, setAsPrimitive, createCanvas, extend, createHashMap, map, defaults, isDom, isArray, $override, noop } from 'zrender/lib/core/util';
  43. import * as colorTool from 'zrender/lib/tool/color';
  44. import env from 'zrender/lib/core/env';
  45. import timsort from 'zrender/lib/core/timsort';
  46. import Eventful from 'zrender/lib/core/Eventful';
  47. import GlobalModel from '../model/Global';
  48. import ExtensionAPI from './ExtensionAPI';
  49. import CoordinateSystemManager from './CoordinateSystem';
  50. import OptionManager from '../model/OptionManager';
  51. import backwardCompat from '../preprocessor/backwardCompat';
  52. import dataStack from '../processor/dataStack';
  53. import SeriesModel from '../model/Series';
  54. import ComponentView from '../view/Component';
  55. import ChartView from '../view/Chart';
  56. import * as graphic from '../util/graphic';
  57. import { getECData } from '../util/innerStore';
  58. 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, handleGlboalMouseOutForHighDown } from '../util/states';
  59. import * as modelUtil from '../util/model';
  60. import { throttle } from '../util/throttle';
  61. import { seriesStyleTask, dataStyleTask, dataColorPaletteTask } from '../visual/style';
  62. import loadingDefault from '../loading/default';
  63. import Scheduler from './Scheduler';
  64. import lightTheme from '../theme/light';
  65. import darkTheme from '../theme/dark';
  66. import { parseClassType } from '../util/clazz';
  67. import { ECEventProcessor } from '../util/ECEventProcessor';
  68. import { seriesSymbolTask, dataSymbolTask } from '../visual/symbol';
  69. import { getVisualFromData, getItemVisualFromData } from '../visual/helper';
  70. import { deprecateLog } from '../util/log';
  71. import { handleLegacySelectEvents } from '../legacy/dataSelectAction';
  72. import { registerExternalTransform } from '../data/helper/transform';
  73. import { createLocaleObject, SYSTEM_LANG } from './locale';
  74. import { findEventDispatcher } from '../util/event';
  75. import decal from '../visual/decal';
  76. import geoSourceManager from '../coord/geo/geoSourceManager';
  77. import lifecycle from './lifecycle';
  78. var hasWindow = typeof window !== 'undefined';
  79. export var version = '5.2.1';
  80. export var dependencies = {
  81. zrender: '5.2.1'
  82. };
  83. var TEST_FRAME_REMAIN_TIME = 1;
  84. var PRIORITY_PROCESSOR_SERIES_FILTER = 800; // Some data processors depends on the stack result dimension (to calculate data extent).
  85. // So data stack stage should be in front of data processing stage.
  86. var PRIORITY_PROCESSOR_DATASTACK = 900; // "Data filter" will block the stream, so it should be
  87. // put at the begining of data processing.
  88. var PRIORITY_PROCESSOR_FILTER = 1000;
  89. var PRIORITY_PROCESSOR_DEFAULT = 2000;
  90. var PRIORITY_PROCESSOR_STATISTIC = 5000;
  91. var PRIORITY_VISUAL_LAYOUT = 1000;
  92. var PRIORITY_VISUAL_PROGRESSIVE_LAYOUT = 1100;
  93. var PRIORITY_VISUAL_GLOBAL = 2000;
  94. var PRIORITY_VISUAL_CHART = 3000;
  95. var PRIORITY_VISUAL_COMPONENT = 4000; // Visual property in data. Greater than `PRIORITY_VISUAL_COMPONENT` to enable to
  96. // overwrite the viusal result of component (like `visualMap`)
  97. // using data item specific setting (like itemStyle.xxx on data item)
  98. var PRIORITY_VISUAL_CHART_DATA_CUSTOM = 4500; // Greater than `PRIORITY_VISUAL_CHART_DATA_CUSTOM` to enable to layout based on
  99. // visual result like `symbolSize`.
  100. var PRIORITY_VISUAL_POST_CHART_LAYOUT = 4600;
  101. var PRIORITY_VISUAL_BRUSH = 5000;
  102. var PRIORITY_VISUAL_ARIA = 6000;
  103. var PRIORITY_VISUAL_DECAL = 7000;
  104. export var PRIORITY = {
  105. PROCESSOR: {
  106. FILTER: PRIORITY_PROCESSOR_FILTER,
  107. SERIES_FILTER: PRIORITY_PROCESSOR_SERIES_FILTER,
  108. STATISTIC: PRIORITY_PROCESSOR_STATISTIC
  109. },
  110. VISUAL: {
  111. LAYOUT: PRIORITY_VISUAL_LAYOUT,
  112. PROGRESSIVE_LAYOUT: PRIORITY_VISUAL_PROGRESSIVE_LAYOUT,
  113. GLOBAL: PRIORITY_VISUAL_GLOBAL,
  114. CHART: PRIORITY_VISUAL_CHART,
  115. POST_CHART_LAYOUT: PRIORITY_VISUAL_POST_CHART_LAYOUT,
  116. COMPONENT: PRIORITY_VISUAL_COMPONENT,
  117. BRUSH: PRIORITY_VISUAL_BRUSH,
  118. CHART_ITEM: PRIORITY_VISUAL_CHART_DATA_CUSTOM,
  119. ARIA: PRIORITY_VISUAL_ARIA,
  120. DECAL: PRIORITY_VISUAL_DECAL
  121. }
  122. }; // Main process have three entries: `setOption`, `dispatchAction` and `resize`,
  123. // where they must not be invoked nestedly, except the only case: invoke
  124. // dispatchAction with updateMethod "none" in main process.
  125. // This flag is used to carry out this rule.
  126. // All events will be triggered out side main process (i.e. when !this[IN_MAIN_PROCESS]).
  127. var IN_MAIN_PROCESS_KEY = '__flagInMainProcess';
  128. var PENDING_UPDATE = '__pendingUpdate';
  129. var STATUS_NEEDS_UPDATE_KEY = '__needsUpdateStatus';
  130. var ACTION_REG = /^[a-zA-Z0-9_]+$/;
  131. var CONNECT_STATUS_KEY = '__connectUpdateStatus';
  132. var CONNECT_STATUS_PENDING = 0;
  133. var CONNECT_STATUS_UPDATING = 1;
  134. var CONNECT_STATUS_UPDATED = 2;
  135. ;
  136. ;
  137. function createRegisterEventWithLowercaseECharts(method) {
  138. return function () {
  139. var args = [];
  140. for (var _i = 0; _i < arguments.length; _i++) {
  141. args[_i] = arguments[_i];
  142. }
  143. if (this.isDisposed()) {
  144. disposedWarning(this.id);
  145. return;
  146. }
  147. return toLowercaseNameAndCallEventful(this, method, args);
  148. };
  149. }
  150. function createRegisterEventWithLowercaseMessageCenter(method) {
  151. return function () {
  152. var args = [];
  153. for (var _i = 0; _i < arguments.length; _i++) {
  154. args[_i] = arguments[_i];
  155. }
  156. return toLowercaseNameAndCallEventful(this, method, args);
  157. };
  158. }
  159. function toLowercaseNameAndCallEventful(host, method, args) {
  160. // `args[0]` is event name. Event name is all lowercase.
  161. args[0] = args[0] && args[0].toLowerCase();
  162. return Eventful.prototype[method].apply(host, args);
  163. }
  164. var MessageCenter =
  165. /** @class */
  166. function (_super) {
  167. __extends(MessageCenter, _super);
  168. function MessageCenter() {
  169. return _super !== null && _super.apply(this, arguments) || this;
  170. }
  171. return MessageCenter;
  172. }(Eventful);
  173. var messageCenterProto = MessageCenter.prototype;
  174. messageCenterProto.on = createRegisterEventWithLowercaseMessageCenter('on');
  175. messageCenterProto.off = createRegisterEventWithLowercaseMessageCenter('off'); // ---------------------------------------
  176. // Internal method names for class ECharts
  177. // ---------------------------------------
  178. var prepare;
  179. var prepareView;
  180. var updateDirectly;
  181. var updateMethods;
  182. var doConvertPixel;
  183. var updateStreamModes;
  184. var doDispatchAction;
  185. var flushPendingActions;
  186. var triggerUpdatedEvent;
  187. var bindRenderedEvent;
  188. var bindMouseEvent;
  189. var clearColorPalette;
  190. var render;
  191. var renderComponents;
  192. var renderSeries;
  193. var createExtensionAPI;
  194. var enableConnect;
  195. var markStatusToUpdate;
  196. var applyChangedStates;
  197. var ECharts =
  198. /** @class */
  199. function (_super) {
  200. __extends(ECharts, _super);
  201. function ECharts(dom, // Theme name or themeOption.
  202. theme, opts) {
  203. var _this = _super.call(this, new ECEventProcessor()) || this;
  204. _this._chartsViews = [];
  205. _this._chartsMap = {};
  206. _this._componentsViews = [];
  207. _this._componentsMap = {}; // Can't dispatch action during rendering procedure
  208. _this._pendingActions = [];
  209. opts = opts || {}; // Get theme by name
  210. if (typeof theme === 'string') {
  211. theme = themeStorage[theme];
  212. }
  213. _this._dom = dom;
  214. var defaultRenderer = 'canvas';
  215. var defaultUseDirtyRect = false;
  216. if (process.env.NODE_ENV !== 'production') {
  217. var root =
  218. /* eslint-disable-next-line */
  219. hasWindow ? window : global;
  220. defaultRenderer = root.__ECHARTS__DEFAULT__RENDERER__ || defaultRenderer;
  221. var devUseDirtyRect = root.__ECHARTS__DEFAULT__USE_DIRTY_RECT__;
  222. defaultUseDirtyRect = devUseDirtyRect == null ? defaultUseDirtyRect : devUseDirtyRect;
  223. }
  224. var zr = _this._zr = zrender.init(dom, {
  225. renderer: opts.renderer || defaultRenderer,
  226. devicePixelRatio: opts.devicePixelRatio,
  227. width: opts.width,
  228. height: opts.height,
  229. useDirtyRect: opts.useDirtyRect == null ? defaultUseDirtyRect : opts.useDirtyRect
  230. }); // Expect 60 fps.
  231. _this._throttledZrFlush = throttle(bind(zr.flush, zr), 17);
  232. theme = clone(theme);
  233. theme && backwardCompat(theme, true);
  234. _this._theme = theme;
  235. _this._locale = createLocaleObject(opts.locale || SYSTEM_LANG);
  236. _this._coordSysMgr = new CoordinateSystemManager();
  237. var api = _this._api = createExtensionAPI(_this); // Sort on demand
  238. function prioritySortFunc(a, b) {
  239. return a.__prio - b.__prio;
  240. }
  241. timsort(visualFuncs, prioritySortFunc);
  242. timsort(dataProcessorFuncs, prioritySortFunc);
  243. _this._scheduler = new Scheduler(_this, api, dataProcessorFuncs, visualFuncs);
  244. _this._messageCenter = new MessageCenter(); // Init mouse events
  245. _this._initEvents(); // In case some people write `window.onresize = chart.resize`
  246. _this.resize = bind(_this.resize, _this);
  247. zr.animation.on('frame', _this._onframe, _this);
  248. bindRenderedEvent(zr, _this);
  249. bindMouseEvent(zr, _this); // ECharts instance can be used as value.
  250. setAsPrimitive(_this);
  251. return _this;
  252. }
  253. ECharts.prototype._onframe = function () {
  254. if (this._disposed) {
  255. return;
  256. }
  257. applyChangedStates(this);
  258. var scheduler = this._scheduler; // Lazy update
  259. if (this[PENDING_UPDATE]) {
  260. var silent = this[PENDING_UPDATE].silent;
  261. this[IN_MAIN_PROCESS_KEY] = true;
  262. prepare(this);
  263. updateMethods.update.call(this, null, this[PENDING_UPDATE].updateParams); // At present, in each frame, zrender performs:
  264. // (1) animation step forward.
  265. // (2) trigger('frame') (where this `_onframe` is called)
  266. // (3) zrender flush (render).
  267. // If we do nothing here, since we use `setToFinal: true`, the step (3) above
  268. // will render the final state of the elements before the real animation started.
  269. this._zr.flush();
  270. this[IN_MAIN_PROCESS_KEY] = false;
  271. this[PENDING_UPDATE] = null;
  272. flushPendingActions.call(this, silent);
  273. triggerUpdatedEvent.call(this, silent);
  274. } // Avoid do both lazy update and progress in one frame.
  275. else if (scheduler.unfinished) {
  276. // Stream progress.
  277. var remainTime = TEST_FRAME_REMAIN_TIME;
  278. var ecModel = this._model;
  279. var api = this._api;
  280. scheduler.unfinished = false;
  281. do {
  282. var startTime = +new Date();
  283. scheduler.performSeriesTasks(ecModel); // Currently dataProcessorFuncs do not check threshold.
  284. scheduler.performDataProcessorTasks(ecModel);
  285. updateStreamModes(this, ecModel); // Do not update coordinate system here. Because that coord system update in
  286. // each frame is not a good user experience. So we follow the rule that
  287. // the extent of the coordinate system is determin in the first frame (the
  288. // frame is executed immedietely after task reset.
  289. // this._coordSysMgr.update(ecModel, api);
  290. // console.log('--- ec frame visual ---', remainTime);
  291. scheduler.performVisualTasks(ecModel);
  292. renderSeries(this, this._model, api, 'remain', {});
  293. remainTime -= +new Date() - startTime;
  294. } while (remainTime > 0 && scheduler.unfinished); // Call flush explicitly for trigger finished event.
  295. if (!scheduler.unfinished) {
  296. this._zr.flush();
  297. } // Else, zr flushing be ensue within the same frame,
  298. // because zr flushing is after onframe event.
  299. }
  300. };
  301. ECharts.prototype.getDom = function () {
  302. return this._dom;
  303. };
  304. ECharts.prototype.getId = function () {
  305. return this.id;
  306. };
  307. ECharts.prototype.getZr = function () {
  308. return this._zr;
  309. };
  310. /* eslint-disable-next-line */
  311. ECharts.prototype.setOption = function (option, notMerge, lazyUpdate) {
  312. if (process.env.NODE_ENV !== 'production') {
  313. assert(!this[IN_MAIN_PROCESS_KEY], '`setOption` should not be called during main process.');
  314. }
  315. if (this._disposed) {
  316. disposedWarning(this.id);
  317. return;
  318. }
  319. var silent;
  320. var replaceMerge;
  321. var transitionOpt;
  322. if (isObject(notMerge)) {
  323. lazyUpdate = notMerge.lazyUpdate;
  324. silent = notMerge.silent;
  325. replaceMerge = notMerge.replaceMerge;
  326. transitionOpt = notMerge.transition;
  327. notMerge = notMerge.notMerge;
  328. }
  329. this[IN_MAIN_PROCESS_KEY] = true;
  330. if (!this._model || notMerge) {
  331. var optionManager = new OptionManager(this._api);
  332. var theme = this._theme;
  333. var ecModel = this._model = new GlobalModel();
  334. ecModel.scheduler = this._scheduler;
  335. ecModel.init(null, null, null, theme, this._locale, optionManager);
  336. }
  337. this._model.setOption(option, {
  338. replaceMerge: replaceMerge
  339. }, optionPreprocessorFuncs);
  340. var updateParams = {
  341. seriesTransition: transitionOpt,
  342. optionChanged: true
  343. };
  344. if (lazyUpdate) {
  345. this[PENDING_UPDATE] = {
  346. silent: silent,
  347. updateParams: updateParams
  348. };
  349. this[IN_MAIN_PROCESS_KEY] = false; // `setOption(option, {lazyMode: true})` may be called when zrender has been slept.
  350. // It should wake it up to make sure zrender start to render at the next frame.
  351. this.getZr().wakeUp();
  352. } else {
  353. prepare(this);
  354. updateMethods.update.call(this, null, updateParams); // Ensure zr refresh sychronously, and then pixel in canvas can be
  355. // fetched after `setOption`.
  356. this._zr.flush();
  357. this[PENDING_UPDATE] = null;
  358. this[IN_MAIN_PROCESS_KEY] = false;
  359. flushPendingActions.call(this, silent);
  360. triggerUpdatedEvent.call(this, silent);
  361. }
  362. };
  363. /**
  364. * @DEPRECATED
  365. */
  366. ECharts.prototype.setTheme = function () {
  367. console.error('ECharts#setTheme() is DEPRECATED in ECharts 3.0');
  368. }; // We don't want developers to use getModel directly.
  369. ECharts.prototype.getModel = function () {
  370. return this._model;
  371. };
  372. ECharts.prototype.getOption = function () {
  373. return this._model && this._model.getOption();
  374. };
  375. ECharts.prototype.getWidth = function () {
  376. return this._zr.getWidth();
  377. };
  378. ECharts.prototype.getHeight = function () {
  379. return this._zr.getHeight();
  380. };
  381. ECharts.prototype.getDevicePixelRatio = function () {
  382. return this._zr.painter.dpr
  383. /* eslint-disable-next-line */
  384. || hasWindow && window.devicePixelRatio || 1;
  385. };
  386. /**
  387. * Get canvas which has all thing rendered
  388. */
  389. ECharts.prototype.getRenderedCanvas = function (opts) {
  390. if (!env.canvasSupported) {
  391. return;
  392. }
  393. opts = opts || {};
  394. return this._zr.painter.getRenderedCanvas({
  395. backgroundColor: opts.backgroundColor || this._model.get('backgroundColor'),
  396. pixelRatio: opts.pixelRatio || this.getDevicePixelRatio()
  397. });
  398. };
  399. /**
  400. * Get svg data url
  401. */
  402. ECharts.prototype.getSvgDataURL = function () {
  403. if (!env.svgSupported) {
  404. return;
  405. }
  406. var zr = this._zr;
  407. var list = zr.storage.getDisplayList(); // Stop animations
  408. each(list, function (el) {
  409. el.stopAnimation(null, true);
  410. });
  411. return zr.painter.toDataURL();
  412. };
  413. ECharts.prototype.getDataURL = function (opts) {
  414. if (this._disposed) {
  415. disposedWarning(this.id);
  416. return;
  417. }
  418. opts = opts || {};
  419. var excludeComponents = opts.excludeComponents;
  420. var ecModel = this._model;
  421. var excludesComponentViews = [];
  422. var self = this;
  423. each(excludeComponents, function (componentType) {
  424. ecModel.eachComponent({
  425. mainType: componentType
  426. }, function (component) {
  427. var view = self._componentsMap[component.__viewId];
  428. if (!view.group.ignore) {
  429. excludesComponentViews.push(view);
  430. view.group.ignore = true;
  431. }
  432. });
  433. });
  434. var url = this._zr.painter.getType() === 'svg' ? this.getSvgDataURL() : this.getRenderedCanvas(opts).toDataURL('image/' + (opts && opts.type || 'png'));
  435. each(excludesComponentViews, function (view) {
  436. view.group.ignore = false;
  437. });
  438. return url;
  439. };
  440. ECharts.prototype.getConnectedDataURL = function (opts) {
  441. if (this._disposed) {
  442. disposedWarning(this.id);
  443. return;
  444. }
  445. if (!env.canvasSupported) {
  446. return;
  447. }
  448. var isSvg = opts.type === 'svg';
  449. var groupId = this.group;
  450. var mathMin = Math.min;
  451. var mathMax = Math.max;
  452. var MAX_NUMBER = Infinity;
  453. if (connectedGroups[groupId]) {
  454. var left_1 = MAX_NUMBER;
  455. var top_1 = MAX_NUMBER;
  456. var right_1 = -MAX_NUMBER;
  457. var bottom_1 = -MAX_NUMBER;
  458. var canvasList_1 = [];
  459. var dpr_1 = opts && opts.pixelRatio || this.getDevicePixelRatio();
  460. each(instances, function (chart, id) {
  461. if (chart.group === groupId) {
  462. var canvas = isSvg ? chart.getZr().painter.getSvgDom().innerHTML : chart.getRenderedCanvas(clone(opts));
  463. var boundingRect = chart.getDom().getBoundingClientRect();
  464. left_1 = mathMin(boundingRect.left, left_1);
  465. top_1 = mathMin(boundingRect.top, top_1);
  466. right_1 = mathMax(boundingRect.right, right_1);
  467. bottom_1 = mathMax(boundingRect.bottom, bottom_1);
  468. canvasList_1.push({
  469. dom: canvas,
  470. left: boundingRect.left,
  471. top: boundingRect.top
  472. });
  473. }
  474. });
  475. left_1 *= dpr_1;
  476. top_1 *= dpr_1;
  477. right_1 *= dpr_1;
  478. bottom_1 *= dpr_1;
  479. var width = right_1 - left_1;
  480. var height = bottom_1 - top_1;
  481. var targetCanvas = createCanvas();
  482. var zr_1 = zrender.init(targetCanvas, {
  483. renderer: isSvg ? 'svg' : 'canvas'
  484. });
  485. zr_1.resize({
  486. width: width,
  487. height: height
  488. });
  489. if (isSvg) {
  490. var content_1 = '';
  491. each(canvasList_1, function (item) {
  492. var x = item.left - left_1;
  493. var y = item.top - top_1;
  494. content_1 += '<g transform="translate(' + x + ',' + y + ')">' + item.dom + '</g>';
  495. });
  496. zr_1.painter.getSvgRoot().innerHTML = content_1;
  497. if (opts.connectedBackgroundColor) {
  498. zr_1.painter.setBackgroundColor(opts.connectedBackgroundColor);
  499. }
  500. zr_1.refreshImmediately();
  501. return zr_1.painter.toDataURL();
  502. } else {
  503. // Background between the charts
  504. if (opts.connectedBackgroundColor) {
  505. zr_1.add(new graphic.Rect({
  506. shape: {
  507. x: 0,
  508. y: 0,
  509. width: width,
  510. height: height
  511. },
  512. style: {
  513. fill: opts.connectedBackgroundColor
  514. }
  515. }));
  516. }
  517. each(canvasList_1, function (item) {
  518. var img = new graphic.Image({
  519. style: {
  520. x: item.left * dpr_1 - left_1,
  521. y: item.top * dpr_1 - top_1,
  522. image: item.dom
  523. }
  524. });
  525. zr_1.add(img);
  526. });
  527. zr_1.refreshImmediately();
  528. return targetCanvas.toDataURL('image/' + (opts && opts.type || 'png'));
  529. }
  530. } else {
  531. return this.getDataURL(opts);
  532. }
  533. };
  534. ECharts.prototype.convertToPixel = function (finder, value) {
  535. return doConvertPixel(this, 'convertToPixel', finder, value);
  536. };
  537. ECharts.prototype.convertFromPixel = function (finder, value) {
  538. return doConvertPixel(this, 'convertFromPixel', finder, value);
  539. };
  540. /**
  541. * Is the specified coordinate systems or components contain the given pixel point.
  542. * @param {Array|number} value
  543. * @return {boolean} result
  544. */
  545. ECharts.prototype.containPixel = function (finder, value) {
  546. if (this._disposed) {
  547. disposedWarning(this.id);
  548. return;
  549. }
  550. var ecModel = this._model;
  551. var result;
  552. var findResult = modelUtil.parseFinder(ecModel, finder);
  553. each(findResult, function (models, key) {
  554. key.indexOf('Models') >= 0 && each(models, function (model) {
  555. var coordSys = model.coordinateSystem;
  556. if (coordSys && coordSys.containPoint) {
  557. result = result || !!coordSys.containPoint(value);
  558. } else if (key === 'seriesModels') {
  559. var view = this._chartsMap[model.__viewId];
  560. if (view && view.containPoint) {
  561. result = result || view.containPoint(value, model);
  562. } else {
  563. if (process.env.NODE_ENV !== 'production') {
  564. console.warn(key + ': ' + (view ? 'The found component do not support containPoint.' : 'No view mapping to the found component.'));
  565. }
  566. }
  567. } else {
  568. if (process.env.NODE_ENV !== 'production') {
  569. console.warn(key + ': containPoint is not supported');
  570. }
  571. }
  572. }, this);
  573. }, this);
  574. return !!result;
  575. };
  576. /**
  577. * Get visual from series or data.
  578. * @param finder
  579. * If string, e.g., 'series', means {seriesIndex: 0}.
  580. * If Object, could contain some of these properties below:
  581. * {
  582. * seriesIndex / seriesId / seriesName,
  583. * dataIndex / dataIndexInside
  584. * }
  585. * If dataIndex is not specified, series visual will be fetched,
  586. * but not data item visual.
  587. * If all of seriesIndex, seriesId, seriesName are not specified,
  588. * visual will be fetched from first series.
  589. * @param visualType 'color', 'symbol', 'symbolSize'
  590. */
  591. ECharts.prototype.getVisual = function (finder, visualType) {
  592. var ecModel = this._model;
  593. var parsedFinder = modelUtil.parseFinder(ecModel, finder, {
  594. defaultMainType: 'series'
  595. });
  596. var seriesModel = parsedFinder.seriesModel;
  597. if (process.env.NODE_ENV !== 'production') {
  598. if (!seriesModel) {
  599. console.warn('There is no specified seires model');
  600. }
  601. }
  602. var data = seriesModel.getData();
  603. var dataIndexInside = parsedFinder.hasOwnProperty('dataIndexInside') ? parsedFinder.dataIndexInside : parsedFinder.hasOwnProperty('dataIndex') ? data.indexOfRawIndex(parsedFinder.dataIndex) : null;
  604. return dataIndexInside != null ? getItemVisualFromData(data, dataIndexInside, visualType) : getVisualFromData(data, visualType);
  605. };
  606. /**
  607. * Get view of corresponding component model
  608. */
  609. ECharts.prototype.getViewOfComponentModel = function (componentModel) {
  610. return this._componentsMap[componentModel.__viewId];
  611. };
  612. /**
  613. * Get view of corresponding series model
  614. */
  615. ECharts.prototype.getViewOfSeriesModel = function (seriesModel) {
  616. return this._chartsMap[seriesModel.__viewId];
  617. };
  618. ECharts.prototype._initEvents = function () {
  619. var _this = this;
  620. each(MOUSE_EVENT_NAMES, function (eveName) {
  621. var handler = function (e) {
  622. var ecModel = _this.getModel();
  623. var el = e.target;
  624. var params;
  625. var isGlobalOut = eveName === 'globalout'; // no e.target when 'globalout'.
  626. if (isGlobalOut) {
  627. params = {};
  628. } else {
  629. el && findEventDispatcher(el, function (parent) {
  630. var ecData = getECData(parent);
  631. if (ecData && ecData.dataIndex != null) {
  632. var dataModel = ecData.dataModel || ecModel.getSeriesByIndex(ecData.seriesIndex);
  633. params = dataModel && dataModel.getDataParams(ecData.dataIndex, ecData.dataType) || {};
  634. return true;
  635. } // If element has custom eventData of components
  636. else if (ecData.eventData) {
  637. params = extend({}, ecData.eventData);
  638. return true;
  639. }
  640. }, true);
  641. } // Contract: if params prepared in mouse event,
  642. // these properties must be specified:
  643. // {
  644. // componentType: string (component main type)
  645. // componentIndex: number
  646. // }
  647. // Otherwise event query can not work.
  648. if (params) {
  649. var componentType = params.componentType;
  650. var componentIndex = params.componentIndex; // Special handling for historic reason: when trigger by
  651. // markLine/markPoint/markArea, the componentType is
  652. // 'markLine'/'markPoint'/'markArea', but we should better
  653. // enable them to be queried by seriesIndex, since their
  654. // option is set in each series.
  655. if (componentType === 'markLine' || componentType === 'markPoint' || componentType === 'markArea') {
  656. componentType = 'series';
  657. componentIndex = params.seriesIndex;
  658. }
  659. var model = componentType && componentIndex != null && ecModel.getComponent(componentType, componentIndex);
  660. var view = model && _this[model.mainType === 'series' ? '_chartsMap' : '_componentsMap'][model.__viewId];
  661. if (process.env.NODE_ENV !== 'production') {
  662. // `event.componentType` and `event[componentTpype + 'Index']` must not
  663. // be missed, otherwise there is no way to distinguish source component.
  664. // See `dataFormat.getDataParams`.
  665. if (!isGlobalOut && !(model && view)) {
  666. console.warn('model or view can not be found by params');
  667. }
  668. }
  669. params.event = e;
  670. params.type = eveName;
  671. _this._$eventProcessor.eventInfo = {
  672. targetEl: el,
  673. packedEvent: params,
  674. model: model,
  675. view: view
  676. };
  677. _this.trigger(eveName, params);
  678. }
  679. }; // Consider that some component (like tooltip, brush, ...)
  680. // register zr event handler, but user event handler might
  681. // do anything, such as call `setOption` or `dispatchAction`,
  682. // which probably update any of the content and probably
  683. // cause problem if it is called previous other inner handlers.
  684. handler.zrEventfulCallAtLast = true;
  685. _this._zr.on(eveName, handler, _this);
  686. });
  687. each(eventActionMap, function (actionType, eventType) {
  688. _this._messageCenter.on(eventType, function (event) {
  689. this.trigger(eventType, event);
  690. }, _this);
  691. }); // Extra events
  692. // TODO register?
  693. each(['selectchanged'], function (eventType) {
  694. _this._messageCenter.on(eventType, function (event) {
  695. this.trigger(eventType, event);
  696. }, _this);
  697. });
  698. handleLegacySelectEvents(this._messageCenter, this, this._api);
  699. };
  700. ECharts.prototype.isDisposed = function () {
  701. return this._disposed;
  702. };
  703. ECharts.prototype.clear = function () {
  704. if (this._disposed) {
  705. disposedWarning(this.id);
  706. return;
  707. }
  708. this.setOption({
  709. series: []
  710. }, true);
  711. };
  712. ECharts.prototype.dispose = function () {
  713. if (this._disposed) {
  714. disposedWarning(this.id);
  715. return;
  716. }
  717. this._disposed = true;
  718. modelUtil.setAttribute(this.getDom(), DOM_ATTRIBUTE_KEY, '');
  719. var chart = this;
  720. var api = chart._api;
  721. var ecModel = chart._model;
  722. each(chart._componentsViews, function (component) {
  723. component.dispose(ecModel, api);
  724. });
  725. each(chart._chartsViews, function (chart) {
  726. chart.dispose(ecModel, api);
  727. }); // Dispose after all views disposed
  728. chart._zr.dispose(); // Set properties to null.
  729. // To reduce the memory cost in case the top code still holds this instance unexpectedly.
  730. 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;
  731. delete instances[chart.id];
  732. };
  733. /**
  734. * Resize the chart
  735. */
  736. ECharts.prototype.resize = function (opts) {
  737. if (process.env.NODE_ENV !== 'production') {
  738. assert(!this[IN_MAIN_PROCESS_KEY], '`resize` should not be called during main process.');
  739. }
  740. if (this._disposed) {
  741. disposedWarning(this.id);
  742. return;
  743. }
  744. this._zr.resize(opts);
  745. var ecModel = this._model; // Resize loading effect
  746. this._loadingFX && this._loadingFX.resize();
  747. if (!ecModel) {
  748. return;
  749. }
  750. var needPrepare = ecModel.resetOption('media');
  751. var silent = opts && opts.silent; // There is some real cases that:
  752. // chart.setOption(option, { lazyUpdate: true });
  753. // chart.resize();
  754. if (this[PENDING_UPDATE]) {
  755. if (silent == null) {
  756. silent = this[PENDING_UPDATE].silent;
  757. }
  758. needPrepare = true;
  759. this[PENDING_UPDATE] = null;
  760. }
  761. this[IN_MAIN_PROCESS_KEY] = true;
  762. needPrepare && prepare(this);
  763. updateMethods.update.call(this, {
  764. type: 'resize',
  765. animation: extend({
  766. // Disable animation
  767. duration: 0
  768. }, opts && opts.animation)
  769. });
  770. this[IN_MAIN_PROCESS_KEY] = false;
  771. flushPendingActions.call(this, silent);
  772. triggerUpdatedEvent.call(this, silent);
  773. };
  774. ECharts.prototype.showLoading = function (name, cfg) {
  775. if (this._disposed) {
  776. disposedWarning(this.id);
  777. return;
  778. }
  779. if (isObject(name)) {
  780. cfg = name;
  781. name = '';
  782. }
  783. name = name || 'default';
  784. this.hideLoading();
  785. if (!loadingEffects[name]) {
  786. if (process.env.NODE_ENV !== 'production') {
  787. console.warn('Loading effects ' + name + ' not exists.');
  788. }
  789. return;
  790. }
  791. var el = loadingEffects[name](this._api, cfg);
  792. var zr = this._zr;
  793. this._loadingFX = el;
  794. zr.add(el);
  795. };
  796. /**
  797. * Hide loading effect
  798. */
  799. ECharts.prototype.hideLoading = function () {
  800. if (this._disposed) {
  801. disposedWarning(this.id);
  802. return;
  803. }
  804. this._loadingFX && this._zr.remove(this._loadingFX);
  805. this._loadingFX = null;
  806. };
  807. ECharts.prototype.makeActionFromEvent = function (eventObj) {
  808. var payload = extend({}, eventObj);
  809. payload.type = eventActionMap[eventObj.type];
  810. return payload;
  811. };
  812. /**
  813. * @param opt If pass boolean, means opt.silent
  814. * @param opt.silent Default `false`. Whether trigger events.
  815. * @param opt.flush Default `undefined`.
  816. * true: Flush immediately, and then pixel in canvas can be fetched
  817. * immediately. Caution: it might affect performance.
  818. * false: Not flush.
  819. * undefined: Auto decide whether perform flush.
  820. */
  821. ECharts.prototype.dispatchAction = function (payload, opt) {
  822. if (this._disposed) {
  823. disposedWarning(this.id);
  824. return;
  825. }
  826. if (!isObject(opt)) {
  827. opt = {
  828. silent: !!opt
  829. };
  830. }
  831. if (!actions[payload.type]) {
  832. return;
  833. } // Avoid dispatch action before setOption. Especially in `connect`.
  834. if (!this._model) {
  835. return;
  836. } // May dispatchAction in rendering procedure
  837. if (this[IN_MAIN_PROCESS_KEY]) {
  838. this._pendingActions.push(payload);
  839. return;
  840. }
  841. var silent = opt.silent;
  842. doDispatchAction.call(this, payload, silent);
  843. var flush = opt.flush;
  844. if (flush) {
  845. this._zr.flush();
  846. } else if (flush !== false && env.browser.weChat) {
  847. // In WeChat embeded browser, `requestAnimationFrame` and `setInterval`
  848. // hang when sliding page (on touch event), which cause that zr does not
  849. // refresh util user interaction finished, which is not expected.
  850. // But `dispatchAction` may be called too frequently when pan on touch
  851. // screen, which impacts performance if do not throttle them.
  852. this._throttledZrFlush();
  853. }
  854. flushPendingActions.call(this, silent);
  855. triggerUpdatedEvent.call(this, silent);
  856. };
  857. ECharts.prototype.updateLabelLayout = function () {
  858. lifecycle.trigger('series:layoutlabels', this._model, this._api, {
  859. // Not adding series labels.
  860. // TODO
  861. updatedSeries: []
  862. });
  863. };
  864. ECharts.prototype.appendData = function (params) {
  865. if (this._disposed) {
  866. disposedWarning(this.id);
  867. return;
  868. }
  869. var seriesIndex = params.seriesIndex;
  870. var ecModel = this.getModel();
  871. var seriesModel = ecModel.getSeriesByIndex(seriesIndex);
  872. if (process.env.NODE_ENV !== 'production') {
  873. assert(params.data && seriesModel);
  874. }
  875. seriesModel.appendData(params); // Note: `appendData` does not support that update extent of coordinate
  876. // system, util some scenario require that. In the expected usage of
  877. // `appendData`, the initial extent of coordinate system should better
  878. // be fixed by axis `min`/`max` setting or initial data, otherwise if
  879. // the extent changed while `appendData`, the location of the painted
  880. // graphic elements have to be changed, which make the usage of
  881. // `appendData` meaningless.
  882. this._scheduler.unfinished = true;
  883. this.getZr().wakeUp();
  884. }; // A work around for no `internal` modifier in ts yet but
  885. // need to strictly hide private methods to JS users.
  886. ECharts.internalField = function () {
  887. prepare = function (ecIns) {
  888. var scheduler = ecIns._scheduler;
  889. scheduler.restorePipelines(ecIns._model);
  890. scheduler.prepareStageTasks();
  891. prepareView(ecIns, true);
  892. prepareView(ecIns, false);
  893. scheduler.plan();
  894. };
  895. /**
  896. * Prepare view instances of charts and components
  897. */
  898. prepareView = function (ecIns, isComponent) {
  899. var ecModel = ecIns._model;
  900. var scheduler = ecIns._scheduler;
  901. var viewList = isComponent ? ecIns._componentsViews : ecIns._chartsViews;
  902. var viewMap = isComponent ? ecIns._componentsMap : ecIns._chartsMap;
  903. var zr = ecIns._zr;
  904. var api = ecIns._api;
  905. for (var i = 0; i < viewList.length; i++) {
  906. viewList[i].__alive = false;
  907. }
  908. isComponent ? ecModel.eachComponent(function (componentType, model) {
  909. componentType !== 'series' && doPrepare(model);
  910. }) : ecModel.eachSeries(doPrepare);
  911. function doPrepare(model) {
  912. // By defaut view will be reused if possible for the case that `setOption` with "notMerge"
  913. // mode and need to enable transition animation. (Usually, when they have the same id, or
  914. // especially no id but have the same type & name & index. See the `model.id` generation
  915. // rule in `makeIdAndName` and `viewId` generation rule here).
  916. // But in `replaceMerge` mode, this feature should be able to disabled when it is clear that
  917. // the new model has nothing to do with the old model.
  918. var requireNewView = model.__requireNewView; // This command should not work twice.
  919. model.__requireNewView = false; // Consider: id same and type changed.
  920. var viewId = '_ec_' + model.id + '_' + model.type;
  921. var view = !requireNewView && viewMap[viewId];
  922. if (!view) {
  923. var classType = parseClassType(model.type);
  924. var Clazz = isComponent ? ComponentView.getClass(classType.main, classType.sub) : // FIXME:TS
  925. // (ChartView as ChartViewConstructor).getClass('series', classType.sub)
  926. // For backward compat, still support a chart type declared as only subType
  927. // like "liquidfill", but recommend "series.liquidfill"
  928. // But need a base class to make a type series.
  929. ChartView.getClass(classType.sub);
  930. if (process.env.NODE_ENV !== 'production') {
  931. assert(Clazz, classType.sub + ' does not exist.');
  932. }
  933. view = new Clazz();
  934. view.init(ecModel, api);
  935. viewMap[viewId] = view;
  936. viewList.push(view);
  937. zr.add(view.group);
  938. }
  939. model.__viewId = view.__id = viewId;
  940. view.__alive = true;
  941. view.__model = model;
  942. view.group.__ecComponentInfo = {
  943. mainType: model.mainType,
  944. index: model.componentIndex
  945. };
  946. !isComponent && scheduler.prepareView(view, model, ecModel, api);
  947. }
  948. for (var i = 0; i < viewList.length;) {
  949. var view = viewList[i];
  950. if (!view.__alive) {
  951. !isComponent && view.renderTask.dispose();
  952. zr.remove(view.group);
  953. view.dispose(ecModel, api);
  954. viewList.splice(i, 1);
  955. if (viewMap[view.__id] === view) {
  956. delete viewMap[view.__id];
  957. }
  958. view.__id = view.group.__ecComponentInfo = null;
  959. } else {
  960. i++;
  961. }
  962. }
  963. };
  964. updateDirectly = function (ecIns, method, payload, mainType, subType) {
  965. var ecModel = ecIns._model;
  966. ecModel.setUpdatePayload(payload); // broadcast
  967. if (!mainType) {
  968. // FIXME
  969. // Chart will not be update directly here, except set dirty.
  970. // But there is no such scenario now.
  971. each([].concat(ecIns._componentsViews).concat(ecIns._chartsViews), callView);
  972. return;
  973. }
  974. var query = {};
  975. query[mainType + 'Id'] = payload[mainType + 'Id'];
  976. query[mainType + 'Index'] = payload[mainType + 'Index'];
  977. query[mainType + 'Name'] = payload[mainType + 'Name'];
  978. var condition = {
  979. mainType: mainType,
  980. query: query
  981. };
  982. subType && (condition.subType = subType); // subType may be '' by parseClassType;
  983. var excludeSeriesId = payload.excludeSeriesId;
  984. var excludeSeriesIdMap;
  985. if (excludeSeriesId != null) {
  986. excludeSeriesIdMap = createHashMap();
  987. each(modelUtil.normalizeToArray(excludeSeriesId), function (id) {
  988. var modelId = modelUtil.convertOptionIdName(id, null);
  989. if (modelId != null) {
  990. excludeSeriesIdMap.set(modelId, true);
  991. }
  992. });
  993. }
  994. if (isHighDownPayload(payload)) {
  995. allLeaveBlur(ecIns._api);
  996. } // If dispatchAction before setOption, do nothing.
  997. ecModel && ecModel.eachComponent(condition, function (model) {
  998. var isExcluded = excludeSeriesIdMap && excludeSeriesIdMap.get(model.id) !== null;
  999. if (isExcluded) {
  1000. return;
  1001. }
  1002. ;
  1003. if (isHighDownPayload(payload)) {
  1004. if (model instanceof SeriesModel) {
  1005. if (payload.type === HIGHLIGHT_ACTION_TYPE && !payload.notBlur) {
  1006. blurSeriesFromHighlightPayload(model, payload, ecIns._api);
  1007. }
  1008. } else {
  1009. var _a = findComponentHighDownDispatchers(model.mainType, model.componentIndex, payload.name, ecIns._api),
  1010. focusSelf = _a.focusSelf,
  1011. dispatchers = _a.dispatchers;
  1012. if (payload.type === HIGHLIGHT_ACTION_TYPE && focusSelf && !payload.notBlur) {
  1013. blurComponent(model.mainType, model.componentIndex, ecIns._api);
  1014. } // PENDING:
  1015. // Whether to put this "enter emphasis" code in `ComponentView`,
  1016. // which will be the same as `ChartView` but might be not necessary
  1017. // and will be far from this logic.
  1018. if (dispatchers) {
  1019. each(dispatchers, function (dispatcher) {
  1020. payload.type === HIGHLIGHT_ACTION_TYPE ? enterEmphasis(dispatcher) : leaveEmphasis(dispatcher);
  1021. });
  1022. }
  1023. }
  1024. } else if (isSelectChangePayload(payload)) {
  1025. // TODO geo
  1026. if (model instanceof SeriesModel) {
  1027. toggleSelectionFromPayload(model, payload, ecIns._api);
  1028. updateSeriesElementSelection(model);
  1029. markStatusToUpdate(ecIns);
  1030. }
  1031. }
  1032. }, ecIns);
  1033. ecModel && ecModel.eachComponent(condition, function (model) {
  1034. var isExcluded = excludeSeriesIdMap && excludeSeriesIdMap.get(model.id) !== null;
  1035. if (isExcluded) {
  1036. return;
  1037. }
  1038. ;
  1039. callView(ecIns[mainType === 'series' ? '_chartsMap' : '_componentsMap'][model.__viewId]);
  1040. }, ecIns);
  1041. function callView(view) {
  1042. view && view.__alive && view[method] && view[method](view.__model, ecModel, ecIns._api, payload);
  1043. }
  1044. };
  1045. updateMethods = {
  1046. prepareAndUpdate: function (payload) {
  1047. prepare(this);
  1048. updateMethods.update.call(this, payload, {
  1049. // Needs to mark option changed if newOption is given.
  1050. // It's from MagicType.
  1051. // TODO If use a separate flag optionChanged in payload?
  1052. optionChanged: payload.newOption != null
  1053. });
  1054. },
  1055. update: function (payload, updateParams) {
  1056. var ecModel = this._model;
  1057. var api = this._api;
  1058. var zr = this._zr;
  1059. var coordSysMgr = this._coordSysMgr;
  1060. var scheduler = this._scheduler; // update before setOption
  1061. if (!ecModel) {
  1062. return;
  1063. }
  1064. ecModel.setUpdatePayload(payload);
  1065. scheduler.restoreData(ecModel, payload);
  1066. scheduler.performSeriesTasks(ecModel); // TODO
  1067. // Save total ecModel here for undo/redo (after restoring data and before processing data).
  1068. // Undo (restoration of total ecModel) can be carried out in 'action' or outside API call.
  1069. // Create new coordinate system each update
  1070. // In LineView may save the old coordinate system and use it to get the orignal point
  1071. coordSysMgr.create(ecModel, api);
  1072. scheduler.performDataProcessorTasks(ecModel, payload); // Current stream render is not supported in data process. So we can update
  1073. // stream modes after data processing, where the filtered data is used to
  1074. // deteming whether use progressive rendering.
  1075. updateStreamModes(this, ecModel); // We update stream modes before coordinate system updated, then the modes info
  1076. // can be fetched when coord sys updating (consider the barGrid extent fix). But
  1077. // the drawback is the full coord info can not be fetched. Fortunately this full
  1078. // coord is not requied in stream mode updater currently.
  1079. coordSysMgr.update(ecModel, api);
  1080. clearColorPalette(ecModel);
  1081. scheduler.performVisualTasks(ecModel, payload);
  1082. render(this, ecModel, api, payload, updateParams); // Set background
  1083. var backgroundColor = ecModel.get('backgroundColor') || 'transparent';
  1084. var darkMode = ecModel.get('darkMode'); // In IE8
  1085. if (!env.canvasSupported) {
  1086. var colorArr = colorTool.parse(backgroundColor);
  1087. backgroundColor = colorTool.stringify(colorArr, 'rgb');
  1088. if (colorArr[3] === 0) {
  1089. backgroundColor = 'transparent';
  1090. }
  1091. } else {
  1092. zr.setBackgroundColor(backgroundColor); // Force set dark mode.
  1093. if (darkMode != null && darkMode !== 'auto') {
  1094. zr.setDarkMode(darkMode);
  1095. }
  1096. }
  1097. lifecycle.trigger('afterupdate', ecModel, api);
  1098. },
  1099. updateTransform: function (payload) {
  1100. var _this = this;
  1101. var ecModel = this._model;
  1102. var api = this._api; // update before setOption
  1103. if (!ecModel) {
  1104. return;
  1105. }
  1106. ecModel.setUpdatePayload(payload); // ChartView.markUpdateMethod(payload, 'updateTransform');
  1107. var componentDirtyList = [];
  1108. ecModel.eachComponent(function (componentType, componentModel) {
  1109. if (componentType === 'series') {
  1110. return;
  1111. }
  1112. var componentView = _this.getViewOfComponentModel(componentModel);
  1113. if (componentView && componentView.__alive) {
  1114. if (componentView.updateTransform) {
  1115. var result = componentView.updateTransform(componentModel, ecModel, api, payload);
  1116. result && result.update && componentDirtyList.push(componentView);
  1117. } else {
  1118. componentDirtyList.push(componentView);
  1119. }
  1120. }
  1121. });
  1122. var seriesDirtyMap = createHashMap();
  1123. ecModel.eachSeries(function (seriesModel) {
  1124. var chartView = _this._chartsMap[seriesModel.__viewId];
  1125. if (chartView.updateTransform) {
  1126. var result = chartView.updateTransform(seriesModel, ecModel, api, payload);
  1127. result && result.update && seriesDirtyMap.set(seriesModel.uid, 1);
  1128. } else {
  1129. seriesDirtyMap.set(seriesModel.uid, 1);
  1130. }
  1131. });
  1132. clearColorPalette(ecModel); // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
  1133. // this._scheduler.performVisualTasks(ecModel, payload, 'layout', true);
  1134. this._scheduler.performVisualTasks(ecModel, payload, {
  1135. setDirty: true,
  1136. dirtyMap: seriesDirtyMap
  1137. }); // Currently, not call render of components. Geo render cost a lot.
  1138. // renderComponents(ecIns, ecModel, api, payload, componentDirtyList);
  1139. renderSeries(this, ecModel, api, payload, {}, seriesDirtyMap);
  1140. lifecycle.trigger('afterupdate', ecModel, api);
  1141. },
  1142. updateView: function (payload) {
  1143. var ecModel = this._model; // update before setOption
  1144. if (!ecModel) {
  1145. return;
  1146. }
  1147. ecModel.setUpdatePayload(payload);
  1148. ChartView.markUpdateMethod(payload, 'updateView');
  1149. clearColorPalette(ecModel); // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
  1150. this._scheduler.performVisualTasks(ecModel, payload, {
  1151. setDirty: true
  1152. });
  1153. render(this, ecModel, this._api, payload, {});
  1154. lifecycle.trigger('afterupdate', ecModel, this._api);
  1155. },
  1156. updateVisual: function (payload) {
  1157. // updateMethods.update.call(this, payload);
  1158. var _this = this;
  1159. var ecModel = this._model; // update before setOption
  1160. if (!ecModel) {
  1161. return;
  1162. }
  1163. ecModel.setUpdatePayload(payload); // clear all visual
  1164. ecModel.eachSeries(function (seriesModel) {
  1165. seriesModel.getData().clearAllVisual();
  1166. }); // Perform visual
  1167. ChartView.markUpdateMethod(payload, 'updateVisual');
  1168. clearColorPalette(ecModel); // Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
  1169. this._scheduler.performVisualTasks(ecModel, payload, {
  1170. visualType: 'visual',
  1171. setDirty: true
  1172. });
  1173. ecModel.eachComponent(function (componentType, componentModel) {
  1174. if (componentType !== 'series') {
  1175. var componentView = _this.getViewOfComponentModel(componentModel);
  1176. componentView && componentView.__alive && componentView.updateVisual(componentModel, ecModel, _this._api, payload);
  1177. }
  1178. });
  1179. ecModel.eachSeries(function (seriesModel) {
  1180. var chartView = _this._chartsMap[seriesModel.__viewId];
  1181. chartView.updateVisual(seriesModel, ecModel, _this._api, payload);
  1182. });
  1183. lifecycle.trigger('afterupdate', ecModel, this._api);
  1184. },
  1185. updateLayout: function (payload) {
  1186. updateMethods.update.call(this, payload);
  1187. }
  1188. };
  1189. doConvertPixel = function (ecIns, methodName, finder, value) {
  1190. if (ecIns._disposed) {
  1191. disposedWarning(ecIns.id);
  1192. return;
  1193. }
  1194. var ecModel = ecIns._model;
  1195. var coordSysList = ecIns._coordSysMgr.getCoordinateSystems();
  1196. var result;
  1197. var parsedFinder = modelUtil.parseFinder(ecModel, finder);
  1198. for (var i = 0; i < coordSysList.length; i++) {
  1199. var coordSys = coordSysList[i];
  1200. if (coordSys[methodName] && (result = coordSys[methodName](ecModel, parsedFinder, value)) != null) {
  1201. return result;
  1202. }
  1203. }
  1204. if (process.env.NODE_ENV !== 'production') {
  1205. console.warn('No coordinate system that supports ' + methodName + ' found by the given finder.');
  1206. }
  1207. };
  1208. updateStreamModes = function (ecIns, ecModel) {
  1209. var chartsMap = ecIns._chartsMap;
  1210. var scheduler = ecIns._scheduler;
  1211. ecModel.eachSeries(function (seriesModel) {
  1212. scheduler.updateStreamModes(seriesModel, chartsMap[seriesModel.__viewId]);
  1213. });
  1214. };
  1215. doDispatchAction = function (payload, silent) {
  1216. var _this = this;
  1217. var ecModel = this.getModel();
  1218. var payloadType = payload.type;
  1219. var escapeConnect = payload.escapeConnect;
  1220. var actionWrap = actions[payloadType];
  1221. var actionInfo = actionWrap.actionInfo;
  1222. var cptTypeTmp = (actionInfo.update || 'update').split(':');
  1223. var updateMethod = cptTypeTmp.pop();
  1224. var cptType = cptTypeTmp[0] != null && parseClassType(cptTypeTmp[0]);
  1225. this[IN_MAIN_PROCESS_KEY] = true;
  1226. var payloads = [payload];
  1227. var batched = false; // Batch action
  1228. if (payload.batch) {
  1229. batched = true;
  1230. payloads = map(payload.batch, function (item) {
  1231. item = defaults(extend({}, item), payload);
  1232. item.batch = null;
  1233. return item;
  1234. });
  1235. }
  1236. var eventObjBatch = [];
  1237. var eventObj;
  1238. var isSelectChange = isSelectChangePayload(payload);
  1239. var isHighDown = isHighDownPayload(payload);
  1240. each(payloads, function (batchItem) {
  1241. // Action can specify the event by return it.
  1242. eventObj = actionWrap.action(batchItem, _this._model, _this._api); // Emit event outside
  1243. eventObj = eventObj || extend({}, batchItem); // Convert type to eventType
  1244. eventObj.type = actionInfo.event || eventObj.type;
  1245. eventObjBatch.push(eventObj); // light update does not perform data process, layout and visual.
  1246. if (isHighDown) {
  1247. var _a = modelUtil.preParseFinder(payload),
  1248. queryOptionMap = _a.queryOptionMap,
  1249. mainTypeSpecified = _a.mainTypeSpecified;
  1250. var componentMainType = mainTypeSpecified ? queryOptionMap.keys()[0] : 'series';
  1251. updateDirectly(_this, updateMethod, batchItem, componentMainType);
  1252. markStatusToUpdate(_this);
  1253. } else if (isSelectChange) {
  1254. // At present `dispatchAction({ type: 'select', ... })` is not supported on components.
  1255. // geo still use 'geoselect'.
  1256. updateDirectly(_this, updateMethod, batchItem, 'series');
  1257. markStatusToUpdate(_this);
  1258. } else if (cptType) {
  1259. updateDirectly(_this, updateMethod, batchItem, cptType.main, cptType.sub);
  1260. }
  1261. });
  1262. if (updateMethod !== 'none' && !isHighDown && !isSelectChange && !cptType) {
  1263. // Still dirty
  1264. if (this[PENDING_UPDATE]) {
  1265. prepare(this);
  1266. updateMethods.update.call(this, payload);
  1267. this[PENDING_UPDATE] = null;
  1268. } else {
  1269. updateMethods[updateMethod].call(this, payload);
  1270. }
  1271. } // Follow the rule of action batch
  1272. if (batched) {
  1273. eventObj = {
  1274. type: actionInfo.event || payloadType,
  1275. escapeConnect: escapeConnect,
  1276. batch: eventObjBatch
  1277. };
  1278. } else {
  1279. eventObj = eventObjBatch[0];
  1280. }
  1281. this[IN_MAIN_PROCESS_KEY] = false;
  1282. if (!silent) {
  1283. var messageCenter = this._messageCenter;
  1284. messageCenter.trigger(eventObj.type, eventObj); // Extra triggered 'selectchanged' event
  1285. if (isSelectChange) {
  1286. var newObj = {
  1287. type: 'selectchanged',
  1288. escapeConnect: escapeConnect,
  1289. selected: getAllSelectedIndices(ecModel),
  1290. isFromClick: payload.isFromClick || false,
  1291. fromAction: payload.type,
  1292. fromActionPayload: payload
  1293. };
  1294. messageCenter.trigger(newObj.type, newObj);
  1295. }
  1296. }
  1297. };
  1298. flushPendingActions = function (silent) {
  1299. var pendingActions = this._pendingActions;
  1300. while (pendingActions.length) {
  1301. var payload = pendingActions.shift();
  1302. doDispatchAction.call(this, payload, silent);
  1303. }
  1304. };
  1305. triggerUpdatedEvent = function (silent) {
  1306. !silent && this.trigger('updated');
  1307. };
  1308. /**
  1309. * Event `rendered` is triggered when zr
  1310. * rendered. It is useful for realtime
  1311. * snapshot (reflect animation).
  1312. *
  1313. * Event `finished` is triggered when:
  1314. * (1) zrender rendering finished.
  1315. * (2) initial animation finished.
  1316. * (3) progressive rendering finished.
  1317. * (4) no pending action.
  1318. * (5) no delayed setOption needs to be processed.
  1319. */
  1320. bindRenderedEvent = function (zr, ecIns) {
  1321. zr.on('rendered', function (params) {
  1322. ecIns.trigger('rendered', params); // The `finished` event should not be triggered repeatly,
  1323. // so it should only be triggered when rendering indeed happend
  1324. // in zrender. (Consider the case that dipatchAction is keep
  1325. // triggering when mouse move).
  1326. if ( // Although zr is dirty if initial animation is not finished
  1327. // and this checking is called on frame, we also check
  1328. // animation finished for robustness.
  1329. zr.animation.isFinished() && !ecIns[PENDING_UPDATE] && !ecIns._scheduler.unfinished && !ecIns._pendingActions.length) {
  1330. ecIns.trigger('finished');
  1331. }
  1332. });
  1333. };
  1334. bindMouseEvent = function (zr, ecIns) {
  1335. zr.on('mouseover', function (e) {
  1336. var el = e.target;
  1337. var dispatcher = findEventDispatcher(el, isHighDownDispatcher);
  1338. if (dispatcher) {
  1339. handleGlobalMouseOverForHighDown(dispatcher, e, ecIns._api);
  1340. markStatusToUpdate(ecIns);
  1341. }
  1342. }).on('mouseout', function (e) {
  1343. var el = e.target;
  1344. var dispatcher = findEventDispatcher(el, isHighDownDispatcher);
  1345. if (dispatcher) {
  1346. handleGlboalMouseOutForHighDown(dispatcher, e, ecIns._api);
  1347. markStatusToUpdate(ecIns);
  1348. }
  1349. }).on('click', function (e) {
  1350. var el = e.target;
  1351. var dispatcher = findEventDispatcher(el, function (target) {
  1352. return getECData(target).dataIndex != null;
  1353. }, true);
  1354. if (dispatcher) {
  1355. var actionType = dispatcher.selected ? 'unselect' : 'select';
  1356. var ecData = getECData(dispatcher);
  1357. ecIns._api.dispatchAction({
  1358. type: actionType,
  1359. dataType: ecData.dataType,
  1360. dataIndexInside: ecData.dataIndex,
  1361. seriesIndex: ecData.seriesIndex,
  1362. isFromClick: true
  1363. });
  1364. }
  1365. });
  1366. };
  1367. clearColorPalette = function (ecModel) {
  1368. ecModel.clearColorPalette();
  1369. ecModel.eachSeries(function (seriesModel) {
  1370. seriesModel.clearColorPalette();
  1371. });
  1372. };
  1373. render = function (ecIns, ecModel, api, payload, updateParams) {
  1374. renderComponents(ecIns, ecModel, api, payload, updateParams);
  1375. each(ecIns._chartsViews, function (chart) {
  1376. chart.__alive = false;
  1377. });
  1378. renderSeries(ecIns, ecModel, api, payload, updateParams); // Remove groups of unrendered charts
  1379. each(ecIns._chartsViews, function (chart) {
  1380. if (!chart.__alive) {
  1381. chart.remove(ecModel, api);
  1382. }
  1383. });
  1384. };
  1385. renderComponents = function (ecIns, ecModel, api, payload, updateParams, dirtyList) {
  1386. each(dirtyList || ecIns._componentsViews, function (componentView) {
  1387. var componentModel = componentView.__model;
  1388. clearStates(componentModel, componentView);
  1389. componentView.render(componentModel, ecModel, api, payload);
  1390. updateZ(componentModel, componentView);
  1391. updateStates(componentModel, componentView);
  1392. });
  1393. };
  1394. /**
  1395. * Render each chart and component
  1396. */
  1397. renderSeries = function (ecIns, ecModel, api, payload, updateParams, dirtyMap) {
  1398. // Render all charts
  1399. var scheduler = ecIns._scheduler;
  1400. updateParams = extend(updateParams || {}, {
  1401. updatedSeries: ecModel.getSeries()
  1402. }); // TODO progressive?
  1403. lifecycle.trigger('series:beforeupdate', ecModel, api, updateParams);
  1404. var unfinished = false;
  1405. ecModel.eachSeries(function (seriesModel) {
  1406. var chartView = ecIns._chartsMap[seriesModel.__viewId];
  1407. chartView.__alive = true;
  1408. var renderTask = chartView.renderTask;
  1409. scheduler.updatePayload(renderTask, payload); // TODO states on marker.
  1410. clearStates(seriesModel, chartView);
  1411. if (dirtyMap && dirtyMap.get(seriesModel.uid)) {
  1412. renderTask.dirty();
  1413. }
  1414. if (renderTask.perform(scheduler.getPerformArgs(renderTask))) {
  1415. unfinished = true;
  1416. }
  1417. chartView.group.silent = !!seriesModel.get('silent'); // Should not call markRedraw on group, because it will disable zrender
  1418. // increamental render (alway render from the __startIndex each frame)
  1419. // chartView.group.markRedraw();
  1420. updateBlend(seriesModel, chartView);
  1421. updateSeriesElementSelection(seriesModel);
  1422. });
  1423. scheduler.unfinished = unfinished || scheduler.unfinished;
  1424. lifecycle.trigger('series:layoutlabels', ecModel, api, updateParams); // transition after label is layouted.
  1425. lifecycle.trigger('series:transition', ecModel, api, updateParams);
  1426. ecModel.eachSeries(function (seriesModel) {
  1427. var chartView = ecIns._chartsMap[seriesModel.__viewId]; // Update Z after labels updated. Before applying states.
  1428. updateZ(seriesModel, chartView); // NOTE: Update states after label is updated.
  1429. // label should be in normal status when layouting.
  1430. updateStates(seriesModel, chartView);
  1431. }); // If use hover layer
  1432. updateHoverLayerStatus(ecIns, ecModel);
  1433. lifecycle.trigger('series:afterupdate', ecModel, api, updateParams);
  1434. };
  1435. markStatusToUpdate = function (ecIns) {
  1436. ecIns[STATUS_NEEDS_UPDATE_KEY] = true; // Wake up zrender if it's sleep. Let it update states in the next frame.
  1437. ecIns.getZr().wakeUp();
  1438. };
  1439. applyChangedStates = function (ecIns) {
  1440. if (!ecIns[STATUS_NEEDS_UPDATE_KEY]) {
  1441. return;
  1442. }
  1443. ecIns.getZr().storage.traverse(function (el) {
  1444. // Not applied on removed elements, it may still in fading.
  1445. if (graphic.isElementRemoved(el)) {
  1446. return;
  1447. }
  1448. applyElementStates(el);
  1449. });
  1450. ecIns[STATUS_NEEDS_UPDATE_KEY] = false;
  1451. };
  1452. function applyElementStates(el) {
  1453. var newStates = [];
  1454. var oldStates = el.currentStates; // Keep other states.
  1455. for (var i = 0; i < oldStates.length; i++) {
  1456. var stateName = oldStates[i];
  1457. if (!(stateName === 'emphasis' || stateName === 'blur' || stateName === 'select')) {
  1458. newStates.push(stateName);
  1459. }
  1460. } // Only use states when it's exists.
  1461. if (el.selected && el.states.select) {
  1462. newStates.push('select');
  1463. }
  1464. if (el.hoverState === HOVER_STATE_EMPHASIS && el.states.emphasis) {
  1465. newStates.push('emphasis');
  1466. } else if (el.hoverState === HOVER_STATE_BLUR && el.states.blur) {
  1467. newStates.push('blur');
  1468. }
  1469. el.useStates(newStates);
  1470. }
  1471. function updateHoverLayerStatus(ecIns, ecModel) {
  1472. var zr = ecIns._zr;
  1473. var storage = zr.storage;
  1474. var elCount = 0;
  1475. storage.traverse(function (el) {
  1476. if (!el.isGroup) {
  1477. elCount++;
  1478. }
  1479. });
  1480. if (elCount > ecModel.get('hoverLayerThreshold') && !env.node && !env.worker) {
  1481. ecModel.eachSeries(function (seriesModel) {
  1482. if (seriesModel.preventUsingHoverLayer) {
  1483. return;
  1484. }
  1485. var chartView = ecIns._chartsMap[seriesModel.__viewId];
  1486. if (chartView.__alive) {
  1487. chartView.group.traverse(function (el) {
  1488. if (el.states.emphasis) {
  1489. el.states.emphasis.hoverLayer = true;
  1490. }
  1491. });
  1492. }
  1493. });
  1494. }
  1495. }
  1496. ;
  1497. /**
  1498. * Update chart and blend.
  1499. */
  1500. function updateBlend(seriesModel, chartView) {
  1501. var blendMode = seriesModel.get('blendMode') || null;
  1502. if (process.env.NODE_ENV !== 'production') {
  1503. if (!env.canvasSupported && blendMode && blendMode !== 'source-over') {
  1504. console.warn('Only canvas support blendMode');
  1505. }
  1506. }
  1507. chartView.group.traverse(function (el) {
  1508. // FIXME marker and other components
  1509. if (!el.isGroup) {
  1510. // DONT mark the element dirty. In case element is incremental and don't wan't to rerender.
  1511. el.style.blend = blendMode;
  1512. }
  1513. if (el.eachPendingDisplayable) {
  1514. el.eachPendingDisplayable(function (displayable) {
  1515. displayable.style.blend = blendMode;
  1516. });
  1517. }
  1518. });
  1519. }
  1520. ;
  1521. function updateZ(model, view) {
  1522. if (model.preventAutoZ) {
  1523. return;
  1524. } // Set z and zlevel
  1525. _updateZ(view.group, model.get('z') || 0, model.get('zlevel') || 0, -Infinity);
  1526. }
  1527. ;
  1528. function _updateZ(el, z, zlevel, maxZ2) {
  1529. // Group may also have textContent
  1530. var label = el.getTextContent();
  1531. var labelLine = el.getTextGuideLine();
  1532. var isGroup = el.isGroup;
  1533. if (isGroup) {
  1534. // set z & zlevel of children elements of Group
  1535. // el.traverse((childEl: Element) => _updateZ(childEl, z, zlevel));
  1536. var children = el.childrenRef();
  1537. for (var i = 0; i < children.length; i++) {
  1538. maxZ2 = Math.max(_updateZ(children[i], z, zlevel, maxZ2), maxZ2);
  1539. }
  1540. } else {
  1541. // not Group
  1542. el.z = z;
  1543. el.zlevel = zlevel;
  1544. maxZ2 = Math.max(el.z2, maxZ2);
  1545. } // always set z and zlevel if label/labelLine exists
  1546. if (label) {
  1547. label.z = z;
  1548. label.zlevel = zlevel; // lift z2 of text content
  1549. // TODO if el.emphasis.z2 is spcefied, what about textContent.
  1550. isFinite(maxZ2) && (label.z2 = maxZ2 + 2);
  1551. }
  1552. if (labelLine) {
  1553. var textGuideLineConfig = el.textGuideLineConfig;
  1554. labelLine.z = z;
  1555. labelLine.zlevel = zlevel;
  1556. isFinite(maxZ2) && (labelLine.z2 = maxZ2 + (textGuideLineConfig && textGuideLineConfig.showAbove ? 1 : -1));
  1557. }
  1558. return maxZ2;
  1559. } // Clear states without animation.
  1560. // TODO States on component.
  1561. function clearStates(model, view) {
  1562. view.group.traverse(function (el) {
  1563. // Not applied on removed elements, it may still in fading.
  1564. if (graphic.isElementRemoved(el)) {
  1565. return;
  1566. }
  1567. var textContent = el.getTextContent();
  1568. var textGuide = el.getTextGuideLine();
  1569. if (el.stateTransition) {
  1570. el.stateTransition = null;
  1571. }
  1572. if (textContent && textContent.stateTransition) {
  1573. textContent.stateTransition = null;
  1574. }
  1575. if (textGuide && textGuide.stateTransition) {
  1576. textGuide.stateTransition = null;
  1577. } // TODO If el is incremental.
  1578. if (el.hasState()) {
  1579. el.prevStates = el.currentStates;
  1580. el.clearStates();
  1581. } else if (el.prevStates) {
  1582. el.prevStates = null;
  1583. }
  1584. });
  1585. }
  1586. function updateStates(model, view) {
  1587. var stateAnimationModel = model.getModel('stateAnimation');
  1588. var enableAnimation = model.isAnimationEnabled();
  1589. var duration = stateAnimationModel.get('duration');
  1590. var stateTransition = duration > 0 ? {
  1591. duration: duration,
  1592. delay: stateAnimationModel.get('delay'),
  1593. easing: stateAnimationModel.get('easing') // additive: stateAnimationModel.get('additive')
  1594. } : null;
  1595. view.group.traverse(function (el) {
  1596. if (el.states && el.states.emphasis) {
  1597. // Not applied on removed elements, it may still in fading.
  1598. if (graphic.isElementRemoved(el)) {
  1599. return;
  1600. }
  1601. if (el instanceof graphic.Path) {
  1602. savePathStates(el);
  1603. } // Only updated on changed element. In case element is incremental and don't wan't to rerender.
  1604. // TODO, a more proper way?
  1605. if (el.__dirty) {
  1606. var prevStates = el.prevStates; // Restore states without animation
  1607. if (prevStates) {
  1608. el.useStates(prevStates);
  1609. }
  1610. } // Update state transition and enable animation again.
  1611. if (enableAnimation) {
  1612. el.stateTransition = stateTransition;
  1613. var textContent = el.getTextContent();
  1614. var textGuide = el.getTextGuideLine(); // TODO Is it necessary to animate label?
  1615. if (textContent) {
  1616. textContent.stateTransition = stateTransition;
  1617. }
  1618. if (textGuide) {
  1619. textGuide.stateTransition = stateTransition;
  1620. }
  1621. } // The use higlighted and selected flag to toggle states.
  1622. if (el.__dirty) {
  1623. applyElementStates(el);
  1624. }
  1625. }
  1626. });
  1627. }
  1628. ;
  1629. createExtensionAPI = function (ecIns) {
  1630. return new (
  1631. /** @class */
  1632. function (_super) {
  1633. __extends(class_1, _super);
  1634. function class_1() {
  1635. return _super !== null && _super.apply(this, arguments) || this;
  1636. }
  1637. class_1.prototype.getCoordinateSystems = function () {
  1638. return ecIns._coordSysMgr.getCoordinateSystems();
  1639. };
  1640. class_1.prototype.getComponentByElement = function (el) {
  1641. while (el) {
  1642. var modelInfo = el.__ecComponentInfo;
  1643. if (modelInfo != null) {
  1644. return ecIns._model.getComponent(modelInfo.mainType, modelInfo.index);
  1645. }
  1646. el = el.parent;
  1647. }
  1648. };
  1649. class_1.prototype.enterEmphasis = function (el, highlightDigit) {
  1650. enterEmphasis(el, highlightDigit);
  1651. markStatusToUpdate(ecIns);
  1652. };
  1653. class_1.prototype.leaveEmphasis = function (el, highlightDigit) {
  1654. leaveEmphasis(el, highlightDigit);
  1655. markStatusToUpdate(ecIns);
  1656. };
  1657. class_1.prototype.enterBlur = function (el) {
  1658. enterBlur(el);
  1659. markStatusToUpdate(ecIns);
  1660. };
  1661. class_1.prototype.leaveBlur = function (el) {
  1662. leaveBlur(el);
  1663. markStatusToUpdate(ecIns);
  1664. };
  1665. class_1.prototype.enterSelect = function (el) {
  1666. enterSelect(el);
  1667. markStatusToUpdate(ecIns);
  1668. };
  1669. class_1.prototype.leaveSelect = function (el) {
  1670. leaveSelect(el);
  1671. markStatusToUpdate(ecIns);
  1672. };
  1673. class_1.prototype.getModel = function () {
  1674. return ecIns.getModel();
  1675. };
  1676. class_1.prototype.getViewOfComponentModel = function (componentModel) {
  1677. return ecIns.getViewOfComponentModel(componentModel);
  1678. };
  1679. class_1.prototype.getViewOfSeriesModel = function (seriesModel) {
  1680. return ecIns.getViewOfSeriesModel(seriesModel);
  1681. };
  1682. return class_1;
  1683. }(ExtensionAPI))(ecIns);
  1684. };
  1685. enableConnect = function (chart) {
  1686. function updateConnectedChartsStatus(charts, status) {
  1687. for (var i = 0; i < charts.length; i++) {
  1688. var otherChart = charts[i];
  1689. otherChart[CONNECT_STATUS_KEY] = status;
  1690. }
  1691. }
  1692. each(eventActionMap, function (actionType, eventType) {
  1693. chart._messageCenter.on(eventType, function (event) {
  1694. if (connectedGroups[chart.group] && chart[CONNECT_STATUS_KEY] !== CONNECT_STATUS_PENDING) {
  1695. if (event && event.escapeConnect) {
  1696. return;
  1697. }
  1698. var action_1 = chart.makeActionFromEvent(event);
  1699. var otherCharts_1 = [];
  1700. each(instances, function (otherChart) {
  1701. if (otherChart !== chart && otherChart.group === chart.group) {
  1702. otherCharts_1.push(otherChart);
  1703. }
  1704. });
  1705. updateConnectedChartsStatus(otherCharts_1, CONNECT_STATUS_PENDING);
  1706. each(otherCharts_1, function (otherChart) {
  1707. if (otherChart[CONNECT_STATUS_KEY] !== CONNECT_STATUS_UPDATING) {
  1708. otherChart.dispatchAction(action_1);
  1709. }
  1710. });
  1711. updateConnectedChartsStatus(otherCharts_1, CONNECT_STATUS_UPDATED);
  1712. }
  1713. });
  1714. });
  1715. };
  1716. }();
  1717. return ECharts;
  1718. }(Eventful);
  1719. var echartsProto = ECharts.prototype;
  1720. echartsProto.on = createRegisterEventWithLowercaseECharts('on');
  1721. echartsProto.off = createRegisterEventWithLowercaseECharts('off');
  1722. /**
  1723. * @deprecated
  1724. */
  1725. // @ts-ignore
  1726. echartsProto.one = function (eventName, cb, ctx) {
  1727. var self = this;
  1728. deprecateLog('ECharts#one is deprecated.');
  1729. function wrapped() {
  1730. var args2 = [];
  1731. for (var _i = 0; _i < arguments.length; _i++) {
  1732. args2[_i] = arguments[_i];
  1733. }
  1734. cb && cb.apply && cb.apply(this, args2); // @ts-ignore
  1735. self.off(eventName, wrapped);
  1736. }
  1737. ; // @ts-ignore
  1738. this.on.call(this, eventName, wrapped, ctx);
  1739. }; // /**
  1740. // * Encode visual infomation from data after data processing
  1741. // *
  1742. // * @param {module:echarts/model/Global} ecModel
  1743. // * @param {object} layout
  1744. // * @param {boolean} [layoutFilter] `true`: only layout,
  1745. // * `false`: only not layout,
  1746. // * `null`/`undefined`: all.
  1747. // * @param {string} taskBaseTag
  1748. // * @private
  1749. // */
  1750. // function startVisualEncoding(ecIns, ecModel, api, payload, layoutFilter) {
  1751. // each(visualFuncs, function (visual, index) {
  1752. // let isLayout = visual.isLayout;
  1753. // if (layoutFilter == null
  1754. // || (layoutFilter === false && !isLayout)
  1755. // || (layoutFilter === true && isLayout)
  1756. // ) {
  1757. // visual.func(ecModel, api, payload);
  1758. // }
  1759. // });
  1760. // }
  1761. var MOUSE_EVENT_NAMES = ['click', 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'mouseup', 'globalout', 'contextmenu'];
  1762. function disposedWarning(id) {
  1763. if (process.env.NODE_ENV !== 'production') {
  1764. console.warn('Instance ' + id + ' has been disposed');
  1765. }
  1766. }
  1767. var actions = {};
  1768. /**
  1769. * Map eventType to actionType
  1770. */
  1771. var eventActionMap = {};
  1772. var dataProcessorFuncs = [];
  1773. var optionPreprocessorFuncs = [];
  1774. var visualFuncs = [];
  1775. var themeStorage = {};
  1776. var loadingEffects = {};
  1777. var instances = {};
  1778. var connectedGroups = {};
  1779. var idBase = +new Date() - 0;
  1780. var groupIdBase = +new Date() - 0;
  1781. var DOM_ATTRIBUTE_KEY = '_echarts_instance_';
  1782. /**
  1783. * @param opts.devicePixelRatio Use window.devicePixelRatio by default
  1784. * @param opts.renderer Can choose 'canvas' or 'svg' to render the chart.
  1785. * @param opts.width Use clientWidth of the input `dom` by default.
  1786. * Can be 'auto' (the same as null/undefined)
  1787. * @param opts.height Use clientHeight of the input `dom` by default.
  1788. * Can be 'auto' (the same as null/undefined)
  1789. * @param opts.locale Specify the locale.
  1790. * @param opts.useDirtyRect Enable dirty rectangle rendering or not.
  1791. */
  1792. export function init(dom, theme, opts) {
  1793. if (process.env.NODE_ENV !== 'production') {
  1794. if (!dom) {
  1795. throw new Error('Initialize failed: invalid dom.');
  1796. }
  1797. }
  1798. var existInstance = getInstanceByDom(dom);
  1799. if (existInstance) {
  1800. if (process.env.NODE_ENV !== 'production') {
  1801. console.warn('There is a chart instance already initialized on the dom.');
  1802. }
  1803. return existInstance;
  1804. }
  1805. if (process.env.NODE_ENV !== 'production') {
  1806. if (isDom(dom) && dom.nodeName.toUpperCase() !== 'CANVAS' && (!dom.clientWidth && (!opts || opts.width == null) || !dom.clientHeight && (!opts || opts.height == null))) {
  1807. console.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.');
  1808. }
  1809. }
  1810. var chart = new ECharts(dom, theme, opts);
  1811. chart.id = 'ec_' + idBase++;
  1812. instances[chart.id] = chart;
  1813. modelUtil.setAttribute(dom, DOM_ATTRIBUTE_KEY, chart.id);
  1814. enableConnect(chart);
  1815. lifecycle.trigger('afterinit', chart);
  1816. return chart;
  1817. }
  1818. /**
  1819. * @usage
  1820. * (A)
  1821. * ```js
  1822. * let chart1 = echarts.init(dom1);
  1823. * let chart2 = echarts.init(dom2);
  1824. * chart1.group = 'xxx';
  1825. * chart2.group = 'xxx';
  1826. * echarts.connect('xxx');
  1827. * ```
  1828. * (B)
  1829. * ```js
  1830. * let chart1 = echarts.init(dom1);
  1831. * let chart2 = echarts.init(dom2);
  1832. * echarts.connect('xxx', [chart1, chart2]);
  1833. * ```
  1834. */
  1835. export function connect(groupId) {
  1836. // Is array of charts
  1837. if (isArray(groupId)) {
  1838. var charts = groupId;
  1839. groupId = null; // If any chart has group
  1840. each(charts, function (chart) {
  1841. if (chart.group != null) {
  1842. groupId = chart.group;
  1843. }
  1844. });
  1845. groupId = groupId || 'g_' + groupIdBase++;
  1846. each(charts, function (chart) {
  1847. chart.group = groupId;
  1848. });
  1849. }
  1850. connectedGroups[groupId] = true;
  1851. return groupId;
  1852. }
  1853. /**
  1854. * @deprecated
  1855. */
  1856. export function disConnect(groupId) {
  1857. connectedGroups[groupId] = false;
  1858. }
  1859. /**
  1860. * Alias and backword compat
  1861. */
  1862. export var disconnect = disConnect;
  1863. /**
  1864. * Dispose a chart instance
  1865. */
  1866. export function dispose(chart) {
  1867. if (typeof chart === 'string') {
  1868. chart = instances[chart];
  1869. } else if (!(chart instanceof ECharts)) {
  1870. // Try to treat as dom
  1871. chart = getInstanceByDom(chart);
  1872. }
  1873. if (chart instanceof ECharts && !chart.isDisposed()) {
  1874. chart.dispose();
  1875. }
  1876. }
  1877. export function getInstanceByDom(dom) {
  1878. return instances[modelUtil.getAttribute(dom, DOM_ATTRIBUTE_KEY)];
  1879. }
  1880. export function getInstanceById(key) {
  1881. return instances[key];
  1882. }
  1883. /**
  1884. * Register theme
  1885. */
  1886. export function registerTheme(name, theme) {
  1887. themeStorage[name] = theme;
  1888. }
  1889. /**
  1890. * Register option preprocessor
  1891. */
  1892. export function registerPreprocessor(preprocessorFunc) {
  1893. if (indexOf(optionPreprocessorFuncs, preprocessorFunc) < 0) {
  1894. optionPreprocessorFuncs.push(preprocessorFunc);
  1895. }
  1896. }
  1897. export function registerProcessor(priority, processor) {
  1898. normalizeRegister(dataProcessorFuncs, priority, processor, PRIORITY_PROCESSOR_DEFAULT);
  1899. }
  1900. /**
  1901. * Register postIniter
  1902. * @param {Function} postInitFunc
  1903. */
  1904. export function registerPostInit(postInitFunc) {
  1905. registerUpdateLifecycle('afterinit', postInitFunc);
  1906. }
  1907. /**
  1908. * Register postUpdater
  1909. * @param {Function} postUpdateFunc
  1910. */
  1911. export function registerPostUpdate(postUpdateFunc) {
  1912. registerUpdateLifecycle('afterupdate', postUpdateFunc);
  1913. }
  1914. export function registerUpdateLifecycle(name, cb) {
  1915. lifecycle.on(name, cb);
  1916. }
  1917. export function registerAction(actionInfo, eventName, action) {
  1918. if (typeof eventName === 'function') {
  1919. action = eventName;
  1920. eventName = '';
  1921. }
  1922. var actionType = isObject(actionInfo) ? actionInfo.type : [actionInfo, actionInfo = {
  1923. event: eventName
  1924. }][0]; // Event name is all lowercase
  1925. actionInfo.event = (actionInfo.event || actionType).toLowerCase();
  1926. eventName = actionInfo.event;
  1927. if (eventActionMap[eventName]) {
  1928. // Already registered.
  1929. return;
  1930. } // Validate action type and event name.
  1931. assert(ACTION_REG.test(actionType) && ACTION_REG.test(eventName));
  1932. if (!actions[actionType]) {
  1933. actions[actionType] = {
  1934. action: action,
  1935. actionInfo: actionInfo
  1936. };
  1937. }
  1938. eventActionMap[eventName] = actionType;
  1939. }
  1940. export function registerCoordinateSystem(type, coordSysCreator) {
  1941. CoordinateSystemManager.register(type, coordSysCreator);
  1942. }
  1943. /**
  1944. * Get dimensions of specified coordinate system.
  1945. * @param {string} type
  1946. * @return {Array.<string|Object>}
  1947. */
  1948. export function getCoordinateSystemDimensions(type) {
  1949. var coordSysCreator = CoordinateSystemManager.get(type);
  1950. if (coordSysCreator) {
  1951. return coordSysCreator.getDimensionsInfo ? coordSysCreator.getDimensionsInfo() : coordSysCreator.dimensions.slice();
  1952. }
  1953. }
  1954. export { registerLocale } from './locale';
  1955. function registerLayout(priority, layoutTask) {
  1956. normalizeRegister(visualFuncs, priority, layoutTask, PRIORITY_VISUAL_LAYOUT, 'layout');
  1957. }
  1958. function registerVisual(priority, visualTask) {
  1959. normalizeRegister(visualFuncs, priority, visualTask, PRIORITY_VISUAL_CHART, 'visual');
  1960. }
  1961. export { registerLayout, registerVisual };
  1962. var registeredTasks = [];
  1963. function normalizeRegister(targetList, priority, fn, defaultPriority, visualType) {
  1964. if (isFunction(priority) || isObject(priority)) {
  1965. fn = priority;
  1966. priority = defaultPriority;
  1967. }
  1968. if (process.env.NODE_ENV !== 'production') {
  1969. if (isNaN(priority) || priority == null) {
  1970. throw new Error('Illegal priority');
  1971. } // Check duplicate
  1972. each(targetList, function (wrap) {
  1973. assert(wrap.__raw !== fn);
  1974. });
  1975. } // Already registered
  1976. if (indexOf(registeredTasks, fn) >= 0) {
  1977. return;
  1978. }
  1979. registeredTasks.push(fn);
  1980. var stageHandler = Scheduler.wrapStageHandler(fn, visualType);
  1981. stageHandler.__prio = priority;
  1982. stageHandler.__raw = fn;
  1983. targetList.push(stageHandler);
  1984. }
  1985. export function registerLoading(name, loadingFx) {
  1986. loadingEffects[name] = loadingFx;
  1987. }
  1988. /**
  1989. * ZRender need a canvas context to do measureText.
  1990. * But in node environment canvas may be created by node-canvas.
  1991. * So we need to specify how to create a canvas instead of using document.createElement('canvas')
  1992. *
  1993. * Be careful of using it in the browser.
  1994. *
  1995. * @example
  1996. * let Canvas = require('canvas');
  1997. * let echarts = require('echarts');
  1998. * echarts.setCanvasCreator(function () {
  1999. * // Small size is enough.
  2000. * return new Canvas(32, 32);
  2001. * });
  2002. */
  2003. export function setCanvasCreator(creator) {
  2004. $override('createCanvas', creator);
  2005. }
  2006. /**
  2007. * The parameters and usage: see `geoSourceManager.registerMap`.
  2008. * Compatible with previous `echarts.registerMap`.
  2009. */
  2010. export function registerMap(mapName, geoJson, specialAreas) {
  2011. geoSourceManager.registerMap(mapName, geoJson, specialAreas);
  2012. }
  2013. export function getMap(mapName) {
  2014. return geoSourceManager.getMapForUser(mapName);
  2015. }
  2016. export var registerTransform = registerExternalTransform;
  2017. /**
  2018. * Globa dispatchAction to a specified chart instance.
  2019. */
  2020. // export function dispatchAction(payload: { chartId: string } & Payload, opt?: Parameters<ECharts['dispatchAction']>[1]) {
  2021. // if (!payload || !payload.chartId) {
  2022. // // Must have chartId to find chart
  2023. // return;
  2024. // }
  2025. // const chart = instances[payload.chartId];
  2026. // if (chart) {
  2027. // chart.dispatchAction(payload, opt);
  2028. // }
  2029. // }
  2030. // Buitlin global visual
  2031. registerVisual(PRIORITY_VISUAL_GLOBAL, seriesStyleTask);
  2032. registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataStyleTask);
  2033. registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataColorPaletteTask);
  2034. registerVisual(PRIORITY_VISUAL_GLOBAL, seriesSymbolTask);
  2035. registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataSymbolTask);
  2036. registerVisual(PRIORITY_VISUAL_DECAL, decal);
  2037. registerPreprocessor(backwardCompat);
  2038. registerProcessor(PRIORITY_PROCESSOR_DATASTACK, dataStack);
  2039. registerLoading('default', loadingDefault); // Default actions
  2040. registerAction({
  2041. type: HIGHLIGHT_ACTION_TYPE,
  2042. event: HIGHLIGHT_ACTION_TYPE,
  2043. update: HIGHLIGHT_ACTION_TYPE
  2044. }, noop);
  2045. registerAction({
  2046. type: DOWNPLAY_ACTION_TYPE,
  2047. event: DOWNPLAY_ACTION_TYPE,
  2048. update: DOWNPLAY_ACTION_TYPE
  2049. }, noop);
  2050. registerAction({
  2051. type: SELECT_ACTION_TYPE,
  2052. event: SELECT_ACTION_TYPE,
  2053. update: SELECT_ACTION_TYPE
  2054. }, noop);
  2055. registerAction({
  2056. type: UNSELECT_ACTION_TYPE,
  2057. event: UNSELECT_ACTION_TYPE,
  2058. update: UNSELECT_ACTION_TYPE
  2059. }, noop);
  2060. registerAction({
  2061. type: TOGGLE_SELECT_ACTION_TYPE,
  2062. event: TOGGLE_SELECT_ACTION_TYPE,
  2063. update: TOGGLE_SELECT_ACTION_TYPE
  2064. }, noop); // Default theme
  2065. registerTheme('light', lightTheme);
  2066. registerTheme('dark', darkTheme); // For backward compatibility, where the namespace `dataTool` will
  2067. // be mounted on `echarts` is the extension `dataTool` is imported.
  2068. export var dataTool = {};