echarts.js 82 KB

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