Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 
 
 

74814 řádky
2.3 MiB

  1. (function webpackUniversalModuleDefinition(root, factory) {
  2. if(typeof exports === 'object' && typeof module === 'object')
  3. module.exports = factory();
  4. else if(typeof define === 'function' && define.amd)
  5. define([], factory);
  6. else if(typeof exports === 'object')
  7. exports["echarts"] = factory();
  8. else
  9. root["echarts"] = factory();
  10. })(this, function() {
  11. return /******/ (function(modules) { // webpackBootstrap
  12. /******/ // The module cache
  13. /******/ var installedModules = {};
  14. /******/ // The require function
  15. /******/ function __webpack_require__(moduleId) {
  16. /******/ // Check if module is in cache
  17. /******/ if(installedModules[moduleId])
  18. /******/ return installedModules[moduleId].exports;
  19. /******/ // Create a new module (and put it into the cache)
  20. /******/ var module = installedModules[moduleId] = {
  21. /******/ exports: {},
  22. /******/ id: moduleId,
  23. /******/ loaded: false
  24. /******/ };
  25. /******/ // Execute the module function
  26. /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  27. /******/ // Flag the module as loaded
  28. /******/ module.loaded = true;
  29. /******/ // Return the exports of the module
  30. /******/ return module.exports;
  31. /******/ }
  32. /******/ // expose the modules object (__webpack_modules__)
  33. /******/ __webpack_require__.m = modules;
  34. /******/ // expose the module cache
  35. /******/ __webpack_require__.c = installedModules;
  36. /******/ // __webpack_public_path__
  37. /******/ __webpack_require__.p = "";
  38. /******/ // Load entry module and return exports
  39. /******/ return __webpack_require__(0);
  40. /******/ })
  41. /************************************************************************/
  42. /******/ ([
  43. /* 0 */
  44. /***/ function(module, exports, __webpack_require__) {
  45. /**
  46. * Export echarts as CommonJS module
  47. */
  48. module.exports = __webpack_require__(1);
  49. // Import all charts and components
  50. __webpack_require__(113);
  51. __webpack_require__(139);
  52. __webpack_require__(146);
  53. __webpack_require__(155);
  54. __webpack_require__(159);
  55. __webpack_require__(169);
  56. __webpack_require__(192);
  57. __webpack_require__(204);
  58. __webpack_require__(225);
  59. __webpack_require__(229);
  60. __webpack_require__(233);
  61. __webpack_require__(250);
  62. __webpack_require__(256);
  63. __webpack_require__(263);
  64. __webpack_require__(269);
  65. __webpack_require__(273);
  66. __webpack_require__(282);
  67. __webpack_require__(286);
  68. __webpack_require__(289);
  69. __webpack_require__(312);
  70. __webpack_require__(318);
  71. __webpack_require__(319);
  72. __webpack_require__(320);
  73. __webpack_require__(326);
  74. __webpack_require__(297);
  75. __webpack_require__(330);
  76. __webpack_require__(343);
  77. __webpack_require__(234);
  78. __webpack_require__(290);
  79. __webpack_require__(346);
  80. __webpack_require__(357);
  81. __webpack_require__(361);
  82. __webpack_require__(362);
  83. __webpack_require__(375);
  84. __webpack_require__(390);
  85. __webpack_require__(396);
  86. __webpack_require__(399);
  87. __webpack_require__(402);
  88. __webpack_require__(411);
  89. __webpack_require__(423);
  90. /***/ },
  91. /* 1 */
  92. /***/ function(module, exports, __webpack_require__) {
  93. // Enable DEV mode when using source code without build. which has no __DEV__ variable
  94. // In build process 'typeof __DEV__' will be replace with 'boolean'
  95. // So this code will be removed or disabled anyway after built.
  96. if (false) {
  97. // In browser
  98. if (typeof window !== 'undefined') {
  99. window.__DEV__ = true;
  100. }
  101. // In node
  102. else if (typeof global !== 'undefined') {
  103. global.__DEV__ = true;
  104. }
  105. }
  106. /*!
  107. * ECharts, a javascript interactive chart library.
  108. *
  109. * Copyright (c) 2015, Baidu Inc.
  110. * All rights reserved.
  111. *
  112. * LICENSE
  113. * https://github.com/ecomfe/echarts/blob/master/LICENSE.txt
  114. */
  115. /**
  116. * @module echarts
  117. */
  118. var env = __webpack_require__(2);
  119. var GlobalModel = __webpack_require__(3);
  120. var ExtensionAPI = __webpack_require__(75);
  121. var CoordinateSystemManager = __webpack_require__(76);
  122. var OptionManager = __webpack_require__(77);
  123. var ComponentModel = __webpack_require__(69);
  124. var SeriesModel = __webpack_require__(78);
  125. var ComponentView = __webpack_require__(79);
  126. var ChartView = __webpack_require__(80);
  127. var graphic = __webpack_require__(18);
  128. var modelUtil = __webpack_require__(5);
  129. var throttle = __webpack_require__(81);
  130. var zrender = __webpack_require__(82);
  131. var zrUtil = __webpack_require__(4);
  132. var colorTool = __webpack_require__(31);
  133. var Eventful = __webpack_require__(25);
  134. var timsort = __webpack_require__(86);
  135. var each = zrUtil.each;
  136. var parseClassType = ComponentModel.parseClassType;
  137. var PRIORITY_PROCESSOR_FILTER = 1000;
  138. var PRIORITY_PROCESSOR_STATISTIC = 5000;
  139. var PRIORITY_VISUAL_LAYOUT = 1000;
  140. var PRIORITY_VISUAL_GLOBAL = 2000;
  141. var PRIORITY_VISUAL_CHART = 3000;
  142. var PRIORITY_VISUAL_COMPONENT = 4000;
  143. // FIXME
  144. // necessary?
  145. var PRIORITY_VISUAL_BRUSH = 5000;
  146. // Main process have three entries: `setOption`, `dispatchAction` and `resize`,
  147. // where they must not be invoked nestedly, except the only case: invoke
  148. // dispatchAction with updateMethod "none" in main process.
  149. // This flag is used to carry out this rule.
  150. // All events will be triggered out side main process (i.e. when !this[IN_MAIN_PROCESS]).
  151. var IN_MAIN_PROCESS = '__flagInMainProcess';
  152. var HAS_GRADIENT_OR_PATTERN_BG = '__hasGradientOrPatternBg';
  153. var OPTION_UPDATED = '__optionUpdated';
  154. var ACTION_REG = /^[a-zA-Z0-9_]+$/;
  155. function createRegisterEventWithLowercaseName(method) {
  156. return function (eventName, handler, context) {
  157. // Event name is all lowercase
  158. eventName = eventName && eventName.toLowerCase();
  159. Eventful.prototype[method].call(this, eventName, handler, context);
  160. };
  161. }
  162. /**
  163. * @module echarts~MessageCenter
  164. */
  165. function MessageCenter() {
  166. Eventful.call(this);
  167. }
  168. MessageCenter.prototype.on = createRegisterEventWithLowercaseName('on');
  169. MessageCenter.prototype.off = createRegisterEventWithLowercaseName('off');
  170. MessageCenter.prototype.one = createRegisterEventWithLowercaseName('one');
  171. zrUtil.mixin(MessageCenter, Eventful);
  172. /**
  173. * @module echarts~ECharts
  174. */
  175. function ECharts(dom, theme, opts) {
  176. opts = opts || {};
  177. // Get theme by name
  178. if (typeof theme === 'string') {
  179. theme = themeStorage[theme];
  180. }
  181. /**
  182. * @type {string}
  183. */
  184. this.id;
  185. /**
  186. * Group id
  187. * @type {string}
  188. */
  189. this.group;
  190. /**
  191. * @type {HTMLDomElement}
  192. * @private
  193. */
  194. this._dom = dom;
  195. /**
  196. * @type {module:zrender/ZRender}
  197. * @private
  198. */
  199. var zr = this._zr = zrender.init(dom, {
  200. renderer: opts.renderer || 'canvas',
  201. devicePixelRatio: opts.devicePixelRatio,
  202. width: opts.width,
  203. height: opts.height
  204. });
  205. /**
  206. * Expect 60 pfs.
  207. * @type {Function}
  208. * @private
  209. */
  210. this._throttledZrFlush = throttle.throttle(zrUtil.bind(zr.flush, zr), 17);
  211. /**
  212. * @type {Object}
  213. * @private
  214. */
  215. this._theme = zrUtil.clone(theme);
  216. /**
  217. * @type {Array.<module:echarts/view/Chart>}
  218. * @private
  219. */
  220. this._chartsViews = [];
  221. /**
  222. * @type {Object.<string, module:echarts/view/Chart>}
  223. * @private
  224. */
  225. this._chartsMap = {};
  226. /**
  227. * @type {Array.<module:echarts/view/Component>}
  228. * @private
  229. */
  230. this._componentsViews = [];
  231. /**
  232. * @type {Object.<string, module:echarts/view/Component>}
  233. * @private
  234. */
  235. this._componentsMap = {};
  236. /**
  237. * @type {module:echarts/CoordinateSystem}
  238. * @private
  239. */
  240. this._coordSysMgr = new CoordinateSystemManager();
  241. /**
  242. * @type {module:echarts/ExtensionAPI}
  243. * @private
  244. */
  245. this._api = createExtensionAPI(this);
  246. Eventful.call(this);
  247. /**
  248. * @type {module:echarts~MessageCenter}
  249. * @private
  250. */
  251. this._messageCenter = new MessageCenter();
  252. // Init mouse events
  253. this._initEvents();
  254. // In case some people write `window.onresize = chart.resize`
  255. this.resize = zrUtil.bind(this.resize, this);
  256. // Can't dispatch action during rendering procedure
  257. this._pendingActions = [];
  258. // Sort on demand
  259. function prioritySortFunc(a, b) {
  260. return a.prio - b.prio;
  261. }
  262. timsort(visualFuncs, prioritySortFunc);
  263. timsort(dataProcessorFuncs, prioritySortFunc);
  264. zr.animation.on('frame', this._onframe, this);
  265. // ECharts instance can be used as value.
  266. zrUtil.setAsPrimitive(this);
  267. }
  268. var echartsProto = ECharts.prototype;
  269. echartsProto._onframe = function () {
  270. // Lazy update
  271. if (this[OPTION_UPDATED]) {
  272. var silent = this[OPTION_UPDATED].silent;
  273. this[IN_MAIN_PROCESS] = true;
  274. updateMethods.prepareAndUpdate.call(this);
  275. this[IN_MAIN_PROCESS] = false;
  276. this[OPTION_UPDATED] = false;
  277. flushPendingActions.call(this, silent);
  278. triggerUpdatedEvent.call(this, silent);
  279. }
  280. };
  281. /**
  282. * @return {HTMLDomElement}
  283. */
  284. echartsProto.getDom = function () {
  285. return this._dom;
  286. };
  287. /**
  288. * @return {module:zrender~ZRender}
  289. */
  290. echartsProto.getZr = function () {
  291. return this._zr;
  292. };
  293. /**
  294. * Usage:
  295. * chart.setOption(option, notMerge, lazyUpdate);
  296. * chart.setOption(option, {
  297. * notMerge: ...,
  298. * lazyUpdate: ...,
  299. * silent: ...
  300. * });
  301. *
  302. * @param {Object} option
  303. * @param {Object|boolean} [opts] opts or notMerge.
  304. * @param {boolean} [opts.notMerge=false]
  305. * @param {boolean} [opts.lazyUpdate=false] Useful when setOption frequently.
  306. */
  307. echartsProto.setOption = function (option, notMerge, lazyUpdate) {
  308. if (true) {
  309. zrUtil.assert(!this[IN_MAIN_PROCESS], '`setOption` should not be called during main process.');
  310. }
  311. var silent;
  312. if (zrUtil.isObject(notMerge)) {
  313. lazyUpdate = notMerge.lazyUpdate;
  314. silent = notMerge.silent;
  315. notMerge = notMerge.notMerge;
  316. }
  317. this[IN_MAIN_PROCESS] = true;
  318. if (!this._model || notMerge) {
  319. var optionManager = new OptionManager(this._api);
  320. var theme = this._theme;
  321. var ecModel = this._model = new GlobalModel(null, null, theme, optionManager);
  322. ecModel.init(null, null, theme, optionManager);
  323. }
  324. this._model.setOption(option, optionPreprocessorFuncs);
  325. if (lazyUpdate) {
  326. this[OPTION_UPDATED] = {silent: silent};
  327. this[IN_MAIN_PROCESS] = false;
  328. }
  329. else {
  330. updateMethods.prepareAndUpdate.call(this);
  331. // Ensure zr refresh sychronously, and then pixel in canvas can be
  332. // fetched after `setOption`.
  333. this._zr.flush();
  334. this[OPTION_UPDATED] = false;
  335. this[IN_MAIN_PROCESS] = false;
  336. flushPendingActions.call(this, silent);
  337. triggerUpdatedEvent.call(this, silent);
  338. }
  339. };
  340. /**
  341. * @DEPRECATED
  342. */
  343. echartsProto.setTheme = function () {
  344. console.log('ECharts#setTheme() is DEPRECATED in ECharts 3.0');
  345. };
  346. /**
  347. * @return {module:echarts/model/Global}
  348. */
  349. echartsProto.getModel = function () {
  350. return this._model;
  351. };
  352. /**
  353. * @return {Object}
  354. */
  355. echartsProto.getOption = function () {
  356. return this._model && this._model.getOption();
  357. };
  358. /**
  359. * @return {number}
  360. */
  361. echartsProto.getWidth = function () {
  362. return this._zr.getWidth();
  363. };
  364. /**
  365. * @return {number}
  366. */
  367. echartsProto.getHeight = function () {
  368. return this._zr.getHeight();
  369. };
  370. /**
  371. * @return {number}
  372. */
  373. echartsProto.getDevicePixelRatio = function () {
  374. return this._zr.painter.dpr || window.devicePixelRatio || 1;
  375. };
  376. /**
  377. * Get canvas which has all thing rendered
  378. * @param {Object} opts
  379. * @param {string} [opts.backgroundColor]
  380. */
  381. echartsProto.getRenderedCanvas = function (opts) {
  382. if (!env.canvasSupported) {
  383. return;
  384. }
  385. opts = opts || {};
  386. opts.pixelRatio = opts.pixelRatio || 1;
  387. opts.backgroundColor = opts.backgroundColor
  388. || this._model.get('backgroundColor');
  389. var zr = this._zr;
  390. var list = zr.storage.getDisplayList();
  391. // Stop animations
  392. zrUtil.each(list, function (el) {
  393. el.stopAnimation(true);
  394. });
  395. return zr.painter.getRenderedCanvas(opts);
  396. };
  397. /**
  398. * @return {string}
  399. * @param {Object} opts
  400. * @param {string} [opts.type='png']
  401. * @param {string} [opts.pixelRatio=1]
  402. * @param {string} [opts.backgroundColor]
  403. * @param {string} [opts.excludeComponents]
  404. */
  405. echartsProto.getDataURL = function (opts) {
  406. opts = opts || {};
  407. var excludeComponents = opts.excludeComponents;
  408. var ecModel = this._model;
  409. var excludesComponentViews = [];
  410. var self = this;
  411. each(excludeComponents, function (componentType) {
  412. ecModel.eachComponent({
  413. mainType: componentType
  414. }, function (component) {
  415. var view = self._componentsMap[component.__viewId];
  416. if (!view.group.ignore) {
  417. excludesComponentViews.push(view);
  418. view.group.ignore = true;
  419. }
  420. });
  421. });
  422. var url = this.getRenderedCanvas(opts).toDataURL(
  423. 'image/' + (opts && opts.type || 'png')
  424. );
  425. each(excludesComponentViews, function (view) {
  426. view.group.ignore = false;
  427. });
  428. return url;
  429. };
  430. /**
  431. * @return {string}
  432. * @param {Object} opts
  433. * @param {string} [opts.type='png']
  434. * @param {string} [opts.pixelRatio=1]
  435. * @param {string} [opts.backgroundColor]
  436. */
  437. echartsProto.getConnectedDataURL = function (opts) {
  438. if (!env.canvasSupported) {
  439. return;
  440. }
  441. var groupId = this.group;
  442. var mathMin = Math.min;
  443. var mathMax = Math.max;
  444. var MAX_NUMBER = Infinity;
  445. if (connectedGroups[groupId]) {
  446. var left = MAX_NUMBER;
  447. var top = MAX_NUMBER;
  448. var right = -MAX_NUMBER;
  449. var bottom = -MAX_NUMBER;
  450. var canvasList = [];
  451. var dpr = (opts && opts.pixelRatio) || 1;
  452. zrUtil.each(instances, function (chart, id) {
  453. if (chart.group === groupId) {
  454. var canvas = chart.getRenderedCanvas(
  455. zrUtil.clone(opts)
  456. );
  457. var boundingRect = chart.getDom().getBoundingClientRect();
  458. left = mathMin(boundingRect.left, left);
  459. top = mathMin(boundingRect.top, top);
  460. right = mathMax(boundingRect.right, right);
  461. bottom = mathMax(boundingRect.bottom, bottom);
  462. canvasList.push({
  463. dom: canvas,
  464. left: boundingRect.left,
  465. top: boundingRect.top
  466. });
  467. }
  468. });
  469. left *= dpr;
  470. top *= dpr;
  471. right *= dpr;
  472. bottom *= dpr;
  473. var width = right - left;
  474. var height = bottom - top;
  475. var targetCanvas = zrUtil.createCanvas();
  476. targetCanvas.width = width;
  477. targetCanvas.height = height;
  478. var zr = zrender.init(targetCanvas);
  479. each(canvasList, function (item) {
  480. var img = new graphic.Image({
  481. style: {
  482. x: item.left * dpr - left,
  483. y: item.top * dpr - top,
  484. image: item.dom
  485. }
  486. });
  487. zr.add(img);
  488. });
  489. zr.refreshImmediately();
  490. return targetCanvas.toDataURL('image/' + (opts && opts.type || 'png'));
  491. }
  492. else {
  493. return this.getDataURL(opts);
  494. }
  495. };
  496. /**
  497. * Convert from logical coordinate system to pixel coordinate system.
  498. * See CoordinateSystem#convertToPixel.
  499. * @param {string|Object} finder
  500. * If string, e.g., 'geo', means {geoIndex: 0}.
  501. * If Object, could contain some of these properties below:
  502. * {
  503. * seriesIndex / seriesId / seriesName,
  504. * geoIndex / geoId, geoName,
  505. * bmapIndex / bmapId / bmapName,
  506. * xAxisIndex / xAxisId / xAxisName,
  507. * yAxisIndex / yAxisId / yAxisName,
  508. * gridIndex / gridId / gridName,
  509. * ... (can be extended)
  510. * }
  511. * @param {Array|number} value
  512. * @return {Array|number} result
  513. */
  514. echartsProto.convertToPixel = zrUtil.curry(doConvertPixel, 'convertToPixel');
  515. /**
  516. * Convert from pixel coordinate system to logical coordinate system.
  517. * See CoordinateSystem#convertFromPixel.
  518. * @param {string|Object} finder
  519. * If string, e.g., 'geo', means {geoIndex: 0}.
  520. * If Object, could contain some of these properties below:
  521. * {
  522. * seriesIndex / seriesId / seriesName,
  523. * geoIndex / geoId / geoName,
  524. * bmapIndex / bmapId / bmapName,
  525. * xAxisIndex / xAxisId / xAxisName,
  526. * yAxisIndex / yAxisId / yAxisName
  527. * gridIndex / gridId / gridName,
  528. * ... (can be extended)
  529. * }
  530. * @param {Array|number} value
  531. * @return {Array|number} result
  532. */
  533. echartsProto.convertFromPixel = zrUtil.curry(doConvertPixel, 'convertFromPixel');
  534. function doConvertPixel(methodName, finder, value) {
  535. var ecModel = this._model;
  536. var coordSysList = this._coordSysMgr.getCoordinateSystems();
  537. var result;
  538. finder = modelUtil.parseFinder(ecModel, finder);
  539. for (var i = 0; i < coordSysList.length; i++) {
  540. var coordSys = coordSysList[i];
  541. if (coordSys[methodName]
  542. && (result = coordSys[methodName](ecModel, finder, value)) != null
  543. ) {
  544. return result;
  545. }
  546. }
  547. if (true) {
  548. console.warn(
  549. 'No coordinate system that supports ' + methodName + ' found by the given finder.'
  550. );
  551. }
  552. }
  553. /**
  554. * Is the specified coordinate systems or components contain the given pixel point.
  555. * @param {string|Object} finder
  556. * If string, e.g., 'geo', means {geoIndex: 0}.
  557. * If Object, could contain some of these properties below:
  558. * {
  559. * seriesIndex / seriesId / seriesName,
  560. * geoIndex / geoId / geoName,
  561. * bmapIndex / bmapId / bmapName,
  562. * xAxisIndex / xAxisId / xAxisName,
  563. * yAxisIndex / yAxisId / yAxisName,
  564. * gridIndex / gridId / gridName,
  565. * ... (can be extended)
  566. * }
  567. * @param {Array|number} value
  568. * @return {boolean} result
  569. */
  570. echartsProto.containPixel = function (finder, value) {
  571. var ecModel = this._model;
  572. var result;
  573. finder = modelUtil.parseFinder(ecModel, finder);
  574. zrUtil.each(finder, function (models, key) {
  575. key.indexOf('Models') >= 0 && zrUtil.each(models, function (model) {
  576. var coordSys = model.coordinateSystem;
  577. if (coordSys && coordSys.containPoint) {
  578. result |= !!coordSys.containPoint(value);
  579. }
  580. else if (key === 'seriesModels') {
  581. var view = this._chartsMap[model.__viewId];
  582. if (view && view.containPoint) {
  583. result |= view.containPoint(value, model);
  584. }
  585. else {
  586. if (true) {
  587. console.warn(key + ': ' + (view
  588. ? 'The found component do not support containPoint.'
  589. : 'No view mapping to the found component.'
  590. ));
  591. }
  592. }
  593. }
  594. else {
  595. if (true) {
  596. console.warn(key + ': containPoint is not supported');
  597. }
  598. }
  599. }, this);
  600. }, this);
  601. return !!result;
  602. };
  603. /**
  604. * Get visual from series or data.
  605. * @param {string|Object} finder
  606. * If string, e.g., 'series', means {seriesIndex: 0}.
  607. * If Object, could contain some of these properties below:
  608. * {
  609. * seriesIndex / seriesId / seriesName,
  610. * dataIndex / dataIndexInside
  611. * }
  612. * If dataIndex is not specified, series visual will be fetched,
  613. * but not data item visual.
  614. * If all of seriesIndex, seriesId, seriesName are not specified,
  615. * visual will be fetched from first series.
  616. * @param {string} visualType 'color', 'symbol', 'symbolSize'
  617. */
  618. echartsProto.getVisual = function (finder, visualType) {
  619. var ecModel = this._model;
  620. finder = modelUtil.parseFinder(ecModel, finder, {defaultMainType: 'series'});
  621. var seriesModel = finder.seriesModel;
  622. if (true) {
  623. if (!seriesModel) {
  624. console.warn('There is no specified seires model');
  625. }
  626. }
  627. var data = seriesModel.getData();
  628. var dataIndexInside = finder.hasOwnProperty('dataIndexInside')
  629. ? finder.dataIndexInside
  630. : finder.hasOwnProperty('dataIndex')
  631. ? data.indexOfRawIndex(finder.dataIndex)
  632. : null;
  633. return dataIndexInside != null
  634. ? data.getItemVisual(dataIndexInside, visualType)
  635. : data.getVisual(visualType);
  636. };
  637. /**
  638. * Get view of corresponding component model
  639. * @param {module:echarts/model/Component} componentModel
  640. * @return {module:echarts/view/Component}
  641. */
  642. echartsProto.getViewOfComponentModel = function (componentModel) {
  643. return this._componentsMap[componentModel.__viewId];
  644. };
  645. /**
  646. * Get view of corresponding series model
  647. * @param {module:echarts/model/Series} seriesModel
  648. * @return {module:echarts/view/Chart}
  649. */
  650. echartsProto.getViewOfSeriesModel = function (seriesModel) {
  651. return this._chartsMap[seriesModel.__viewId];
  652. };
  653. var updateMethods = {
  654. /**
  655. * @param {Object} payload
  656. * @private
  657. */
  658. update: function (payload) {
  659. // console.profile && console.profile('update');
  660. var ecModel = this._model;
  661. var api = this._api;
  662. var coordSysMgr = this._coordSysMgr;
  663. var zr = this._zr;
  664. // update before setOption
  665. if (!ecModel) {
  666. return;
  667. }
  668. // Fixme First time update ?
  669. ecModel.restoreData();
  670. // TODO
  671. // Save total ecModel here for undo/redo (after restoring data and before processing data).
  672. // Undo (restoration of total ecModel) can be carried out in 'action' or outside API call.
  673. // Create new coordinate system each update
  674. // In LineView may save the old coordinate system and use it to get the orignal point
  675. coordSysMgr.create(this._model, this._api);
  676. processData.call(this, ecModel, api);
  677. stackSeriesData.call(this, ecModel);
  678. coordSysMgr.update(ecModel, api);
  679. doVisualEncoding.call(this, ecModel, payload);
  680. doRender.call(this, ecModel, payload);
  681. // Set background
  682. var backgroundColor = ecModel.get('backgroundColor') || 'transparent';
  683. var painter = zr.painter;
  684. // TODO all use clearColor ?
  685. if (painter.isSingleCanvas && painter.isSingleCanvas()) {
  686. zr.configLayer(0, {
  687. clearColor: backgroundColor
  688. });
  689. }
  690. else {
  691. // In IE8
  692. if (!env.canvasSupported) {
  693. var colorArr = colorTool.parse(backgroundColor);
  694. backgroundColor = colorTool.stringify(colorArr, 'rgb');
  695. if (colorArr[3] === 0) {
  696. backgroundColor = 'transparent';
  697. }
  698. }
  699. if (backgroundColor.colorStops || backgroundColor.image) {
  700. // Gradient background
  701. // FIXME Fixed layer?
  702. zr.configLayer(0, {
  703. clearColor: backgroundColor
  704. });
  705. this[HAS_GRADIENT_OR_PATTERN_BG] = true;
  706. this._dom.style.background = 'transparent';
  707. }
  708. else {
  709. if (this[HAS_GRADIENT_OR_PATTERN_BG]) {
  710. zr.configLayer(0, {
  711. clearColor: null
  712. });
  713. }
  714. this[HAS_GRADIENT_OR_PATTERN_BG] = false;
  715. this._dom.style.background = backgroundColor;
  716. }
  717. }
  718. each(postUpdateFuncs, function (func) {
  719. func(ecModel, api);
  720. });
  721. // console.profile && console.profileEnd('update');
  722. },
  723. /**
  724. * @param {Object} payload
  725. * @private
  726. */
  727. updateView: function (payload) {
  728. var ecModel = this._model;
  729. // update before setOption
  730. if (!ecModel) {
  731. return;
  732. }
  733. ecModel.eachSeries(function (seriesModel) {
  734. seriesModel.getData().clearAllVisual();
  735. });
  736. doVisualEncoding.call(this, ecModel, payload);
  737. invokeUpdateMethod.call(this, 'updateView', ecModel, payload);
  738. },
  739. /**
  740. * @param {Object} payload
  741. * @private
  742. */
  743. updateVisual: function (payload) {
  744. var ecModel = this._model;
  745. // update before setOption
  746. if (!ecModel) {
  747. return;
  748. }
  749. ecModel.eachSeries(function (seriesModel) {
  750. seriesModel.getData().clearAllVisual();
  751. });
  752. doVisualEncoding.call(this, ecModel, payload, true);
  753. invokeUpdateMethod.call(this, 'updateVisual', ecModel, payload);
  754. },
  755. /**
  756. * @param {Object} payload
  757. * @private
  758. */
  759. updateLayout: function (payload) {
  760. var ecModel = this._model;
  761. // update before setOption
  762. if (!ecModel) {
  763. return;
  764. }
  765. doLayout.call(this, ecModel, payload);
  766. invokeUpdateMethod.call(this, 'updateLayout', ecModel, payload);
  767. },
  768. /**
  769. * @param {Object} payload
  770. * @private
  771. */
  772. prepareAndUpdate: function (payload) {
  773. var ecModel = this._model;
  774. prepareView.call(this, 'component', ecModel);
  775. prepareView.call(this, 'chart', ecModel);
  776. updateMethods.update.call(this, payload);
  777. }
  778. };
  779. /**
  780. * @private
  781. */
  782. function updateDirectly(ecIns, method, payload, mainType, subType) {
  783. var ecModel = ecIns._model;
  784. // broadcast
  785. if (!mainType) {
  786. each(ecIns._componentsViews.concat(ecIns._chartsViews), callView);
  787. return;
  788. }
  789. var query = {};
  790. query[mainType + 'Id'] = payload[mainType + 'Id'];
  791. query[mainType + 'Index'] = payload[mainType + 'Index'];
  792. query[mainType + 'Name'] = payload[mainType + 'Name'];
  793. var condition = {mainType: mainType, query: query};
  794. subType && (condition.subType = subType); // subType may be '' by parseClassType;
  795. // If dispatchAction before setOption, do nothing.
  796. ecModel && ecModel.eachComponent(condition, function (model, index) {
  797. callView(ecIns[
  798. mainType === 'series' ? '_chartsMap' : '_componentsMap'
  799. ][model.__viewId]);
  800. }, ecIns);
  801. function callView(view) {
  802. view && view.__alive && view[method] && view[method](
  803. view.__model, ecModel, ecIns._api, payload
  804. );
  805. }
  806. }
  807. /**
  808. * Resize the chart
  809. * @param {Object} opts
  810. * @param {number} [opts.width] Can be 'auto' (the same as null/undefined)
  811. * @param {number} [opts.height] Can be 'auto' (the same as null/undefined)
  812. * @param {boolean} [opts.silent=false]
  813. */
  814. echartsProto.resize = function (opts) {
  815. if (true) {
  816. zrUtil.assert(!this[IN_MAIN_PROCESS], '`resize` should not be called during main process.');
  817. }
  818. this[IN_MAIN_PROCESS] = true;
  819. this._zr.resize(opts);
  820. var optionChanged = this._model && this._model.resetOption('media');
  821. var updateMethod = optionChanged ? 'prepareAndUpdate' : 'update';
  822. updateMethods[updateMethod].call(this);
  823. // Resize loading effect
  824. this._loadingFX && this._loadingFX.resize();
  825. this[IN_MAIN_PROCESS] = false;
  826. var silent = opts && opts.silent;
  827. flushPendingActions.call(this, silent);
  828. triggerUpdatedEvent.call(this, silent);
  829. };
  830. /**
  831. * Show loading effect
  832. * @param {string} [name='default']
  833. * @param {Object} [cfg]
  834. */
  835. echartsProto.showLoading = function (name, cfg) {
  836. if (zrUtil.isObject(name)) {
  837. cfg = name;
  838. name = '';
  839. }
  840. name = name || 'default';
  841. this.hideLoading();
  842. if (!loadingEffects[name]) {
  843. if (true) {
  844. console.warn('Loading effects ' + name + ' not exists.');
  845. }
  846. return;
  847. }
  848. var el = loadingEffects[name](this._api, cfg);
  849. var zr = this._zr;
  850. this._loadingFX = el;
  851. zr.add(el);
  852. };
  853. /**
  854. * Hide loading effect
  855. */
  856. echartsProto.hideLoading = function () {
  857. this._loadingFX && this._zr.remove(this._loadingFX);
  858. this._loadingFX = null;
  859. };
  860. /**
  861. * @param {Object} eventObj
  862. * @return {Object}
  863. */
  864. echartsProto.makeActionFromEvent = function (eventObj) {
  865. var payload = zrUtil.extend({}, eventObj);
  866. payload.type = eventActionMap[eventObj.type];
  867. return payload;
  868. };
  869. /**
  870. * @pubilc
  871. * @param {Object} payload
  872. * @param {string} [payload.type] Action type
  873. * @param {Object|boolean} [opt] If pass boolean, means opt.silent
  874. * @param {boolean} [opt.silent=false] Whether trigger events.
  875. * @param {boolean} [opt.flush=undefined]
  876. * true: Flush immediately, and then pixel in canvas can be fetched
  877. * immediately. Caution: it might affect performance.
  878. * false: Not not flush.
  879. * undefined: Auto decide whether perform flush.
  880. */
  881. echartsProto.dispatchAction = function (payload, opt) {
  882. if (!zrUtil.isObject(opt)) {
  883. opt = {silent: !!opt};
  884. }
  885. if (!actions[payload.type]) {
  886. return;
  887. }
  888. // May dispatchAction in rendering procedure
  889. if (this[IN_MAIN_PROCESS]) {
  890. this._pendingActions.push(payload);
  891. return;
  892. }
  893. doDispatchAction.call(this, payload, opt.silent);
  894. if (opt.flush) {
  895. this._zr.flush(true);
  896. }
  897. else if (opt.flush !== false && env.browser.weChat) {
  898. // In WeChat embeded browser, `requestAnimationFrame` and `setInterval`
  899. // hang when sliding page (on touch event), which cause that zr does not
  900. // refresh util user interaction finished, which is not expected.
  901. // But `dispatchAction` may be called too frequently when pan on touch
  902. // screen, which impacts performance if do not throttle them.
  903. this._throttledZrFlush();
  904. }
  905. flushPendingActions.call(this, opt.silent);
  906. triggerUpdatedEvent.call(this, opt.silent);
  907. };
  908. function doDispatchAction(payload, silent) {
  909. var payloadType = payload.type;
  910. var escapeConnect = payload.escapeConnect;
  911. var actionWrap = actions[payloadType];
  912. var actionInfo = actionWrap.actionInfo;
  913. var cptType = (actionInfo.update || 'update').split(':');
  914. var updateMethod = cptType.pop();
  915. cptType = cptType[0] != null && parseClassType(cptType[0]);
  916. this[IN_MAIN_PROCESS] = true;
  917. var payloads = [payload];
  918. var batched = false;
  919. // Batch action
  920. if (payload.batch) {
  921. batched = true;
  922. payloads = zrUtil.map(payload.batch, function (item) {
  923. item = zrUtil.defaults(zrUtil.extend({}, item), payload);
  924. item.batch = null;
  925. return item;
  926. });
  927. }
  928. var eventObjBatch = [];
  929. var eventObj;
  930. var isHighDown = payloadType === 'highlight' || payloadType === 'downplay';
  931. each(payloads, function (batchItem) {
  932. // Action can specify the event by return it.
  933. eventObj = actionWrap.action(batchItem, this._model, this._api);
  934. // Emit event outside
  935. eventObj = eventObj || zrUtil.extend({}, batchItem);
  936. // Convert type to eventType
  937. eventObj.type = actionInfo.event || eventObj.type;
  938. eventObjBatch.push(eventObj);
  939. // light update does not perform data process, layout and visual.
  940. if (isHighDown) {
  941. // method, payload, mainType, subType
  942. updateDirectly(this, updateMethod, batchItem, 'series');
  943. }
  944. else if (cptType) {
  945. updateDirectly(this, updateMethod, batchItem, cptType.main, cptType.sub);
  946. }
  947. }, this);
  948. if (updateMethod !== 'none' && !isHighDown && !cptType) {
  949. // Still dirty
  950. if (this[OPTION_UPDATED]) {
  951. // FIXME Pass payload ?
  952. updateMethods.prepareAndUpdate.call(this, payload);
  953. this[OPTION_UPDATED] = false;
  954. }
  955. else {
  956. updateMethods[updateMethod].call(this, payload);
  957. }
  958. }
  959. // Follow the rule of action batch
  960. if (batched) {
  961. eventObj = {
  962. type: actionInfo.event || payloadType,
  963. escapeConnect: escapeConnect,
  964. batch: eventObjBatch
  965. };
  966. }
  967. else {
  968. eventObj = eventObjBatch[0];
  969. }
  970. this[IN_MAIN_PROCESS] = false;
  971. !silent && this._messageCenter.trigger(eventObj.type, eventObj);
  972. }
  973. function flushPendingActions(silent) {
  974. var pendingActions = this._pendingActions;
  975. while (pendingActions.length) {
  976. var payload = pendingActions.shift();
  977. doDispatchAction.call(this, payload, silent);
  978. }
  979. }
  980. function triggerUpdatedEvent(silent) {
  981. !silent && this.trigger('updated');
  982. }
  983. /**
  984. * Register event
  985. * @method
  986. */
  987. echartsProto.on = createRegisterEventWithLowercaseName('on');
  988. echartsProto.off = createRegisterEventWithLowercaseName('off');
  989. echartsProto.one = createRegisterEventWithLowercaseName('one');
  990. /**
  991. * @param {string} methodName
  992. * @private
  993. */
  994. function invokeUpdateMethod(methodName, ecModel, payload) {
  995. var api = this._api;
  996. // Update all components
  997. each(this._componentsViews, function (component) {
  998. var componentModel = component.__model;
  999. component[methodName](componentModel, ecModel, api, payload);
  1000. updateZ(componentModel, component);
  1001. }, this);
  1002. // Upate all charts
  1003. ecModel.eachSeries(function (seriesModel, idx) {
  1004. var chart = this._chartsMap[seriesModel.__viewId];
  1005. chart[methodName](seriesModel, ecModel, api, payload);
  1006. updateZ(seriesModel, chart);
  1007. updateProgressiveAndBlend(seriesModel, chart);
  1008. }, this);
  1009. // If use hover layer
  1010. updateHoverLayerStatus(this._zr, ecModel);
  1011. // Post render
  1012. each(postUpdateFuncs, function (func) {
  1013. func(ecModel, api);
  1014. });
  1015. }
  1016. /**
  1017. * Prepare view instances of charts and components
  1018. * @param {module:echarts/model/Global} ecModel
  1019. * @private
  1020. */
  1021. function prepareView(type, ecModel) {
  1022. var isComponent = type === 'component';
  1023. var viewList = isComponent ? this._componentsViews : this._chartsViews;
  1024. var viewMap = isComponent ? this._componentsMap : this._chartsMap;
  1025. var zr = this._zr;
  1026. for (var i = 0; i < viewList.length; i++) {
  1027. viewList[i].__alive = false;
  1028. }
  1029. ecModel[isComponent ? 'eachComponent' : 'eachSeries'](function (componentType, model) {
  1030. if (isComponent) {
  1031. if (componentType === 'series') {
  1032. return;
  1033. }
  1034. }
  1035. else {
  1036. model = componentType;
  1037. }
  1038. // Consider: id same and type changed.
  1039. var viewId = '_ec_' + model.id + '_' + model.type;
  1040. var view = viewMap[viewId];
  1041. if (!view) {
  1042. var classType = parseClassType(model.type);
  1043. var Clazz = isComponent
  1044. ? ComponentView.getClass(classType.main, classType.sub)
  1045. : ChartView.getClass(classType.sub);
  1046. if (Clazz) {
  1047. view = new Clazz();
  1048. view.init(ecModel, this._api);
  1049. viewMap[viewId] = view;
  1050. viewList.push(view);
  1051. zr.add(view.group);
  1052. }
  1053. else {
  1054. // Error
  1055. return;
  1056. }
  1057. }
  1058. model.__viewId = view.__id = viewId;
  1059. view.__alive = true;
  1060. view.__model = model;
  1061. view.group.__ecComponentInfo = {
  1062. mainType: model.mainType,
  1063. index: model.componentIndex
  1064. };
  1065. }, this);
  1066. for (var i = 0; i < viewList.length;) {
  1067. var view = viewList[i];
  1068. if (!view.__alive) {
  1069. zr.remove(view.group);
  1070. view.dispose(ecModel, this._api);
  1071. viewList.splice(i, 1);
  1072. delete viewMap[view.__id];
  1073. view.__id = view.group.__ecComponentInfo = null;
  1074. }
  1075. else {
  1076. i++;
  1077. }
  1078. }
  1079. }
  1080. /**
  1081. * Processor data in each series
  1082. *
  1083. * @param {module:echarts/model/Global} ecModel
  1084. * @private
  1085. */
  1086. function processData(ecModel, api) {
  1087. each(dataProcessorFuncs, function (process) {
  1088. process.func(ecModel, api);
  1089. });
  1090. }
  1091. /**
  1092. * @private
  1093. */
  1094. function stackSeriesData(ecModel) {
  1095. var stackedDataMap = {};
  1096. ecModel.eachSeries(function (series) {
  1097. var stack = series.get('stack');
  1098. var data = series.getData();
  1099. if (stack && data.type === 'list') {
  1100. var previousStack = stackedDataMap[stack];
  1101. // Avoid conflict with Object.prototype
  1102. if (stackedDataMap.hasOwnProperty(stack) && previousStack) {
  1103. data.stackedOn = previousStack;
  1104. }
  1105. stackedDataMap[stack] = data;
  1106. }
  1107. });
  1108. }
  1109. /**
  1110. * Layout before each chart render there series, special visual encoding stage
  1111. *
  1112. * @param {module:echarts/model/Global} ecModel
  1113. * @private
  1114. */
  1115. function doLayout(ecModel, payload) {
  1116. var api = this._api;
  1117. each(visualFuncs, function (visual) {
  1118. if (visual.isLayout) {
  1119. visual.func(ecModel, api, payload);
  1120. }
  1121. });
  1122. }
  1123. /**
  1124. * Encode visual infomation from data after data processing
  1125. *
  1126. * @param {module:echarts/model/Global} ecModel
  1127. * @param {object} layout
  1128. * @param {boolean} [excludesLayout]
  1129. * @private
  1130. */
  1131. function doVisualEncoding(ecModel, payload, excludesLayout) {
  1132. var api = this._api;
  1133. ecModel.clearColorPalette();
  1134. ecModel.eachSeries(function (seriesModel) {
  1135. seriesModel.clearColorPalette();
  1136. });
  1137. each(visualFuncs, function (visual) {
  1138. (!excludesLayout || !visual.isLayout)
  1139. && visual.func(ecModel, api, payload);
  1140. });
  1141. }
  1142. /**
  1143. * Render each chart and component
  1144. * @private
  1145. */
  1146. function doRender(ecModel, payload) {
  1147. var api = this._api;
  1148. // Render all components
  1149. each(this._componentsViews, function (componentView) {
  1150. var componentModel = componentView.__model;
  1151. componentView.render(componentModel, ecModel, api, payload);
  1152. updateZ(componentModel, componentView);
  1153. }, this);
  1154. each(this._chartsViews, function (chart) {
  1155. chart.__alive = false;
  1156. }, this);
  1157. // Render all charts
  1158. ecModel.eachSeries(function (seriesModel, idx) {
  1159. var chartView = this._chartsMap[seriesModel.__viewId];
  1160. chartView.__alive = true;
  1161. chartView.render(seriesModel, ecModel, api, payload);
  1162. chartView.group.silent = !!seriesModel.get('silent');
  1163. updateZ(seriesModel, chartView);
  1164. updateProgressiveAndBlend(seriesModel, chartView);
  1165. }, this);
  1166. // If use hover layer
  1167. updateHoverLayerStatus(this._zr, ecModel);
  1168. // Remove groups of unrendered charts
  1169. each(this._chartsViews, function (chart) {
  1170. if (!chart.__alive) {
  1171. chart.remove(ecModel, api);
  1172. }
  1173. }, this);
  1174. }
  1175. var MOUSE_EVENT_NAMES = [
  1176. 'click', 'dblclick', 'mouseover', 'mouseout', 'mousemove',
  1177. 'mousedown', 'mouseup', 'globalout', 'contextmenu'
  1178. ];
  1179. /**
  1180. * @private
  1181. */
  1182. echartsProto._initEvents = function () {
  1183. each(MOUSE_EVENT_NAMES, function (eveName) {
  1184. this._zr.on(eveName, function (e) {
  1185. var ecModel = this.getModel();
  1186. var el = e.target;
  1187. var params;
  1188. // no e.target when 'globalout'.
  1189. if (eveName === 'globalout') {
  1190. params = {};
  1191. }
  1192. else if (el && el.dataIndex != null) {
  1193. var dataModel = el.dataModel || ecModel.getSeriesByIndex(el.seriesIndex);
  1194. params = dataModel && dataModel.getDataParams(el.dataIndex, el.dataType) || {};
  1195. }
  1196. // If element has custom eventData of components
  1197. else if (el && el.eventData) {
  1198. params = zrUtil.extend({}, el.eventData);
  1199. }
  1200. if (params) {
  1201. params.event = e;
  1202. params.type = eveName;
  1203. this.trigger(eveName, params);
  1204. }
  1205. }, this);
  1206. }, this);
  1207. each(eventActionMap, function (actionType, eventType) {
  1208. this._messageCenter.on(eventType, function (event) {
  1209. this.trigger(eventType, event);
  1210. }, this);
  1211. }, this);
  1212. };
  1213. /**
  1214. * @return {boolean}
  1215. */
  1216. echartsProto.isDisposed = function () {
  1217. return this._disposed;
  1218. };
  1219. /**
  1220. * Clear
  1221. */
  1222. echartsProto.clear = function () {
  1223. this.setOption({ series: [] }, true);
  1224. };
  1225. /**
  1226. * Dispose instance
  1227. */
  1228. echartsProto.dispose = function () {
  1229. if (this._disposed) {
  1230. if (true) {
  1231. console.warn('Instance ' + this.id + ' has been disposed');
  1232. }
  1233. return;
  1234. }
  1235. this._disposed = true;
  1236. var api = this._api;
  1237. var ecModel = this._model;
  1238. each(this._componentsViews, function (component) {
  1239. component.dispose(ecModel, api);
  1240. });
  1241. each(this._chartsViews, function (chart) {
  1242. chart.dispose(ecModel, api);
  1243. });
  1244. // Dispose after all views disposed
  1245. this._zr.dispose();
  1246. delete instances[this.id];
  1247. };
  1248. zrUtil.mixin(ECharts, Eventful);
  1249. function updateHoverLayerStatus(zr, ecModel) {
  1250. var storage = zr.storage;
  1251. var elCount = 0;
  1252. storage.traverse(function (el) {
  1253. if (!el.isGroup) {
  1254. elCount++;
  1255. }
  1256. });
  1257. if (elCount > ecModel.get('hoverLayerThreshold') && !env.node) {
  1258. storage.traverse(function (el) {
  1259. if (!el.isGroup) {
  1260. el.useHoverLayer = true;
  1261. }
  1262. });
  1263. }
  1264. }
  1265. /**
  1266. * Update chart progressive and blend.
  1267. * @param {module:echarts/model/Series|module:echarts/model/Component} model
  1268. * @param {module:echarts/view/Component|module:echarts/view/Chart} view
  1269. */
  1270. function updateProgressiveAndBlend(seriesModel, chartView) {
  1271. // Progressive configuration
  1272. var elCount = 0;
  1273. chartView.group.traverse(function (el) {
  1274. if (el.type !== 'group' && !el.ignore) {
  1275. elCount++;
  1276. }
  1277. });
  1278. var frameDrawNum = +seriesModel.get('progressive');
  1279. var needProgressive = elCount > seriesModel.get('progressiveThreshold') && frameDrawNum && !env.node;
  1280. if (needProgressive) {
  1281. chartView.group.traverse(function (el) {
  1282. // FIXME marker and other components
  1283. if (!el.isGroup) {
  1284. el.progressive = needProgressive ?
  1285. Math.floor(elCount++ / frameDrawNum) : -1;
  1286. if (needProgressive) {
  1287. el.stopAnimation(true);
  1288. }
  1289. }
  1290. });
  1291. }
  1292. // Blend configration
  1293. var blendMode = seriesModel.get('blendMode') || null;
  1294. if (true) {
  1295. if (!env.canvasSupported && blendMode && blendMode !== 'source-over') {
  1296. console.warn('Only canvas support blendMode');
  1297. }
  1298. }
  1299. chartView.group.traverse(function (el) {
  1300. // FIXME marker and other components
  1301. if (!el.isGroup) {
  1302. el.setStyle('blend', blendMode);
  1303. }
  1304. });
  1305. }
  1306. /**
  1307. * @param {module:echarts/model/Series|module:echarts/model/Component} model
  1308. * @param {module:echarts/view/Component|module:echarts/view/Chart} view
  1309. */
  1310. function updateZ(model, view) {
  1311. var z = model.get('z');
  1312. var zlevel = model.get('zlevel');
  1313. // Set z and zlevel
  1314. view.group.traverse(function (el) {
  1315. if (el.type !== 'group') {
  1316. z != null && (el.z = z);
  1317. zlevel != null && (el.zlevel = zlevel);
  1318. }
  1319. });
  1320. }
  1321. function createExtensionAPI(ecInstance) {
  1322. var coordSysMgr = ecInstance._coordSysMgr;
  1323. return zrUtil.extend(new ExtensionAPI(ecInstance), {
  1324. // Inject methods
  1325. getCoordinateSystems: zrUtil.bind(
  1326. coordSysMgr.getCoordinateSystems, coordSysMgr
  1327. ),
  1328. getComponentByElement: function (el) {
  1329. while (el) {
  1330. var modelInfo = el.__ecComponentInfo;
  1331. if (modelInfo != null) {
  1332. return ecInstance._model.getComponent(modelInfo.mainType, modelInfo.index);
  1333. }
  1334. el = el.parent;
  1335. }
  1336. }
  1337. });
  1338. }
  1339. /**
  1340. * @type {Object} key: actionType.
  1341. * @inner
  1342. */
  1343. var actions = {};
  1344. /**
  1345. * Map eventType to actionType
  1346. * @type {Object}
  1347. */
  1348. var eventActionMap = {};
  1349. /**
  1350. * Data processor functions of each stage
  1351. * @type {Array.<Object.<string, Function>>}
  1352. * @inner
  1353. */
  1354. var dataProcessorFuncs = [];
  1355. /**
  1356. * @type {Array.<Function>}
  1357. * @inner
  1358. */
  1359. var optionPreprocessorFuncs = [];
  1360. /**
  1361. * @type {Array.<Function>}
  1362. * @inner
  1363. */
  1364. var postUpdateFuncs = [];
  1365. /**
  1366. * Visual encoding functions of each stage
  1367. * @type {Array.<Object.<string, Function>>}
  1368. * @inner
  1369. */
  1370. var visualFuncs = [];
  1371. /**
  1372. * Theme storage
  1373. * @type {Object.<key, Object>}
  1374. */
  1375. var themeStorage = {};
  1376. /**
  1377. * Loading effects
  1378. */
  1379. var loadingEffects = {};
  1380. var instances = {};
  1381. var connectedGroups = {};
  1382. var idBase = new Date() - 0;
  1383. var groupIdBase = new Date() - 0;
  1384. var DOM_ATTRIBUTE_KEY = '_echarts_instance_';
  1385. /**
  1386. * @alias module:echarts
  1387. */
  1388. var echarts = {
  1389. /**
  1390. * @type {number}
  1391. */
  1392. version: '3.6.0',
  1393. dependencies: {
  1394. zrender: '3.5.0'
  1395. }
  1396. };
  1397. function enableConnect(chart) {
  1398. var STATUS_PENDING = 0;
  1399. var STATUS_UPDATING = 1;
  1400. var STATUS_UPDATED = 2;
  1401. var STATUS_KEY = '__connectUpdateStatus';
  1402. function updateConnectedChartsStatus(charts, status) {
  1403. for (var i = 0; i < charts.length; i++) {
  1404. var otherChart = charts[i];
  1405. otherChart[STATUS_KEY] = status;
  1406. }
  1407. }
  1408. zrUtil.each(eventActionMap, function (actionType, eventType) {
  1409. chart._messageCenter.on(eventType, function (event) {
  1410. if (connectedGroups[chart.group] && chart[STATUS_KEY] !== STATUS_PENDING) {
  1411. if (event && event.escapeConnect) {
  1412. return;
  1413. }
  1414. var action = chart.makeActionFromEvent(event);
  1415. var otherCharts = [];
  1416. zrUtil.each(instances, function (otherChart) {
  1417. if (otherChart !== chart && otherChart.group === chart.group) {
  1418. otherCharts.push(otherChart);
  1419. }
  1420. });
  1421. updateConnectedChartsStatus(otherCharts, STATUS_PENDING);
  1422. each(otherCharts, function (otherChart) {
  1423. if (otherChart[STATUS_KEY] !== STATUS_UPDATING) {
  1424. otherChart.dispatchAction(action);
  1425. }
  1426. });
  1427. updateConnectedChartsStatus(otherCharts, STATUS_UPDATED);
  1428. }
  1429. });
  1430. });
  1431. }
  1432. /**
  1433. * @param {HTMLDomElement} dom
  1434. * @param {Object} [theme]
  1435. * @param {Object} opts
  1436. * @param {number} [opts.devicePixelRatio] Use window.devicePixelRatio by default
  1437. * @param {string} [opts.renderer] Currently only 'canvas' is supported.
  1438. * @param {number} [opts.width] Use clientWidth of the input `dom` by default.
  1439. * Can be 'auto' (the same as null/undefined)
  1440. * @param {number} [opts.height] Use clientHeight of the input `dom` by default.
  1441. * Can be 'auto' (the same as null/undefined)
  1442. */
  1443. echarts.init = function (dom, theme, opts) {
  1444. if (true) {
  1445. // Check version
  1446. if ((zrender.version.replace('.', '') - 0) < (echarts.dependencies.zrender.replace('.', '') - 0)) {
  1447. throw new Error(
  1448. 'ZRender ' + zrender.version
  1449. + ' is too old for ECharts ' + echarts.version
  1450. + '. Current version need ZRender '
  1451. + echarts.dependencies.zrender + '+'
  1452. );
  1453. }
  1454. if (!dom) {
  1455. throw new Error('Initialize failed: invalid dom.');
  1456. }
  1457. }
  1458. var existInstance = echarts.getInstanceByDom(dom);
  1459. if (existInstance) {
  1460. if (true) {
  1461. console.warn('There is a chart instance already initialized on the dom.');
  1462. }
  1463. return existInstance;
  1464. }
  1465. if (true) {
  1466. if (zrUtil.isDom(dom)
  1467. && dom.nodeName.toUpperCase() !== 'CANVAS'
  1468. && (
  1469. (!dom.clientWidth && (!opts || opts.width == null))
  1470. || (!dom.clientHeight && (!opts || opts.height == null))
  1471. )
  1472. ) {
  1473. console.warn('Can\'t get dom width or height');
  1474. }
  1475. }
  1476. var chart = new ECharts(dom, theme, opts);
  1477. chart.id = 'ec_' + idBase++;
  1478. instances[chart.id] = chart;
  1479. if (dom.setAttribute) {
  1480. dom.setAttribute(DOM_ATTRIBUTE_KEY, chart.id);
  1481. }
  1482. else {
  1483. dom[DOM_ATTRIBUTE_KEY] = chart.id;
  1484. }
  1485. enableConnect(chart);
  1486. return chart;
  1487. };
  1488. /**
  1489. * @return {string|Array.<module:echarts~ECharts>} groupId
  1490. */
  1491. echarts.connect = function (groupId) {
  1492. // Is array of charts
  1493. if (zrUtil.isArray(groupId)) {
  1494. var charts = groupId;
  1495. groupId = null;
  1496. // If any chart has group
  1497. zrUtil.each(charts, function (chart) {
  1498. if (chart.group != null) {
  1499. groupId = chart.group;
  1500. }
  1501. });
  1502. groupId = groupId || ('g_' + groupIdBase++);
  1503. zrUtil.each(charts, function (chart) {
  1504. chart.group = groupId;
  1505. });
  1506. }
  1507. connectedGroups[groupId] = true;
  1508. return groupId;
  1509. };
  1510. /**
  1511. * @DEPRECATED
  1512. * @return {string} groupId
  1513. */
  1514. echarts.disConnect = function (groupId) {
  1515. connectedGroups[groupId] = false;
  1516. };
  1517. /**
  1518. * @return {string} groupId
  1519. */
  1520. echarts.disconnect = echarts.disConnect;
  1521. /**
  1522. * Dispose a chart instance
  1523. * @param {module:echarts~ECharts|HTMLDomElement|string} chart
  1524. */
  1525. echarts.dispose = function (chart) {
  1526. if (typeof chart === 'string') {
  1527. chart = instances[chart];
  1528. }
  1529. else if (!(chart instanceof ECharts)){
  1530. // Try to treat as dom
  1531. chart = echarts.getInstanceByDom(chart);
  1532. }
  1533. if ((chart instanceof ECharts) && !chart.isDisposed()) {
  1534. chart.dispose();
  1535. }
  1536. };
  1537. /**
  1538. * @param {HTMLDomElement} dom
  1539. * @return {echarts~ECharts}
  1540. */
  1541. echarts.getInstanceByDom = function (dom) {
  1542. var key;
  1543. if (dom.getAttribute) {
  1544. key = dom.getAttribute(DOM_ATTRIBUTE_KEY);
  1545. }
  1546. else {
  1547. key = dom[DOM_ATTRIBUTE_KEY];
  1548. }
  1549. return instances[key];
  1550. };
  1551. /**
  1552. * @param {string} key
  1553. * @return {echarts~ECharts}
  1554. */
  1555. echarts.getInstanceById = function (key) {
  1556. return instances[key];
  1557. };
  1558. /**
  1559. * Register theme
  1560. */
  1561. echarts.registerTheme = function (name, theme) {
  1562. themeStorage[name] = theme;
  1563. };
  1564. /**
  1565. * Register option preprocessor
  1566. * @param {Function} preprocessorFunc
  1567. */
  1568. echarts.registerPreprocessor = function (preprocessorFunc) {
  1569. optionPreprocessorFuncs.push(preprocessorFunc);
  1570. };
  1571. /**
  1572. * @param {number} [priority=1000]
  1573. * @param {Function} processorFunc
  1574. */
  1575. echarts.registerProcessor = function (priority, processorFunc) {
  1576. if (typeof priority === 'function') {
  1577. processorFunc = priority;
  1578. priority = PRIORITY_PROCESSOR_FILTER;
  1579. }
  1580. if (true) {
  1581. if (isNaN(priority)) {
  1582. throw new Error('Unkown processor priority');
  1583. }
  1584. }
  1585. dataProcessorFuncs.push({
  1586. prio: priority,
  1587. func: processorFunc
  1588. });
  1589. };
  1590. /**
  1591. * Register postUpdater
  1592. * @param {Function} postUpdateFunc
  1593. */
  1594. echarts.registerPostUpdate = function (postUpdateFunc) {
  1595. postUpdateFuncs.push(postUpdateFunc);
  1596. };
  1597. /**
  1598. * Usage:
  1599. * registerAction('someAction', 'someEvent', function () { ... });
  1600. * registerAction('someAction', function () { ... });
  1601. * registerAction(
  1602. * {type: 'someAction', event: 'someEvent', update: 'updateView'},
  1603. * function () { ... }
  1604. * );
  1605. *
  1606. * @param {(string|Object)} actionInfo
  1607. * @param {string} actionInfo.type
  1608. * @param {string} [actionInfo.event]
  1609. * @param {string} [actionInfo.update]
  1610. * @param {string} [eventName]
  1611. * @param {Function} action
  1612. */
  1613. echarts.registerAction = function (actionInfo, eventName, action) {
  1614. if (typeof eventName === 'function') {
  1615. action = eventName;
  1616. eventName = '';
  1617. }
  1618. var actionType = zrUtil.isObject(actionInfo)
  1619. ? actionInfo.type
  1620. : ([actionInfo, actionInfo = {
  1621. event: eventName
  1622. }][0]);
  1623. // Event name is all lowercase
  1624. actionInfo.event = (actionInfo.event || actionType).toLowerCase();
  1625. eventName = actionInfo.event;
  1626. // Validate action type and event name.
  1627. zrUtil.assert(ACTION_REG.test(actionType) && ACTION_REG.test(eventName));
  1628. if (!actions[actionType]) {
  1629. actions[actionType] = {action: action, actionInfo: actionInfo};
  1630. }
  1631. eventActionMap[eventName] = actionType;
  1632. };
  1633. /**
  1634. * @param {string} type
  1635. * @param {*} CoordinateSystem
  1636. */
  1637. echarts.registerCoordinateSystem = function (type, CoordinateSystem) {
  1638. CoordinateSystemManager.register(type, CoordinateSystem);
  1639. };
  1640. /**
  1641. * Layout is a special stage of visual encoding
  1642. * Most visual encoding like color are common for different chart
  1643. * But each chart has it's own layout algorithm
  1644. *
  1645. * @param {number} [priority=1000]
  1646. * @param {Function} layoutFunc
  1647. */
  1648. echarts.registerLayout = function (priority, layoutFunc) {
  1649. if (typeof priority === 'function') {
  1650. layoutFunc = priority;
  1651. priority = PRIORITY_VISUAL_LAYOUT;
  1652. }
  1653. if (true) {
  1654. if (isNaN(priority)) {
  1655. throw new Error('Unkown layout priority');
  1656. }
  1657. }
  1658. visualFuncs.push({
  1659. prio: priority,
  1660. func: layoutFunc,
  1661. isLayout: true
  1662. });
  1663. };
  1664. /**
  1665. * @param {number} [priority=3000]
  1666. * @param {Function} visualFunc
  1667. */
  1668. echarts.registerVisual = function (priority, visualFunc) {
  1669. if (typeof priority === 'function') {
  1670. visualFunc = priority;
  1671. priority = PRIORITY_VISUAL_CHART;
  1672. }
  1673. if (true) {
  1674. if (isNaN(priority)) {
  1675. throw new Error('Unkown visual priority');
  1676. }
  1677. }
  1678. visualFuncs.push({
  1679. prio: priority,
  1680. func: visualFunc
  1681. });
  1682. };
  1683. /**
  1684. * @param {string} name
  1685. */
  1686. echarts.registerLoading = function (name, loadingFx) {
  1687. loadingEffects[name] = loadingFx;
  1688. };
  1689. /**
  1690. * @param {Object} opts
  1691. * @param {string} [superClass]
  1692. */
  1693. echarts.extendComponentModel = function (opts/*, superClass*/) {
  1694. // var Clazz = ComponentModel;
  1695. // if (superClass) {
  1696. // var classType = parseClassType(superClass);
  1697. // Clazz = ComponentModel.getClass(classType.main, classType.sub, true);
  1698. // }
  1699. return ComponentModel.extend(opts);
  1700. };
  1701. /**
  1702. * @param {Object} opts
  1703. * @param {string} [superClass]
  1704. */
  1705. echarts.extendComponentView = function (opts/*, superClass*/) {
  1706. // var Clazz = ComponentView;
  1707. // if (superClass) {
  1708. // var classType = parseClassType(superClass);
  1709. // Clazz = ComponentView.getClass(classType.main, classType.sub, true);
  1710. // }
  1711. return ComponentView.extend(opts);
  1712. };
  1713. /**
  1714. * @param {Object} opts
  1715. * @param {string} [superClass]
  1716. */
  1717. echarts.extendSeriesModel = function (opts/*, superClass*/) {
  1718. // var Clazz = SeriesModel;
  1719. // if (superClass) {
  1720. // superClass = 'series.' + superClass.replace('series.', '');
  1721. // var classType = parseClassType(superClass);
  1722. // Clazz = ComponentModel.getClass(classType.main, classType.sub, true);
  1723. // }
  1724. return SeriesModel.extend(opts);
  1725. };
  1726. /**
  1727. * @param {Object} opts
  1728. * @param {string} [superClass]
  1729. */
  1730. echarts.extendChartView = function (opts/*, superClass*/) {
  1731. // var Clazz = ChartView;
  1732. // if (superClass) {
  1733. // superClass = superClass.replace('series.', '');
  1734. // var classType = parseClassType(superClass);
  1735. // Clazz = ChartView.getClass(classType.main, true);
  1736. // }
  1737. return ChartView.extend(opts);
  1738. };
  1739. /**
  1740. * ZRender need a canvas context to do measureText.
  1741. * But in node environment canvas may be created by node-canvas.
  1742. * So we need to specify how to create a canvas instead of using document.createElement('canvas')
  1743. *
  1744. * Be careful of using it in the browser.
  1745. *
  1746. * @param {Function} creator
  1747. * @example
  1748. * var Canvas = require('canvas');
  1749. * var echarts = require('echarts');
  1750. * echarts.setCanvasCreator(function () {
  1751. * // Small size is enough.
  1752. * return new Canvas(32, 32);
  1753. * });
  1754. */
  1755. echarts.setCanvasCreator = function (creator) {
  1756. zrUtil.createCanvas = creator;
  1757. };
  1758. echarts.registerVisual(PRIORITY_VISUAL_GLOBAL, __webpack_require__(94));
  1759. echarts.registerPreprocessor(__webpack_require__(95));
  1760. echarts.registerLoading('default', __webpack_require__(97));
  1761. // Default action
  1762. echarts.registerAction({
  1763. type: 'highlight',
  1764. event: 'highlight',
  1765. update: 'highlight'
  1766. }, zrUtil.noop);
  1767. echarts.registerAction({
  1768. type: 'downplay',
  1769. event: 'downplay',
  1770. update: 'downplay'
  1771. }, zrUtil.noop);
  1772. // --------
  1773. // Exports
  1774. // --------
  1775. echarts.zrender = zrender;
  1776. echarts.List = __webpack_require__(98);
  1777. echarts.Model = __webpack_require__(12);
  1778. echarts.Axis = __webpack_require__(100);
  1779. echarts.graphic = __webpack_require__(18);
  1780. echarts.number = __webpack_require__(7);
  1781. echarts.format = __webpack_require__(6);
  1782. echarts.throttle = throttle.throttle;
  1783. echarts.matrix = __webpack_require__(11);
  1784. echarts.vector = __webpack_require__(10);
  1785. echarts.color = __webpack_require__(31);
  1786. echarts.util = {};
  1787. each([
  1788. 'map', 'each', 'filter', 'indexOf', 'inherits', 'reduce', 'filter',
  1789. 'bind', 'curry', 'isArray', 'isString', 'isObject', 'isFunction',
  1790. 'extend', 'defaults', 'clone', 'merge'
  1791. ],
  1792. function (name) {
  1793. echarts.util[name] = zrUtil[name];
  1794. }
  1795. );
  1796. echarts.helper = __webpack_require__(108);
  1797. // PRIORITY
  1798. echarts.PRIORITY = {
  1799. PROCESSOR: {
  1800. FILTER: PRIORITY_PROCESSOR_FILTER,
  1801. STATISTIC: PRIORITY_PROCESSOR_STATISTIC
  1802. },
  1803. VISUAL: {
  1804. LAYOUT: PRIORITY_VISUAL_LAYOUT,
  1805. GLOBAL: PRIORITY_VISUAL_GLOBAL,
  1806. CHART: PRIORITY_VISUAL_CHART,
  1807. COMPONENT: PRIORITY_VISUAL_COMPONENT,
  1808. BRUSH: PRIORITY_VISUAL_BRUSH
  1809. }
  1810. };
  1811. module.exports = echarts;
  1812. /***/ },
  1813. /* 2 */
  1814. /***/ function(module, exports) {
  1815. /**
  1816. * echarts设备环境识别
  1817. *
  1818. * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。
  1819. * @author firede[firede@firede.us]
  1820. * @desc thanks zepto.
  1821. */
  1822. var env = {};
  1823. if (typeof navigator === 'undefined') {
  1824. // In node
  1825. env = {
  1826. browser: {},
  1827. os: {},
  1828. node: true,
  1829. // Assume canvas is supported
  1830. canvasSupported: true
  1831. };
  1832. }
  1833. else {
  1834. env = detect(navigator.userAgent);
  1835. }
  1836. module.exports = env;
  1837. // Zepto.js
  1838. // (c) 2010-2013 Thomas Fuchs
  1839. // Zepto.js may be freely distributed under the MIT license.
  1840. function detect(ua) {
  1841. var os = {};
  1842. var browser = {};
  1843. // var webkit = ua.match(/Web[kK]it[\/]{0,1}([\d.]+)/);
  1844. // var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/);
  1845. // var ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
  1846. // var ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
  1847. // var iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/);
  1848. // var webos = ua.match(/(webOS|hpwOS)[\s\/]([\d.]+)/);
  1849. // var touchpad = webos && ua.match(/TouchPad/);
  1850. // var kindle = ua.match(/Kindle\/([\d.]+)/);
  1851. // var silk = ua.match(/Silk\/([\d._]+)/);
  1852. // var blackberry = ua.match(/(BlackBerry).*Version\/([\d.]+)/);
  1853. // var bb10 = ua.match(/(BB10).*Version\/([\d.]+)/);
  1854. // var rimtabletos = ua.match(/(RIM\sTablet\sOS)\s([\d.]+)/);
  1855. // var playbook = ua.match(/PlayBook/);
  1856. // var chrome = ua.match(/Chrome\/([\d.]+)/) || ua.match(/CriOS\/([\d.]+)/);
  1857. var firefox = ua.match(/Firefox\/([\d.]+)/);
  1858. // var safari = webkit && ua.match(/Mobile\//) && !chrome;
  1859. // var webview = ua.match(/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/) && !chrome;
  1860. var ie = ua.match(/MSIE\s([\d.]+)/)
  1861. // IE 11 Trident/7.0; rv:11.0
  1862. || ua.match(/Trident\/.+?rv:(([\d.]+))/);
  1863. var edge = ua.match(/Edge\/([\d.]+)/); // IE 12 and 12+
  1864. var weChat = (/micromessenger/i).test(ua);
  1865. // Todo: clean this up with a better OS/browser seperation:
  1866. // - discern (more) between multiple browsers on android
  1867. // - decide if kindle fire in silk mode is android or not
  1868. // - Firefox on Android doesn't specify the Android version
  1869. // - possibly devide in os, device and browser hashes
  1870. // if (browser.webkit = !!webkit) browser.version = webkit[1];
  1871. // if (android) os.android = true, os.version = android[2];
  1872. // if (iphone && !ipod) os.ios = os.iphone = true, os.version = iphone[2].replace(/_/g, '.');
  1873. // if (ipad) os.ios = os.ipad = true, os.version = ipad[2].replace(/_/g, '.');
  1874. // if (ipod) os.ios = os.ipod = true, os.version = ipod[3] ? ipod[3].replace(/_/g, '.') : null;
  1875. // if (webos) os.webos = true, os.version = webos[2];
  1876. // if (touchpad) os.touchpad = true;
  1877. // if (blackberry) os.blackberry = true, os.version = blackberry[2];
  1878. // if (bb10) os.bb10 = true, os.version = bb10[2];
  1879. // if (rimtabletos) os.rimtabletos = true, os.version = rimtabletos[2];
  1880. // if (playbook) browser.playbook = true;
  1881. // if (kindle) os.kindle = true, os.version = kindle[1];
  1882. // if (silk) browser.silk = true, browser.version = silk[1];
  1883. // if (!silk && os.android && ua.match(/Kindle Fire/)) browser.silk = true;
  1884. // if (chrome) browser.chrome = true, browser.version = chrome[1];
  1885. if (firefox) {
  1886. browser.firefox = true;
  1887. browser.version = firefox[1];
  1888. }
  1889. // if (safari && (ua.match(/Safari/) || !!os.ios)) browser.safari = true;
  1890. // if (webview) browser.webview = true;
  1891. if (ie) {
  1892. browser.ie = true;
  1893. browser.version = ie[1];
  1894. }
  1895. if (edge) {
  1896. browser.edge = true;
  1897. browser.version = edge[1];
  1898. }
  1899. // It is difficult to detect WeChat in Win Phone precisely, because ua can
  1900. // not be set on win phone. So we do not consider Win Phone.
  1901. if (weChat) {
  1902. browser.weChat = true;
  1903. }
  1904. // os.tablet = !!(ipad || playbook || (android && !ua.match(/Mobile/)) ||
  1905. // (firefox && ua.match(/Tablet/)) || (ie && !ua.match(/Phone/) && ua.match(/Touch/)));
  1906. // os.phone = !!(!os.tablet && !os.ipod && (android || iphone || webos ||
  1907. // (chrome && ua.match(/Android/)) || (chrome && ua.match(/CriOS\/([\d.]+)/)) ||
  1908. // (firefox && ua.match(/Mobile/)) || (ie && ua.match(/Touch/))));
  1909. return {
  1910. browser: browser,
  1911. os: os,
  1912. node: false,
  1913. // 原生canvas支持,改极端点了
  1914. // canvasSupported : !(browser.ie && parseFloat(browser.version) < 9)
  1915. canvasSupported : document.createElement('canvas').getContext ? true : false,
  1916. // @see <http://stackoverflow.com/questions/4817029/whats-the-best-way-to-detect-a-touch-screen-device-using-javascript>
  1917. // works on most browsers
  1918. // IE10/11 does not support touch event, and MS Edge supports them but not by
  1919. // default, so we dont check navigator.maxTouchPoints for them here.
  1920. touchEventsSupported: 'ontouchstart' in window && !browser.ie && !browser.edge,
  1921. // <http://caniuse.com/#search=pointer%20event>.
  1922. pointerEventsSupported: 'onpointerdown' in window
  1923. // Firefox supports pointer but not by default, only MS browsers are reliable on pointer
  1924. // events currently. So we dont use that on other browsers unless tested sufficiently.
  1925. // Although IE 10 supports pointer event, it use old style and is different from the
  1926. // standard. So we exclude that. (IE 10 is hardly used on touch device)
  1927. && (browser.edge || (browser.ie && browser.version >= 11))
  1928. };
  1929. }
  1930. /***/ },
  1931. /* 3 */
  1932. /***/ function(module, exports, __webpack_require__) {
  1933. /**
  1934. * ECharts global model
  1935. *
  1936. * @module {echarts/model/Global}
  1937. */
  1938. /**
  1939. * Caution: If the mechanism should be changed some day, these cases
  1940. * should be considered:
  1941. *
  1942. * (1) In `merge option` mode, if using the same option to call `setOption`
  1943. * many times, the result should be the same (try our best to ensure that).
  1944. * (2) In `merge option` mode, if a component has no id/name specified, it
  1945. * will be merged by index, and the result sequence of the components is
  1946. * consistent to the original sequence.
  1947. * (3) `reset` feature (in toolbox). Find detailed info in comments about
  1948. * `mergeOption` in module:echarts/model/OptionManager.
  1949. */
  1950. var zrUtil = __webpack_require__(4);
  1951. var modelUtil = __webpack_require__(5);
  1952. var Model = __webpack_require__(12);
  1953. var each = zrUtil.each;
  1954. var filter = zrUtil.filter;
  1955. var map = zrUtil.map;
  1956. var isArray = zrUtil.isArray;
  1957. var indexOf = zrUtil.indexOf;
  1958. var isObject = zrUtil.isObject;
  1959. var ComponentModel = __webpack_require__(69);
  1960. var globalDefault = __webpack_require__(73);
  1961. var OPTION_INNER_KEY = '\0_ec_inner';
  1962. /**
  1963. * @alias module:echarts/model/Global
  1964. *
  1965. * @param {Object} option
  1966. * @param {module:echarts/model/Model} parentModel
  1967. * @param {Object} theme
  1968. */
  1969. var GlobalModel = Model.extend({
  1970. constructor: GlobalModel,
  1971. init: function (option, parentModel, theme, optionManager) {
  1972. theme = theme || {};
  1973. this.option = null; // Mark as not initialized.
  1974. /**
  1975. * @type {module:echarts/model/Model}
  1976. * @private
  1977. */
  1978. this._theme = new Model(theme);
  1979. /**
  1980. * @type {module:echarts/model/OptionManager}
  1981. */
  1982. this._optionManager = optionManager;
  1983. },
  1984. setOption: function (option, optionPreprocessorFuncs) {
  1985. zrUtil.assert(
  1986. !(OPTION_INNER_KEY in option),
  1987. 'please use chart.getOption()'
  1988. );
  1989. this._optionManager.setOption(option, optionPreprocessorFuncs);
  1990. this.resetOption(null);
  1991. },
  1992. /**
  1993. * @param {string} type null/undefined: reset all.
  1994. * 'recreate': force recreate all.
  1995. * 'timeline': only reset timeline option
  1996. * 'media': only reset media query option
  1997. * @return {boolean} Whether option changed.
  1998. */
  1999. resetOption: function (type) {
  2000. var optionChanged = false;
  2001. var optionManager = this._optionManager;
  2002. if (!type || type === 'recreate') {
  2003. var baseOption = optionManager.mountOption(type === 'recreate');
  2004. if (!this.option || type === 'recreate') {
  2005. initBase.call(this, baseOption);
  2006. }
  2007. else {
  2008. this.restoreData();
  2009. this.mergeOption(baseOption);
  2010. }
  2011. optionChanged = true;
  2012. }
  2013. if (type === 'timeline' || type === 'media') {
  2014. this.restoreData();
  2015. }
  2016. if (!type || type === 'recreate' || type === 'timeline') {
  2017. var timelineOption = optionManager.getTimelineOption(this);
  2018. timelineOption && (this.mergeOption(timelineOption), optionChanged = true);
  2019. }
  2020. if (!type || type === 'recreate' || type === 'media') {
  2021. var mediaOptions = optionManager.getMediaOption(this, this._api);
  2022. if (mediaOptions.length) {
  2023. each(mediaOptions, function (mediaOption) {
  2024. this.mergeOption(mediaOption, optionChanged = true);
  2025. }, this);
  2026. }
  2027. }
  2028. return optionChanged;
  2029. },
  2030. /**
  2031. * @protected
  2032. */
  2033. mergeOption: function (newOption) {
  2034. var option = this.option;
  2035. var componentsMap = this._componentsMap;
  2036. var newCptTypes = [];
  2037. // 如果不存在对应的 component model 则直接 merge
  2038. each(newOption, function (componentOption, mainType) {
  2039. if (componentOption == null) {
  2040. return;
  2041. }
  2042. if (!ComponentModel.hasClass(mainType)) {
  2043. option[mainType] = option[mainType] == null
  2044. ? zrUtil.clone(componentOption)
  2045. : zrUtil.merge(option[mainType], componentOption, true);
  2046. }
  2047. else {
  2048. newCptTypes.push(mainType);
  2049. }
  2050. });
  2051. // FIXME OPTION 同步是否要改回原来的
  2052. ComponentModel.topologicalTravel(
  2053. newCptTypes, ComponentModel.getAllClassMainTypes(), visitComponent, this
  2054. );
  2055. this._seriesIndices = this._seriesIndices || [];
  2056. function visitComponent(mainType, dependencies) {
  2057. var newCptOptionList = modelUtil.normalizeToArray(newOption[mainType]);
  2058. var mapResult = modelUtil.mappingToExists(
  2059. componentsMap.get(mainType), newCptOptionList
  2060. );
  2061. modelUtil.makeIdAndName(mapResult);
  2062. // Set mainType and complete subType.
  2063. each(mapResult, function (item, index) {
  2064. var opt = item.option;
  2065. if (isObject(opt)) {
  2066. item.keyInfo.mainType = mainType;
  2067. item.keyInfo.subType = determineSubType(mainType, opt, item.exist);
  2068. }
  2069. });
  2070. var dependentModels = getComponentsByTypes(
  2071. componentsMap, dependencies
  2072. );
  2073. option[mainType] = [];
  2074. componentsMap.set(mainType, []);
  2075. each(mapResult, function (resultItem, index) {
  2076. var componentModel = resultItem.exist;
  2077. var newCptOption = resultItem.option;
  2078. zrUtil.assert(
  2079. isObject(newCptOption) || componentModel,
  2080. 'Empty component definition'
  2081. );
  2082. // Consider where is no new option and should be merged using {},
  2083. // see removeEdgeAndAdd in topologicalTravel and
  2084. // ComponentModel.getAllClassMainTypes.
  2085. if (!newCptOption) {
  2086. componentModel.mergeOption({}, this);
  2087. componentModel.optionUpdated({}, false);
  2088. }
  2089. else {
  2090. var ComponentModelClass = ComponentModel.getClass(
  2091. mainType, resultItem.keyInfo.subType, true
  2092. );
  2093. if (componentModel && componentModel instanceof ComponentModelClass) {
  2094. componentModel.name = resultItem.keyInfo.name;
  2095. componentModel.mergeOption(newCptOption, this);
  2096. componentModel.optionUpdated(newCptOption, false);
  2097. }
  2098. else {
  2099. // PENDING Global as parent ?
  2100. var extraOpt = zrUtil.extend(
  2101. {
  2102. dependentModels: dependentModels,
  2103. componentIndex: index
  2104. },
  2105. resultItem.keyInfo
  2106. );
  2107. componentModel = new ComponentModelClass(
  2108. newCptOption, this, this, extraOpt
  2109. );
  2110. zrUtil.extend(componentModel, extraOpt);
  2111. componentModel.init(newCptOption, this, this, extraOpt);
  2112. // Call optionUpdated after init.
  2113. // newCptOption has been used as componentModel.option
  2114. // and may be merged with theme and default, so pass null
  2115. // to avoid confusion.
  2116. componentModel.optionUpdated(null, true);
  2117. }
  2118. }
  2119. componentsMap.get(mainType)[index] = componentModel;
  2120. option[mainType][index] = componentModel.option;
  2121. }, this);
  2122. // Backup series for filtering.
  2123. if (mainType === 'series') {
  2124. this._seriesIndices = createSeriesIndices(componentsMap.get('series'));
  2125. }
  2126. }
  2127. },
  2128. /**
  2129. * Get option for output (cloned option and inner info removed)
  2130. * @public
  2131. * @return {Object}
  2132. */
  2133. getOption: function () {
  2134. var option = zrUtil.clone(this.option);
  2135. each(option, function (opts, mainType) {
  2136. if (ComponentModel.hasClass(mainType)) {
  2137. var opts = modelUtil.normalizeToArray(opts);
  2138. for (var i = opts.length - 1; i >= 0; i--) {
  2139. // Remove options with inner id.
  2140. if (modelUtil.isIdInner(opts[i])) {
  2141. opts.splice(i, 1);
  2142. }
  2143. }
  2144. option[mainType] = opts;
  2145. }
  2146. });
  2147. delete option[OPTION_INNER_KEY];
  2148. return option;
  2149. },
  2150. /**
  2151. * @return {module:echarts/model/Model}
  2152. */
  2153. getTheme: function () {
  2154. return this._theme;
  2155. },
  2156. /**
  2157. * @param {string} mainType
  2158. * @param {number} [idx=0]
  2159. * @return {module:echarts/model/Component}
  2160. */
  2161. getComponent: function (mainType, idx) {
  2162. var list = this._componentsMap.get(mainType);
  2163. if (list) {
  2164. return list[idx || 0];
  2165. }
  2166. },
  2167. /**
  2168. * If none of index and id and name used, return all components with mainType.
  2169. * @param {Object} condition
  2170. * @param {string} condition.mainType
  2171. * @param {string} [condition.subType] If ignore, only query by mainType
  2172. * @param {number|Array.<number>} [condition.index] Either input index or id or name.
  2173. * @param {string|Array.<string>} [condition.id] Either input index or id or name.
  2174. * @param {string|Array.<string>} [condition.name] Either input index or id or name.
  2175. * @return {Array.<module:echarts/model/Component>}
  2176. */
  2177. queryComponents: function (condition) {
  2178. var mainType = condition.mainType;
  2179. if (!mainType) {
  2180. return [];
  2181. }
  2182. var index = condition.index;
  2183. var id = condition.id;
  2184. var name = condition.name;
  2185. var cpts = this._componentsMap.get(mainType);
  2186. if (!cpts || !cpts.length) {
  2187. return [];
  2188. }
  2189. var result;
  2190. if (index != null) {
  2191. if (!isArray(index)) {
  2192. index = [index];
  2193. }
  2194. result = filter(map(index, function (idx) {
  2195. return cpts[idx];
  2196. }), function (val) {
  2197. return !!val;
  2198. });
  2199. }
  2200. else if (id != null) {
  2201. var isIdArray = isArray(id);
  2202. result = filter(cpts, function (cpt) {
  2203. return (isIdArray && indexOf(id, cpt.id) >= 0)
  2204. || (!isIdArray && cpt.id === id);
  2205. });
  2206. }
  2207. else if (name != null) {
  2208. var isNameArray = isArray(name);
  2209. result = filter(cpts, function (cpt) {
  2210. return (isNameArray && indexOf(name, cpt.name) >= 0)
  2211. || (!isNameArray && cpt.name === name);
  2212. });
  2213. }
  2214. else {
  2215. // Return all components with mainType
  2216. result = cpts.slice();
  2217. }
  2218. return filterBySubType(result, condition);
  2219. },
  2220. /**
  2221. * The interface is different from queryComponents,
  2222. * which is convenient for inner usage.
  2223. *
  2224. * @usage
  2225. * var result = findComponents(
  2226. * {mainType: 'dataZoom', query: {dataZoomId: 'abc'}}
  2227. * );
  2228. * var result = findComponents(
  2229. * {mainType: 'series', subType: 'pie', query: {seriesName: 'uio'}}
  2230. * );
  2231. * var result = findComponents(
  2232. * {mainType: 'series'},
  2233. * function (model, index) {...}
  2234. * );
  2235. * // result like [component0, componnet1, ...]
  2236. *
  2237. * @param {Object} condition
  2238. * @param {string} condition.mainType Mandatory.
  2239. * @param {string} [condition.subType] Optional.
  2240. * @param {Object} [condition.query] like {xxxIndex, xxxId, xxxName},
  2241. * where xxx is mainType.
  2242. * If query attribute is null/undefined or has no index/id/name,
  2243. * do not filtering by query conditions, which is convenient for
  2244. * no-payload situations or when target of action is global.
  2245. * @param {Function} [condition.filter] parameter: component, return boolean.
  2246. * @return {Array.<module:echarts/model/Component>}
  2247. */
  2248. findComponents: function (condition) {
  2249. var query = condition.query;
  2250. var mainType = condition.mainType;
  2251. var queryCond = getQueryCond(query);
  2252. var result = queryCond
  2253. ? this.queryComponents(queryCond)
  2254. : this._componentsMap.get(mainType);
  2255. return doFilter(filterBySubType(result, condition));
  2256. function getQueryCond(q) {
  2257. var indexAttr = mainType + 'Index';
  2258. var idAttr = mainType + 'Id';
  2259. var nameAttr = mainType + 'Name';
  2260. return q && (
  2261. q[indexAttr] != null
  2262. || q[idAttr] != null
  2263. || q[nameAttr] != null
  2264. )
  2265. ? {
  2266. mainType: mainType,
  2267. // subType will be filtered finally.
  2268. index: q[indexAttr],
  2269. id: q[idAttr],
  2270. name: q[nameAttr]
  2271. }
  2272. : null;
  2273. }
  2274. function doFilter(res) {
  2275. return condition.filter
  2276. ? filter(res, condition.filter)
  2277. : res;
  2278. }
  2279. },
  2280. /**
  2281. * @usage
  2282. * eachComponent('legend', function (legendModel, index) {
  2283. * ...
  2284. * });
  2285. * eachComponent(function (componentType, model, index) {
  2286. * // componentType does not include subType
  2287. * // (componentType is 'xxx' but not 'xxx.aa')
  2288. * });
  2289. * eachComponent(
  2290. * {mainType: 'dataZoom', query: {dataZoomId: 'abc'}},
  2291. * function (model, index) {...}
  2292. * );
  2293. * eachComponent(
  2294. * {mainType: 'series', subType: 'pie', query: {seriesName: 'uio'}},
  2295. * function (model, index) {...}
  2296. * );
  2297. *
  2298. * @param {string|Object=} mainType When mainType is object, the definition
  2299. * is the same as the method 'findComponents'.
  2300. * @param {Function} cb
  2301. * @param {*} context
  2302. */
  2303. eachComponent: function (mainType, cb, context) {
  2304. var componentsMap = this._componentsMap;
  2305. if (typeof mainType === 'function') {
  2306. context = cb;
  2307. cb = mainType;
  2308. componentsMap.each(function (components, componentType) {
  2309. each(components, function (component, index) {
  2310. cb.call(context, componentType, component, index);
  2311. });
  2312. });
  2313. }
  2314. else if (zrUtil.isString(mainType)) {
  2315. each(componentsMap.get(mainType), cb, context);
  2316. }
  2317. else if (isObject(mainType)) {
  2318. var queryResult = this.findComponents(mainType);
  2319. each(queryResult, cb, context);
  2320. }
  2321. },
  2322. /**
  2323. * @param {string} name
  2324. * @return {Array.<module:echarts/model/Series>}
  2325. */
  2326. getSeriesByName: function (name) {
  2327. var series = this._componentsMap.get('series');
  2328. return filter(series, function (oneSeries) {
  2329. return oneSeries.name === name;
  2330. });
  2331. },
  2332. /**
  2333. * @param {number} seriesIndex
  2334. * @return {module:echarts/model/Series}
  2335. */
  2336. getSeriesByIndex: function (seriesIndex) {
  2337. return this._componentsMap.get('series')[seriesIndex];
  2338. },
  2339. /**
  2340. * @param {string} subType
  2341. * @return {Array.<module:echarts/model/Series>}
  2342. */
  2343. getSeriesByType: function (subType) {
  2344. var series = this._componentsMap.get('series');
  2345. return filter(series, function (oneSeries) {
  2346. return oneSeries.subType === subType;
  2347. });
  2348. },
  2349. /**
  2350. * @return {Array.<module:echarts/model/Series>}
  2351. */
  2352. getSeries: function () {
  2353. return this._componentsMap.get('series').slice();
  2354. },
  2355. /**
  2356. * After filtering, series may be different
  2357. * frome raw series.
  2358. *
  2359. * @param {Function} cb
  2360. * @param {*} context
  2361. */
  2362. eachSeries: function (cb, context) {
  2363. assertSeriesInitialized(this);
  2364. each(this._seriesIndices, function (rawSeriesIndex) {
  2365. var series = this._componentsMap.get('series')[rawSeriesIndex];
  2366. cb.call(context, series, rawSeriesIndex);
  2367. }, this);
  2368. },
  2369. /**
  2370. * Iterate raw series before filtered.
  2371. *
  2372. * @param {Function} cb
  2373. * @param {*} context
  2374. */
  2375. eachRawSeries: function (cb, context) {
  2376. each(this._componentsMap.get('series'), cb, context);
  2377. },
  2378. /**
  2379. * After filtering, series may be different.
  2380. * frome raw series.
  2381. *
  2382. * @parma {string} subType
  2383. * @param {Function} cb
  2384. * @param {*} context
  2385. */
  2386. eachSeriesByType: function (subType, cb, context) {
  2387. assertSeriesInitialized(this);
  2388. each(this._seriesIndices, function (rawSeriesIndex) {
  2389. var series = this._componentsMap.get('series')[rawSeriesIndex];
  2390. if (series.subType === subType) {
  2391. cb.call(context, series, rawSeriesIndex);
  2392. }
  2393. }, this);
  2394. },
  2395. /**
  2396. * Iterate raw series before filtered of given type.
  2397. *
  2398. * @parma {string} subType
  2399. * @param {Function} cb
  2400. * @param {*} context
  2401. */
  2402. eachRawSeriesByType: function (subType, cb, context) {
  2403. return each(this.getSeriesByType(subType), cb, context);
  2404. },
  2405. /**
  2406. * @param {module:echarts/model/Series} seriesModel
  2407. */
  2408. isSeriesFiltered: function (seriesModel) {
  2409. assertSeriesInitialized(this);
  2410. return zrUtil.indexOf(this._seriesIndices, seriesModel.componentIndex) < 0;
  2411. },
  2412. /**
  2413. * @return {Array.<number>}
  2414. */
  2415. getCurrentSeriesIndices: function () {
  2416. return (this._seriesIndices || []).slice();
  2417. },
  2418. /**
  2419. * @param {Function} cb
  2420. * @param {*} context
  2421. */
  2422. filterSeries: function (cb, context) {
  2423. assertSeriesInitialized(this);
  2424. var filteredSeries = filter(
  2425. this._componentsMap.get('series'), cb, context
  2426. );
  2427. this._seriesIndices = createSeriesIndices(filteredSeries);
  2428. },
  2429. restoreData: function () {
  2430. var componentsMap = this._componentsMap;
  2431. this._seriesIndices = createSeriesIndices(componentsMap.get('series'));
  2432. var componentTypes = [];
  2433. componentsMap.each(function (components, componentType) {
  2434. componentTypes.push(componentType);
  2435. });
  2436. ComponentModel.topologicalTravel(
  2437. componentTypes,
  2438. ComponentModel.getAllClassMainTypes(),
  2439. function (componentType, dependencies) {
  2440. each(componentsMap.get(componentType), function (component) {
  2441. component.restoreData();
  2442. });
  2443. }
  2444. );
  2445. }
  2446. });
  2447. /**
  2448. * @inner
  2449. */
  2450. function mergeTheme(option, theme) {
  2451. zrUtil.each(theme, function (themeItem, name) {
  2452. // 如果有 component model 则把具体的 merge 逻辑交给该 model 处理
  2453. if (!ComponentModel.hasClass(name)) {
  2454. if (typeof themeItem === 'object') {
  2455. option[name] = !option[name]
  2456. ? zrUtil.clone(themeItem)
  2457. : zrUtil.merge(option[name], themeItem, false);
  2458. }
  2459. else {
  2460. if (option[name] == null) {
  2461. option[name] = themeItem;
  2462. }
  2463. }
  2464. }
  2465. });
  2466. }
  2467. function initBase(baseOption) {
  2468. baseOption = baseOption;
  2469. // Using OPTION_INNER_KEY to mark that this option can not be used outside,
  2470. // i.e. `chart.setOption(chart.getModel().option);` is forbiden.
  2471. this.option = {};
  2472. this.option[OPTION_INNER_KEY] = 1;
  2473. /**
  2474. * Init with series: [], in case of calling findSeries method
  2475. * before series initialized.
  2476. * @type {Object.<string, Array.<module:echarts/model/Model>>}
  2477. * @private
  2478. */
  2479. this._componentsMap = zrUtil.createHashMap({series: []});
  2480. /**
  2481. * Mapping between filtered series list and raw series list.
  2482. * key: filtered series indices, value: raw series indices.
  2483. * @type {Array.<nubmer>}
  2484. * @private
  2485. */
  2486. this._seriesIndices = null;
  2487. mergeTheme(baseOption, this._theme.option);
  2488. // TODO Needs clone when merging to the unexisted property
  2489. zrUtil.merge(baseOption, globalDefault, false);
  2490. this.mergeOption(baseOption);
  2491. }
  2492. /**
  2493. * @inner
  2494. * @param {Array.<string>|string} types model types
  2495. * @return {Object} key: {string} type, value: {Array.<Object>} models
  2496. */
  2497. function getComponentsByTypes(componentsMap, types) {
  2498. if (!zrUtil.isArray(types)) {
  2499. types = types ? [types] : [];
  2500. }
  2501. var ret = {};
  2502. each(types, function (type) {
  2503. ret[type] = (componentsMap.get(type) || []).slice();
  2504. });
  2505. return ret;
  2506. }
  2507. /**
  2508. * @inner
  2509. */
  2510. function determineSubType(mainType, newCptOption, existComponent) {
  2511. var subType = newCptOption.type
  2512. ? newCptOption.type
  2513. : existComponent
  2514. ? existComponent.subType
  2515. // Use determineSubType only when there is no existComponent.
  2516. : ComponentModel.determineSubType(mainType, newCptOption);
  2517. // tooltip, markline, markpoint may always has no subType
  2518. return subType;
  2519. }
  2520. /**
  2521. * @inner
  2522. */
  2523. function createSeriesIndices(seriesModels) {
  2524. return map(seriesModels, function (series) {
  2525. return series.componentIndex;
  2526. }) || [];
  2527. }
  2528. /**
  2529. * @inner
  2530. */
  2531. function filterBySubType(components, condition) {
  2532. // Using hasOwnProperty for restrict. Consider
  2533. // subType is undefined in user payload.
  2534. return condition.hasOwnProperty('subType')
  2535. ? filter(components, function (cpt) {
  2536. return cpt.subType === condition.subType;
  2537. })
  2538. : components;
  2539. }
  2540. /**
  2541. * @inner
  2542. */
  2543. function assertSeriesInitialized(ecModel) {
  2544. // Components that use _seriesIndices should depends on series component,
  2545. // which make sure that their initialization is after series.
  2546. if (true) {
  2547. if (!ecModel._seriesIndices) {
  2548. throw new Error('Option should contains series.');
  2549. }
  2550. }
  2551. }
  2552. zrUtil.mixin(GlobalModel, __webpack_require__(74));
  2553. module.exports = GlobalModel;
  2554. /***/ },
  2555. /* 4 */
  2556. /***/ function(module, exports) {
  2557. /**
  2558. * @module zrender/core/util
  2559. */
  2560. // 用于处理merge时无法遍历Date等对象的问题
  2561. var BUILTIN_OBJECT = {
  2562. '[object Function]': 1,
  2563. '[object RegExp]': 1,
  2564. '[object Date]': 1,
  2565. '[object Error]': 1,
  2566. '[object CanvasGradient]': 1,
  2567. '[object CanvasPattern]': 1,
  2568. // For node-canvas
  2569. '[object Image]': 1,
  2570. '[object Canvas]': 1
  2571. };
  2572. var TYPED_ARRAY = {
  2573. '[object Int8Array]': 1,
  2574. '[object Uint8Array]': 1,
  2575. '[object Uint8ClampedArray]': 1,
  2576. '[object Int16Array]': 1,
  2577. '[object Uint16Array]': 1,
  2578. '[object Int32Array]': 1,
  2579. '[object Uint32Array]': 1,
  2580. '[object Float32Array]': 1,
  2581. '[object Float64Array]': 1
  2582. };
  2583. var objToString = Object.prototype.toString;
  2584. var arrayProto = Array.prototype;
  2585. var nativeForEach = arrayProto.forEach;
  2586. var nativeFilter = arrayProto.filter;
  2587. var nativeSlice = arrayProto.slice;
  2588. var nativeMap = arrayProto.map;
  2589. var nativeReduce = arrayProto.reduce;
  2590. /**
  2591. * Those data types can be cloned:
  2592. * Plain object, Array, TypedArray, number, string, null, undefined.
  2593. * Those data types will be assgined using the orginal data:
  2594. * BUILTIN_OBJECT
  2595. * Instance of user defined class will be cloned to a plain object, without
  2596. * properties in prototype.
  2597. * Other data types is not supported (not sure what will happen).
  2598. *
  2599. * Caution: do not support clone Date, for performance consideration.
  2600. * (There might be a large number of date in `series.data`).
  2601. * So date should not be modified in and out of echarts.
  2602. *
  2603. * @param {*} source
  2604. * @return {*} new
  2605. */
  2606. function clone(source) {
  2607. if (source == null || typeof source != 'object') {
  2608. return source;
  2609. }
  2610. var result = source;
  2611. var typeStr = objToString.call(source);
  2612. if (typeStr === '[object Array]') {
  2613. result = [];
  2614. for (var i = 0, len = source.length; i < len; i++) {
  2615. result[i] = clone(source[i]);
  2616. }
  2617. }
  2618. else if (TYPED_ARRAY[typeStr]) {
  2619. result = source.constructor.from(source);
  2620. }
  2621. else if (!BUILTIN_OBJECT[typeStr] && !isPrimitive(source) && !isDom(source)) {
  2622. result = {};
  2623. for (var key in source) {
  2624. if (source.hasOwnProperty(key)) {
  2625. result[key] = clone(source[key]);
  2626. }
  2627. }
  2628. }
  2629. return result;
  2630. }
  2631. /**
  2632. * @memberOf module:zrender/core/util
  2633. * @param {*} target
  2634. * @param {*} source
  2635. * @param {boolean} [overwrite=false]
  2636. */
  2637. function merge(target, source, overwrite) {
  2638. // We should escapse that source is string
  2639. // and enter for ... in ...
  2640. if (!isObject(source) || !isObject(target)) {
  2641. return overwrite ? clone(source) : target;
  2642. }
  2643. for (var key in source) {
  2644. if (source.hasOwnProperty(key)) {
  2645. var targetProp = target[key];
  2646. var sourceProp = source[key];
  2647. if (isObject(sourceProp)
  2648. && isObject(targetProp)
  2649. && !isArray(sourceProp)
  2650. && !isArray(targetProp)
  2651. && !isDom(sourceProp)
  2652. && !isDom(targetProp)
  2653. && !isBuiltInObject(sourceProp)
  2654. && !isBuiltInObject(targetProp)
  2655. && !isPrimitive(sourceProp)
  2656. && !isPrimitive(targetProp)
  2657. ) {
  2658. // 如果需要递归覆盖,就递归调用merge
  2659. merge(targetProp, sourceProp, overwrite);
  2660. }
  2661. else if (overwrite || !(key in target)) {
  2662. // 否则只处理overwrite为true,或者在目标对象中没有此属性的情况
  2663. // NOTE,在 target[key] 不存在的时候也是直接覆盖
  2664. target[key] = clone(source[key], true);
  2665. }
  2666. }
  2667. }
  2668. return target;
  2669. }
  2670. /**
  2671. * @param {Array} targetAndSources The first item is target, and the rests are source.
  2672. * @param {boolean} [overwrite=false]
  2673. * @return {*} target
  2674. */
  2675. function mergeAll(targetAndSources, overwrite) {
  2676. var result = targetAndSources[0];
  2677. for (var i = 1, len = targetAndSources.length; i < len; i++) {
  2678. result = merge(result, targetAndSources[i], overwrite);
  2679. }
  2680. return result;
  2681. }
  2682. /**
  2683. * @param {*} target
  2684. * @param {*} source
  2685. * @memberOf module:zrender/core/util
  2686. */
  2687. function extend(target, source) {
  2688. for (var key in source) {
  2689. if (source.hasOwnProperty(key)) {
  2690. target[key] = source[key];
  2691. }
  2692. }
  2693. return target;
  2694. }
  2695. /**
  2696. * @param {*} target
  2697. * @param {*} source
  2698. * @param {boolen} [overlay=false]
  2699. * @memberOf module:zrender/core/util
  2700. */
  2701. function defaults(target, source, overlay) {
  2702. for (var key in source) {
  2703. if (source.hasOwnProperty(key)
  2704. && (overlay ? source[key] != null : target[key] == null)
  2705. ) {
  2706. target[key] = source[key];
  2707. }
  2708. }
  2709. return target;
  2710. }
  2711. function createCanvas() {
  2712. return document.createElement('canvas');
  2713. }
  2714. // FIXME
  2715. var _ctx;
  2716. function getContext() {
  2717. if (!_ctx) {
  2718. // Use util.createCanvas instead of createCanvas
  2719. // because createCanvas may be overwritten in different environment
  2720. _ctx = util.createCanvas().getContext('2d');
  2721. }
  2722. return _ctx;
  2723. }
  2724. /**
  2725. * 查询数组中元素的index
  2726. * @memberOf module:zrender/core/util
  2727. */
  2728. function indexOf(array, value) {
  2729. if (array) {
  2730. if (array.indexOf) {
  2731. return array.indexOf(value);
  2732. }
  2733. for (var i = 0, len = array.length; i < len; i++) {
  2734. if (array[i] === value) {
  2735. return i;
  2736. }
  2737. }
  2738. }
  2739. return -1;
  2740. }
  2741. /**
  2742. * 构造类继承关系
  2743. *
  2744. * @memberOf module:zrender/core/util
  2745. * @param {Function} clazz 源类
  2746. * @param {Function} baseClazz 基类
  2747. */
  2748. function inherits(clazz, baseClazz) {
  2749. var clazzPrototype = clazz.prototype;
  2750. function F() {}
  2751. F.prototype = baseClazz.prototype;
  2752. clazz.prototype = new F();
  2753. for (var prop in clazzPrototype) {
  2754. clazz.prototype[prop] = clazzPrototype[prop];
  2755. }
  2756. clazz.prototype.constructor = clazz;
  2757. clazz.superClass = baseClazz;
  2758. }
  2759. /**
  2760. * @memberOf module:zrender/core/util
  2761. * @param {Object|Function} target
  2762. * @param {Object|Function} sorce
  2763. * @param {boolean} overlay
  2764. */
  2765. function mixin(target, source, overlay) {
  2766. target = 'prototype' in target ? target.prototype : target;
  2767. source = 'prototype' in source ? source.prototype : source;
  2768. defaults(target, source, overlay);
  2769. }
  2770. /**
  2771. * Consider typed array.
  2772. * @param {Array|TypedArray} data
  2773. */
  2774. function isArrayLike(data) {
  2775. if (! data) {
  2776. return;
  2777. }
  2778. if (typeof data == 'string') {
  2779. return false;
  2780. }
  2781. return typeof data.length == 'number';
  2782. }
  2783. /**
  2784. * 数组或对象遍历
  2785. * @memberOf module:zrender/core/util
  2786. * @param {Object|Array} obj
  2787. * @param {Function} cb
  2788. * @param {*} [context]
  2789. */
  2790. function each(obj, cb, context) {
  2791. if (!(obj && cb)) {
  2792. return;
  2793. }
  2794. if (obj.forEach && obj.forEach === nativeForEach) {
  2795. obj.forEach(cb, context);
  2796. }
  2797. else if (obj.length === +obj.length) {
  2798. for (var i = 0, len = obj.length; i < len; i++) {
  2799. cb.call(context, obj[i], i, obj);
  2800. }
  2801. }
  2802. else {
  2803. for (var key in obj) {
  2804. if (obj.hasOwnProperty(key)) {
  2805. cb.call(context, obj[key], key, obj);
  2806. }
  2807. }
  2808. }
  2809. }
  2810. /**
  2811. * 数组映射
  2812. * @memberOf module:zrender/core/util
  2813. * @param {Array} obj
  2814. * @param {Function} cb
  2815. * @param {*} [context]
  2816. * @return {Array}
  2817. */
  2818. function map(obj, cb, context) {
  2819. if (!(obj && cb)) {
  2820. return;
  2821. }
  2822. if (obj.map && obj.map === nativeMap) {
  2823. return obj.map(cb, context);
  2824. }
  2825. else {
  2826. var result = [];
  2827. for (var i = 0, len = obj.length; i < len; i++) {
  2828. result.push(cb.call(context, obj[i], i, obj));
  2829. }
  2830. return result;
  2831. }
  2832. }
  2833. /**
  2834. * @memberOf module:zrender/core/util
  2835. * @param {Array} obj
  2836. * @param {Function} cb
  2837. * @param {Object} [memo]
  2838. * @param {*} [context]
  2839. * @return {Array}
  2840. */
  2841. function reduce(obj, cb, memo, context) {
  2842. if (!(obj && cb)) {
  2843. return;
  2844. }
  2845. if (obj.reduce && obj.reduce === nativeReduce) {
  2846. return obj.reduce(cb, memo, context);
  2847. }
  2848. else {
  2849. for (var i = 0, len = obj.length; i < len; i++) {
  2850. memo = cb.call(context, memo, obj[i], i, obj);
  2851. }
  2852. return memo;
  2853. }
  2854. }
  2855. /**
  2856. * 数组过滤
  2857. * @memberOf module:zrender/core/util
  2858. * @param {Array} obj
  2859. * @param {Function} cb
  2860. * @param {*} [context]
  2861. * @return {Array}
  2862. */
  2863. function filter(obj, cb, context) {
  2864. if (!(obj && cb)) {
  2865. return;
  2866. }
  2867. if (obj.filter && obj.filter === nativeFilter) {
  2868. return obj.filter(cb, context);
  2869. }
  2870. else {
  2871. var result = [];
  2872. for (var i = 0, len = obj.length; i < len; i++) {
  2873. if (cb.call(context, obj[i], i, obj)) {
  2874. result.push(obj[i]);
  2875. }
  2876. }
  2877. return result;
  2878. }
  2879. }
  2880. /**
  2881. * 数组项查找
  2882. * @memberOf module:zrender/core/util
  2883. * @param {Array} obj
  2884. * @param {Function} cb
  2885. * @param {*} [context]
  2886. * @return {Array}
  2887. */
  2888. function find(obj, cb, context) {
  2889. if (!(obj && cb)) {
  2890. return;
  2891. }
  2892. for (var i = 0, len = obj.length; i < len; i++) {
  2893. if (cb.call(context, obj[i], i, obj)) {
  2894. return obj[i];
  2895. }
  2896. }
  2897. }
  2898. /**
  2899. * @memberOf module:zrender/core/util
  2900. * @param {Function} func
  2901. * @param {*} context
  2902. * @return {Function}
  2903. */
  2904. function bind(func, context) {
  2905. var args = nativeSlice.call(arguments, 2);
  2906. return function () {
  2907. return func.apply(context, args.concat(nativeSlice.call(arguments)));
  2908. };
  2909. }
  2910. /**
  2911. * @memberOf module:zrender/core/util
  2912. * @param {Function} func
  2913. * @return {Function}
  2914. */
  2915. function curry(func) {
  2916. var args = nativeSlice.call(arguments, 1);
  2917. return function () {
  2918. return func.apply(this, args.concat(nativeSlice.call(arguments)));
  2919. };
  2920. }
  2921. /**
  2922. * @memberOf module:zrender/core/util
  2923. * @param {*} value
  2924. * @return {boolean}
  2925. */
  2926. function isArray(value) {
  2927. return objToString.call(value) === '[object Array]';
  2928. }
  2929. /**
  2930. * @memberOf module:zrender/core/util
  2931. * @param {*} value
  2932. * @return {boolean}
  2933. */
  2934. function isFunction(value) {
  2935. return typeof value === 'function';
  2936. }
  2937. /**
  2938. * @memberOf module:zrender/core/util
  2939. * @param {*} value
  2940. * @return {boolean}
  2941. */
  2942. function isString(value) {
  2943. return objToString.call(value) === '[object String]';
  2944. }
  2945. /**
  2946. * @memberOf module:zrender/core/util
  2947. * @param {*} value
  2948. * @return {boolean}
  2949. */
  2950. function isObject(value) {
  2951. // Avoid a V8 JIT bug in Chrome 19-20.
  2952. // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
  2953. var type = typeof value;
  2954. return type === 'function' || (!!value && type == 'object');
  2955. }
  2956. /**
  2957. * @memberOf module:zrender/core/util
  2958. * @param {*} value
  2959. * @return {boolean}
  2960. */
  2961. function isBuiltInObject(value) {
  2962. return !!BUILTIN_OBJECT[objToString.call(value)];
  2963. }
  2964. /**
  2965. * @memberOf module:zrender/core/util
  2966. * @param {*} value
  2967. * @return {boolean}
  2968. */
  2969. function isDom(value) {
  2970. return typeof value === 'object'
  2971. && typeof value.nodeType === 'number'
  2972. && typeof value.ownerDocument === 'object';
  2973. }
  2974. /**
  2975. * Whether is exactly NaN. Notice isNaN('a') returns true.
  2976. * @param {*} value
  2977. * @return {boolean}
  2978. */
  2979. function eqNaN(value) {
  2980. return value !== value;
  2981. }
  2982. /**
  2983. * If value1 is not null, then return value1, otherwise judget rest of values.
  2984. * @memberOf module:zrender/core/util
  2985. * @return {*} Final value
  2986. */
  2987. function retrieve(values) {
  2988. for (var i = 0, len = arguments.length; i < len; i++) {
  2989. if (arguments[i] != null) {
  2990. return arguments[i];
  2991. }
  2992. }
  2993. }
  2994. /**
  2995. * @memberOf module:zrender/core/util
  2996. * @param {Array} arr
  2997. * @param {number} startIndex
  2998. * @param {number} endIndex
  2999. * @return {Array}
  3000. */
  3001. function slice() {
  3002. return Function.call.apply(nativeSlice, arguments);
  3003. }
  3004. /**
  3005. * @memberOf module:zrender/core/util
  3006. * @param {boolean} condition
  3007. * @param {string} message
  3008. */
  3009. function assert(condition, message) {
  3010. if (!condition) {
  3011. throw new Error(message);
  3012. }
  3013. }
  3014. var primitiveKey = '__ec_primitive__';
  3015. /**
  3016. * Set an object as primitive to be ignored traversing children in clone or merge
  3017. */
  3018. function setAsPrimitive(obj) {
  3019. obj[primitiveKey] = true;
  3020. }
  3021. function isPrimitive(obj) {
  3022. return obj[primitiveKey];
  3023. }
  3024. /**
  3025. * @constructor
  3026. * @param {Object} obj Only apply `ownProperty`.
  3027. */
  3028. function HashMap(obj) {
  3029. obj && each(obj, function (value, key) {
  3030. this.set(key, value);
  3031. }, this);
  3032. }
  3033. // Add prefix to avoid conflict with Object.prototype.
  3034. var HASH_MAP_PREFIX = '_ec_';
  3035. var HASH_MAP_PREFIX_LENGTH = 4;
  3036. HashMap.prototype = {
  3037. constructor: HashMap,
  3038. // Do not provide `has` method to avoid defining what is `has`.
  3039. // (We usually treat `null` and `undefined` as the same, different
  3040. // from ES6 Map).
  3041. get: function (key) {
  3042. return this[HASH_MAP_PREFIX + key];
  3043. },
  3044. set: function (key, value) {
  3045. this[HASH_MAP_PREFIX + key] = value;
  3046. // Comparing with invocation chaining, `return value` is more commonly
  3047. // used in this case: `var someVal = map.set('a', genVal());`
  3048. return value;
  3049. },
  3050. // Although util.each can be performed on this hashMap directly, user
  3051. // should not use the exposed keys, who are prefixed.
  3052. each: function (cb, context) {
  3053. context !== void 0 && (cb = bind(cb, context));
  3054. for (var prefixedKey in this) {
  3055. this.hasOwnProperty(prefixedKey)
  3056. && cb(this[prefixedKey], prefixedKey.slice(HASH_MAP_PREFIX_LENGTH));
  3057. }
  3058. },
  3059. // Do not use this method if performance sensitive.
  3060. removeKey: function (key) {
  3061. delete this[key];
  3062. }
  3063. };
  3064. function createHashMap(obj) {
  3065. return new HashMap(obj);
  3066. }
  3067. var util = {
  3068. inherits: inherits,
  3069. mixin: mixin,
  3070. clone: clone,
  3071. merge: merge,
  3072. mergeAll: mergeAll,
  3073. extend: extend,
  3074. defaults: defaults,
  3075. getContext: getContext,
  3076. createCanvas: createCanvas,
  3077. indexOf: indexOf,
  3078. slice: slice,
  3079. find: find,
  3080. isArrayLike: isArrayLike,
  3081. each: each,
  3082. map: map,
  3083. reduce: reduce,
  3084. filter: filter,
  3085. bind: bind,
  3086. curry: curry,
  3087. isArray: isArray,
  3088. isString: isString,
  3089. isObject: isObject,
  3090. isFunction: isFunction,
  3091. isBuiltInObject: isBuiltInObject,
  3092. isDom: isDom,
  3093. eqNaN: eqNaN,
  3094. retrieve: retrieve,
  3095. assert: assert,
  3096. setAsPrimitive: setAsPrimitive,
  3097. createHashMap: createHashMap,
  3098. noop: function () {}
  3099. };
  3100. module.exports = util;
  3101. /***/ },
  3102. /* 5 */
  3103. /***/ function(module, exports, __webpack_require__) {
  3104. var formatUtil = __webpack_require__(6);
  3105. var nubmerUtil = __webpack_require__(7);
  3106. var Model = __webpack_require__(12);
  3107. var zrUtil = __webpack_require__(4);
  3108. var each = zrUtil.each;
  3109. var isObject = zrUtil.isObject;
  3110. var modelUtil = {};
  3111. /**
  3112. * If value is not array, then translate it to array.
  3113. * @param {*} value
  3114. * @return {Array} [value] or value
  3115. */
  3116. modelUtil.normalizeToArray = function (value) {
  3117. return value instanceof Array
  3118. ? value
  3119. : value == null
  3120. ? []
  3121. : [value];
  3122. };
  3123. /**
  3124. * Sync default option between normal and emphasis like `position` and `show`
  3125. * In case some one will write code like
  3126. * label: {
  3127. * normal: {
  3128. * show: false,
  3129. * position: 'outside',
  3130. * textStyle: {
  3131. * fontSize: 18
  3132. * }
  3133. * },
  3134. * emphasis: {
  3135. * show: true
  3136. * }
  3137. * }
  3138. * @param {Object} opt
  3139. * @param {Array.<string>} subOpts
  3140. */
  3141. modelUtil.defaultEmphasis = function (opt, subOpts) {
  3142. if (opt) {
  3143. var emphasisOpt = opt.emphasis = opt.emphasis || {};
  3144. var normalOpt = opt.normal = opt.normal || {};
  3145. // Default emphasis option from normal
  3146. each(subOpts, function (subOptName) {
  3147. var val = zrUtil.retrieve(emphasisOpt[subOptName], normalOpt[subOptName]);
  3148. if (val != null) {
  3149. emphasisOpt[subOptName] = val;
  3150. }
  3151. });
  3152. }
  3153. };
  3154. modelUtil.LABEL_OPTIONS = ['position', 'offset', 'show', 'textStyle', 'distance', 'formatter'];
  3155. /**
  3156. * data could be [12, 2323, {value: 223}, [1221, 23], {value: [2, 23]}]
  3157. * This helper method retieves value from data.
  3158. * @param {string|number|Date|Array|Object} dataItem
  3159. * @return {number|string|Date|Array.<number|string|Date>}
  3160. */
  3161. modelUtil.getDataItemValue = function (dataItem) {
  3162. // Performance sensitive.
  3163. return dataItem && (dataItem.value == null ? dataItem : dataItem.value);
  3164. };
  3165. /**
  3166. * data could be [12, 2323, {value: 223}, [1221, 23], {value: [2, 23]}]
  3167. * This helper method determine if dataItem has extra option besides value
  3168. * @param {string|number|Date|Array|Object} dataItem
  3169. */
  3170. modelUtil.isDataItemOption = function (dataItem) {
  3171. return isObject(dataItem)
  3172. && !(dataItem instanceof Array);
  3173. // // markLine data can be array
  3174. // && !(dataItem[0] && isObject(dataItem[0]) && !(dataItem[0] instanceof Array));
  3175. };
  3176. /**
  3177. * This helper method convert value in data.
  3178. * @param {string|number|Date} value
  3179. * @param {Object|string} [dimInfo] If string (like 'x'), dimType defaults 'number'.
  3180. */
  3181. modelUtil.converDataValue = function (value, dimInfo) {
  3182. // Performance sensitive.
  3183. var dimType = dimInfo && dimInfo.type;
  3184. if (dimType === 'ordinal') {
  3185. return value;
  3186. }
  3187. if (dimType === 'time'
  3188. // spead up when using timestamp
  3189. && typeof value !== 'number'
  3190. && value != null
  3191. && value !== '-'
  3192. ) {
  3193. value = +nubmerUtil.parseDate(value);
  3194. }
  3195. // dimType defaults 'number'.
  3196. // If dimType is not ordinal and value is null or undefined or NaN or '-',
  3197. // parse to NaN.
  3198. return (value == null || value === '')
  3199. ? NaN : +value; // If string (like '-'), using '+' parse to NaN
  3200. };
  3201. /**
  3202. * Create a model proxy to be used in tooltip for edge data, markLine data, markPoint data.
  3203. * @param {module:echarts/data/List} data
  3204. * @param {Object} opt
  3205. * @param {string} [opt.seriesIndex]
  3206. * @param {Object} [opt.name]
  3207. * @param {Object} [opt.mainType]
  3208. * @param {Object} [opt.subType]
  3209. */
  3210. modelUtil.createDataFormatModel = function (data, opt) {
  3211. var model = new Model();
  3212. zrUtil.mixin(model, modelUtil.dataFormatMixin);
  3213. model.seriesIndex = opt.seriesIndex;
  3214. model.name = opt.name || '';
  3215. model.mainType = opt.mainType;
  3216. model.subType = opt.subType;
  3217. model.getData = function () {
  3218. return data;
  3219. };
  3220. return model;
  3221. };
  3222. // PENDING A little ugly
  3223. modelUtil.dataFormatMixin = {
  3224. /**
  3225. * Get params for formatter
  3226. * @param {number} dataIndex
  3227. * @param {string} [dataType]
  3228. * @return {Object}
  3229. */
  3230. getDataParams: function (dataIndex, dataType) {
  3231. var data = this.getData(dataType);
  3232. var rawValue = this.getRawValue(dataIndex, dataType);
  3233. var rawDataIndex = data.getRawIndex(dataIndex);
  3234. var name = data.getName(dataIndex, true);
  3235. var itemOpt = data.getRawDataItem(dataIndex);
  3236. var color = data.getItemVisual(dataIndex, 'color');
  3237. return {
  3238. componentType: this.mainType,
  3239. componentSubType: this.subType,
  3240. seriesType: this.mainType === 'series' ? this.subType : null,
  3241. seriesIndex: this.seriesIndex,
  3242. seriesId: this.id,
  3243. seriesName: this.name,
  3244. name: name,
  3245. dataIndex: rawDataIndex,
  3246. data: itemOpt,
  3247. dataType: dataType,
  3248. value: rawValue,
  3249. color: color,
  3250. marker: formatUtil.getTooltipMarker(color),
  3251. // Param name list for mapping `a`, `b`, `c`, `d`, `e`
  3252. $vars: ['seriesName', 'name', 'value']
  3253. };
  3254. },
  3255. /**
  3256. * Format label
  3257. * @param {number} dataIndex
  3258. * @param {string} [status='normal'] 'normal' or 'emphasis'
  3259. * @param {string} [dataType]
  3260. * @param {number} [dimIndex]
  3261. * @return {string}
  3262. */
  3263. getFormattedLabel: function (dataIndex, status, dataType, dimIndex) {
  3264. status = status || 'normal';
  3265. var data = this.getData(dataType);
  3266. var itemModel = data.getItemModel(dataIndex);
  3267. var params = this.getDataParams(dataIndex, dataType);
  3268. if (dimIndex != null && (params.value instanceof Array)) {
  3269. params.value = params.value[dimIndex];
  3270. }
  3271. var formatter = itemModel.get(['label', status, 'formatter']);
  3272. if (typeof formatter === 'function') {
  3273. params.status = status;
  3274. return formatter(params);
  3275. }
  3276. else if (typeof formatter === 'string') {
  3277. return formatUtil.formatTpl(formatter, params);
  3278. }
  3279. },
  3280. /**
  3281. * Get raw value in option
  3282. * @param {number} idx
  3283. * @param {string} [dataType]
  3284. * @return {Object}
  3285. */
  3286. getRawValue: function (idx, dataType) {
  3287. var data = this.getData(dataType);
  3288. var dataItem = data.getRawDataItem(idx);
  3289. if (dataItem != null) {
  3290. return (isObject(dataItem) && !(dataItem instanceof Array))
  3291. ? dataItem.value : dataItem;
  3292. }
  3293. },
  3294. /**
  3295. * Should be implemented.
  3296. * @param {number} dataIndex
  3297. * @param {boolean} [multipleSeries=false]
  3298. * @param {number} [dataType]
  3299. * @return {string} tooltip string
  3300. */
  3301. formatTooltip: zrUtil.noop
  3302. };
  3303. /**
  3304. * Mapping to exists for merge.
  3305. *
  3306. * @public
  3307. * @param {Array.<Object>|Array.<module:echarts/model/Component>} exists
  3308. * @param {Object|Array.<Object>} newCptOptions
  3309. * @return {Array.<Object>} Result, like [{exist: ..., option: ...}, {}],
  3310. * index of which is the same as exists.
  3311. */
  3312. modelUtil.mappingToExists = function (exists, newCptOptions) {
  3313. // Mapping by the order by original option (but not order of
  3314. // new option) in merge mode. Because we should ensure
  3315. // some specified index (like xAxisIndex) is consistent with
  3316. // original option, which is easy to understand, espatially in
  3317. // media query. And in most case, merge option is used to
  3318. // update partial option but not be expected to change order.
  3319. newCptOptions = (newCptOptions || []).slice();
  3320. var result = zrUtil.map(exists || [], function (obj, index) {
  3321. return {exist: obj};
  3322. });
  3323. // Mapping by id or name if specified.
  3324. each(newCptOptions, function (cptOption, index) {
  3325. if (!isObject(cptOption)) {
  3326. return;
  3327. }
  3328. // id has highest priority.
  3329. for (var i = 0; i < result.length; i++) {
  3330. if (!result[i].option // Consider name: two map to one.
  3331. && cptOption.id != null
  3332. && result[i].exist.id === cptOption.id + ''
  3333. ) {
  3334. result[i].option = cptOption;
  3335. newCptOptions[index] = null;
  3336. return;
  3337. }
  3338. }
  3339. for (var i = 0; i < result.length; i++) {
  3340. var exist = result[i].exist;
  3341. if (!result[i].option // Consider name: two map to one.
  3342. // Can not match when both ids exist but different.
  3343. && (exist.id == null || cptOption.id == null)
  3344. && cptOption.name != null
  3345. && !modelUtil.isIdInner(cptOption)
  3346. && !modelUtil.isIdInner(exist)
  3347. && exist.name === cptOption.name + ''
  3348. ) {
  3349. result[i].option = cptOption;
  3350. newCptOptions[index] = null;
  3351. return;
  3352. }
  3353. }
  3354. });
  3355. // Otherwise mapping by index.
  3356. each(newCptOptions, function (cptOption, index) {
  3357. if (!isObject(cptOption)) {
  3358. return;
  3359. }
  3360. var i = 0;
  3361. for (; i < result.length; i++) {
  3362. var exist = result[i].exist;
  3363. if (!result[i].option
  3364. // Existing model that already has id should be able to
  3365. // mapped to (because after mapping performed model may
  3366. // be assigned with a id, whish should not affect next
  3367. // mapping), except those has inner id.
  3368. && !modelUtil.isIdInner(exist)
  3369. // Caution:
  3370. // Do not overwrite id. But name can be overwritten,
  3371. // because axis use name as 'show label text'.
  3372. // 'exist' always has id and name and we dont
  3373. // need to check it.
  3374. && cptOption.id == null
  3375. ) {
  3376. result[i].option = cptOption;
  3377. break;
  3378. }
  3379. }
  3380. if (i >= result.length) {
  3381. result.push({option: cptOption});
  3382. }
  3383. });
  3384. return result;
  3385. };
  3386. /**
  3387. * Make id and name for mapping result (result of mappingToExists)
  3388. * into `keyInfo` field.
  3389. *
  3390. * @public
  3391. * @param {Array.<Object>} Result, like [{exist: ..., option: ...}, {}],
  3392. * which order is the same as exists.
  3393. * @return {Array.<Object>} The input.
  3394. */
  3395. modelUtil.makeIdAndName = function (mapResult) {
  3396. // We use this id to hash component models and view instances
  3397. // in echarts. id can be specified by user, or auto generated.
  3398. // The id generation rule ensures new view instance are able
  3399. // to mapped to old instance when setOption are called in
  3400. // no-merge mode. So we generate model id by name and plus
  3401. // type in view id.
  3402. // name can be duplicated among components, which is convenient
  3403. // to specify multi components (like series) by one name.
  3404. // Ensure that each id is distinct.
  3405. var idMap = zrUtil.createHashMap();
  3406. each(mapResult, function (item, index) {
  3407. var existCpt = item.exist;
  3408. existCpt && idMap.set(existCpt.id, item);
  3409. });
  3410. each(mapResult, function (item, index) {
  3411. var opt = item.option;
  3412. zrUtil.assert(
  3413. !opt || opt.id == null || !idMap.get(opt.id) || idMap.get(opt.id) === item,
  3414. 'id duplicates: ' + (opt && opt.id)
  3415. );
  3416. opt && opt.id != null && idMap.set(opt.id, item);
  3417. !item.keyInfo && (item.keyInfo = {});
  3418. });
  3419. // Make name and id.
  3420. each(mapResult, function (item, index) {
  3421. var existCpt = item.exist;
  3422. var opt = item.option;
  3423. var keyInfo = item.keyInfo;
  3424. if (!isObject(opt)) {
  3425. return;
  3426. }
  3427. // name can be overwitten. Consider case: axis.name = '20km'.
  3428. // But id generated by name will not be changed, which affect
  3429. // only in that case: setOption with 'not merge mode' and view
  3430. // instance will be recreated, which can be accepted.
  3431. keyInfo.name = opt.name != null
  3432. ? opt.name + ''
  3433. : existCpt
  3434. ? existCpt.name
  3435. : '\0-'; // name may be displayed on screen, so use '-'.
  3436. if (existCpt) {
  3437. keyInfo.id = existCpt.id;
  3438. }
  3439. else if (opt.id != null) {
  3440. keyInfo.id = opt.id + '';
  3441. }
  3442. else {
  3443. // Consider this situatoin:
  3444. // optionA: [{name: 'a'}, {name: 'a'}, {..}]
  3445. // optionB [{..}, {name: 'a'}, {name: 'a'}]
  3446. // Series with the same name between optionA and optionB
  3447. // should be mapped.
  3448. var idNum = 0;
  3449. do {
  3450. keyInfo.id = '\0' + keyInfo.name + '\0' + idNum++;
  3451. }
  3452. while (idMap.get(keyInfo.id));
  3453. }
  3454. idMap.set(keyInfo.id, item);
  3455. });
  3456. };
  3457. /**
  3458. * @public
  3459. * @param {Object} cptOption
  3460. * @return {boolean}
  3461. */
  3462. modelUtil.isIdInner = function (cptOption) {
  3463. return isObject(cptOption)
  3464. && cptOption.id
  3465. && (cptOption.id + '').indexOf('\0_ec_\0') === 0;
  3466. };
  3467. /**
  3468. * A helper for removing duplicate items between batchA and batchB,
  3469. * and in themselves, and categorize by series.
  3470. *
  3471. * @param {Array.<Object>} batchA Like: [{seriesId: 2, dataIndex: [32, 4, 5]}, ...]
  3472. * @param {Array.<Object>} batchB Like: [{seriesId: 2, dataIndex: [32, 4, 5]}, ...]
  3473. * @return {Array.<Array.<Object>, Array.<Object>>} result: [resultBatchA, resultBatchB]
  3474. */
  3475. modelUtil.compressBatches = function (batchA, batchB) {
  3476. var mapA = {};
  3477. var mapB = {};
  3478. makeMap(batchA || [], mapA);
  3479. makeMap(batchB || [], mapB, mapA);
  3480. return [mapToArray(mapA), mapToArray(mapB)];
  3481. function makeMap(sourceBatch, map, otherMap) {
  3482. for (var i = 0, len = sourceBatch.length; i < len; i++) {
  3483. var seriesId = sourceBatch[i].seriesId;
  3484. var dataIndices = modelUtil.normalizeToArray(sourceBatch[i].dataIndex);
  3485. var otherDataIndices = otherMap && otherMap[seriesId];
  3486. for (var j = 0, lenj = dataIndices.length; j < lenj; j++) {
  3487. var dataIndex = dataIndices[j];
  3488. if (otherDataIndices && otherDataIndices[dataIndex]) {
  3489. otherDataIndices[dataIndex] = null;
  3490. }
  3491. else {
  3492. (map[seriesId] || (map[seriesId] = {}))[dataIndex] = 1;
  3493. }
  3494. }
  3495. }
  3496. }
  3497. function mapToArray(map, isData) {
  3498. var result = [];
  3499. for (var i in map) {
  3500. if (map.hasOwnProperty(i) && map[i] != null) {
  3501. if (isData) {
  3502. result.push(+i);
  3503. }
  3504. else {
  3505. var dataIndices = mapToArray(map[i], true);
  3506. dataIndices.length && result.push({seriesId: i, dataIndex: dataIndices});
  3507. }
  3508. }
  3509. }
  3510. return result;
  3511. }
  3512. };
  3513. /**
  3514. * @param {module:echarts/data/List} data
  3515. * @param {Object} payload Contains dataIndex (means rawIndex) / dataIndexInside / name
  3516. * each of which can be Array or primary type.
  3517. * @return {number|Array.<number>} dataIndex If not found, return undefined/null.
  3518. */
  3519. modelUtil.queryDataIndex = function (data, payload) {
  3520. if (payload.dataIndexInside != null) {
  3521. return payload.dataIndexInside;
  3522. }
  3523. else if (payload.dataIndex != null) {
  3524. return zrUtil.isArray(payload.dataIndex)
  3525. ? zrUtil.map(payload.dataIndex, function (value) {
  3526. return data.indexOfRawIndex(value);
  3527. })
  3528. : data.indexOfRawIndex(payload.dataIndex);
  3529. }
  3530. else if (payload.name != null) {
  3531. return zrUtil.isArray(payload.name)
  3532. ? zrUtil.map(payload.name, function (value) {
  3533. return data.indexOfName(value);
  3534. })
  3535. : data.indexOfName(payload.name);
  3536. }
  3537. };
  3538. /**
  3539. * Enable property storage to any host object.
  3540. * Notice: Serialization is not supported.
  3541. *
  3542. * For example:
  3543. * var get = modelUitl.makeGetter();
  3544. *
  3545. * function some(hostObj) {
  3546. * get(hostObj)._someProperty = 1212;
  3547. * ...
  3548. * }
  3549. *
  3550. * @return {Function}
  3551. */
  3552. modelUtil.makeGetter = (function () {
  3553. var index = 0;
  3554. return function () {
  3555. var key = '\0__ec_prop_getter_' + index++;
  3556. return function (hostObj) {
  3557. return hostObj[key] || (hostObj[key] = {});
  3558. };
  3559. };
  3560. })();
  3561. /**
  3562. * @param {module:echarts/model/Global} ecModel
  3563. * @param {string|Object} finder
  3564. * If string, e.g., 'geo', means {geoIndex: 0}.
  3565. * If Object, could contain some of these properties below:
  3566. * {
  3567. * seriesIndex, seriesId, seriesName,
  3568. * geoIndex, geoId, geoName,
  3569. * bmapIndex, bmapId, bmapName,
  3570. * xAxisIndex, xAxisId, xAxisName,
  3571. * yAxisIndex, yAxisId, yAxisName,
  3572. * gridIndex, gridId, gridName,
  3573. * ... (can be extended)
  3574. * }
  3575. * Each properties can be number|string|Array.<number>|Array.<string>
  3576. * For example, a finder could be
  3577. * {
  3578. * seriesIndex: 3,
  3579. * geoId: ['aa', 'cc'],
  3580. * gridName: ['xx', 'rr']
  3581. * }
  3582. * xxxIndex can be set as 'all' (means all xxx) or 'none' (means not specify)
  3583. * If nothing or null/undefined specified, return nothing.
  3584. * @param {Object} [opt]
  3585. * @param {string} [opt.defaultMainType]
  3586. * @param {Array.<string>} [opt.includeMainTypes]
  3587. * @return {Object} result like:
  3588. * {
  3589. * seriesModels: [seriesModel1, seriesModel2],
  3590. * seriesModel: seriesModel1, // The first model
  3591. * geoModels: [geoModel1, geoModel2],
  3592. * geoModel: geoModel1, // The first model
  3593. * ...
  3594. * }
  3595. */
  3596. modelUtil.parseFinder = function (ecModel, finder, opt) {
  3597. if (zrUtil.isString(finder)) {
  3598. var obj = {};
  3599. obj[finder + 'Index'] = 0;
  3600. finder = obj;
  3601. }
  3602. var defaultMainType = opt && opt.defaultMainType;
  3603. if (defaultMainType
  3604. && !has(finder, defaultMainType + 'Index')
  3605. && !has(finder, defaultMainType + 'Id')
  3606. && !has(finder, defaultMainType + 'Name')
  3607. ) {
  3608. finder[defaultMainType + 'Index'] = 0;
  3609. }
  3610. var result = {};
  3611. each(finder, function (value, key) {
  3612. var value = finder[key];
  3613. // Exclude 'dataIndex' and other illgal keys.
  3614. if (key === 'dataIndex' || key === 'dataIndexInside') {
  3615. result[key] = value;
  3616. return;
  3617. }
  3618. var parsedKey = key.match(/^(\w+)(Index|Id|Name)$/) || [];
  3619. var mainType = parsedKey[1];
  3620. var queryType = (parsedKey[2] || '').toLowerCase();
  3621. if (!mainType
  3622. || !queryType
  3623. || value == null
  3624. || (queryType === 'index' && value === 'none')
  3625. || (opt && opt.includeMainTypes && zrUtil.indexOf(opt.includeMainTypes, mainType) < 0)
  3626. ) {
  3627. return;
  3628. }
  3629. var queryParam = {mainType: mainType};
  3630. if (queryType !== 'index' || value !== 'all') {
  3631. queryParam[queryType] = value;
  3632. }
  3633. var models = ecModel.queryComponents(queryParam);
  3634. result[mainType + 'Models'] = models;
  3635. result[mainType + 'Model'] = models[0];
  3636. });
  3637. return result;
  3638. };
  3639. /**
  3640. * @see {module:echarts/data/helper/completeDimensions}
  3641. * @param {module:echarts/data/List} data
  3642. * @param {string|number} dataDim
  3643. * @return {string}
  3644. */
  3645. modelUtil.dataDimToCoordDim = function (data, dataDim) {
  3646. var dimensions = data.dimensions;
  3647. dataDim = data.getDimension(dataDim);
  3648. for (var i = 0; i < dimensions.length; i++) {
  3649. var dimItem = data.getDimensionInfo(dimensions[i]);
  3650. if (dimItem.name === dataDim) {
  3651. return dimItem.coordDim;
  3652. }
  3653. }
  3654. };
  3655. /**
  3656. * @see {module:echarts/data/helper/completeDimensions}
  3657. * @param {module:echarts/data/List} data
  3658. * @param {string} coordDim
  3659. * @return {Array.<string>} data dimensions on the coordDim.
  3660. */
  3661. modelUtil.coordDimToDataDim = function (data, coordDim) {
  3662. var dataDim = [];
  3663. each(data.dimensions, function (dimName) {
  3664. var dimItem = data.getDimensionInfo(dimName);
  3665. if (dimItem.coordDim === coordDim) {
  3666. dataDim[dimItem.coordDimIndex] = dimItem.name;
  3667. }
  3668. });
  3669. return dataDim;
  3670. };
  3671. /**
  3672. * @see {module:echarts/data/helper/completeDimensions}
  3673. * @param {module:echarts/data/List} data
  3674. * @param {string} otherDim Can be `otherDims`
  3675. * like 'label' or 'tooltip'.
  3676. * @return {Array.<string>} data dimensions on the otherDim.
  3677. */
  3678. modelUtil.otherDimToDataDim = function (data, otherDim) {
  3679. var dataDim = [];
  3680. each(data.dimensions, function (dimName) {
  3681. var dimItem = data.getDimensionInfo(dimName);
  3682. var otherDims = dimItem.otherDims;
  3683. var dimIndex = otherDims[otherDim];
  3684. if (dimIndex != null && dimIndex !== false) {
  3685. dataDim[dimIndex] = dimItem.name;
  3686. }
  3687. });
  3688. return dataDim;
  3689. };
  3690. function has(obj, prop) {
  3691. return obj && obj.hasOwnProperty(prop);
  3692. }
  3693. module.exports = modelUtil;
  3694. /***/ },
  3695. /* 6 */
  3696. /***/ function(module, exports, __webpack_require__) {
  3697. var zrUtil = __webpack_require__(4);
  3698. var numberUtil = __webpack_require__(7);
  3699. var textContain = __webpack_require__(8);
  3700. var formatUtil = {};
  3701. /**
  3702. * 每三位默认加,格式化
  3703. * @param {string|number} x
  3704. * @return {string}
  3705. */
  3706. formatUtil.addCommas = function (x) {
  3707. if (isNaN(x)) {
  3708. return '-';
  3709. }
  3710. x = (x + '').split('.');
  3711. return x[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g,'$1,')
  3712. + (x.length > 1 ? ('.' + x[1]) : '');
  3713. };
  3714. /**
  3715. * @param {string} str
  3716. * @param {boolean} [upperCaseFirst=false]
  3717. * @return {string} str
  3718. */
  3719. formatUtil.toCamelCase = function (str, upperCaseFirst) {
  3720. str = (str || '').toLowerCase().replace(/-(.)/g, function(match, group1) {
  3721. return group1.toUpperCase();
  3722. });
  3723. if (upperCaseFirst && str) {
  3724. str = str.charAt(0).toUpperCase() + str.slice(1);
  3725. }
  3726. return str;
  3727. };
  3728. /**
  3729. * Normalize css liked array configuration
  3730. * e.g.
  3731. * 3 => [3, 3, 3, 3]
  3732. * [4, 2] => [4, 2, 4, 2]
  3733. * [4, 3, 2] => [4, 3, 2, 3]
  3734. * @param {number|Array.<number>} val
  3735. */
  3736. formatUtil.normalizeCssArray = function (val) {
  3737. var len = val.length;
  3738. if (typeof (val) === 'number') {
  3739. return [val, val, val, val];
  3740. }
  3741. else if (len === 2) {
  3742. // vertical | horizontal
  3743. return [val[0], val[1], val[0], val[1]];
  3744. }
  3745. else if (len === 3) {
  3746. // top | horizontal | bottom
  3747. return [val[0], val[1], val[2], val[1]];
  3748. }
  3749. return val;
  3750. };
  3751. var encodeHTML = formatUtil.encodeHTML = function (source) {
  3752. return String(source)
  3753. .replace(/&/g, '&amp;')
  3754. .replace(/</g, '&lt;')
  3755. .replace(/>/g, '&gt;')
  3756. .replace(/"/g, '&quot;')
  3757. .replace(/'/g, '&#39;');
  3758. };
  3759. var TPL_VAR_ALIAS = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
  3760. var wrapVar = function (varName, seriesIdx) {
  3761. return '{' + varName + (seriesIdx == null ? '' : seriesIdx) + '}';
  3762. };
  3763. /**
  3764. * Template formatter
  3765. * @param {string} tpl
  3766. * @param {Array.<Object>|Object} paramsList
  3767. * @param {boolean} [encode=false]
  3768. * @return {string}
  3769. */
  3770. formatUtil.formatTpl = function (tpl, paramsList, encode) {
  3771. if (!zrUtil.isArray(paramsList)) {
  3772. paramsList = [paramsList];
  3773. }
  3774. var seriesLen = paramsList.length;
  3775. if (!seriesLen) {
  3776. return '';
  3777. }
  3778. var $vars = paramsList[0].$vars || [];
  3779. for (var i = 0; i < $vars.length; i++) {
  3780. var alias = TPL_VAR_ALIAS[i];
  3781. var val = wrapVar(alias, 0);
  3782. tpl = tpl.replace(wrapVar(alias), encode ? encodeHTML(val) : val);
  3783. }
  3784. for (var seriesIdx = 0; seriesIdx < seriesLen; seriesIdx++) {
  3785. for (var k = 0; k < $vars.length; k++) {
  3786. var val = paramsList[seriesIdx][$vars[k]];
  3787. tpl = tpl.replace(
  3788. wrapVar(TPL_VAR_ALIAS[k], seriesIdx),
  3789. encode ? encodeHTML(val) : val
  3790. );
  3791. }
  3792. }
  3793. return tpl;
  3794. };
  3795. /**
  3796. * simple Template formatter
  3797. *
  3798. * @param {string} tpl
  3799. * @param {Object} param
  3800. * @param {boolean} [encode=false]
  3801. * @return {string}
  3802. */
  3803. formatUtil.formatTplSimple = function (tpl, param, encode) {
  3804. zrUtil.each(param, function (value, key) {
  3805. tpl = tpl.replace(
  3806. '{' + key + '}',
  3807. encode ? encodeHTML(value) : value
  3808. );
  3809. });
  3810. return tpl;
  3811. };
  3812. /**
  3813. * @param {string} color
  3814. * @param {string} [extraCssText]
  3815. * @return {string}
  3816. */
  3817. formatUtil.getTooltipMarker = function (color, extraCssText) {
  3818. return color
  3819. ? '<span style="display:inline-block;margin-right:5px;'
  3820. + 'border-radius:10px;width:9px;height:9px;background-color:'
  3821. + formatUtil.encodeHTML(color) + ';' + (extraCssText || '') + '"></span>'
  3822. : '';
  3823. };
  3824. /**
  3825. * @param {string} str
  3826. * @return {string}
  3827. * @inner
  3828. */
  3829. var s2d = function (str) {
  3830. return str < 10 ? ('0' + str) : str;
  3831. };
  3832. /**
  3833. * ISO Date format
  3834. * @param {string} tpl
  3835. * @param {number} value
  3836. * @param {boolean} [isUTC=false] Default in local time.
  3837. * see `module:echarts/scale/Time`
  3838. * and `module:echarts/util/number#parseDate`.
  3839. * @inner
  3840. */
  3841. formatUtil.formatTime = function (tpl, value, isUTC) {
  3842. if (tpl === 'week'
  3843. || tpl === 'month'
  3844. || tpl === 'quarter'
  3845. || tpl === 'half-year'
  3846. || tpl === 'year'
  3847. ) {
  3848. tpl = 'MM-dd\nyyyy';
  3849. }
  3850. var date = numberUtil.parseDate(value);
  3851. var utc = isUTC ? 'UTC' : '';
  3852. var y = date['get' + utc + 'FullYear']();
  3853. var M = date['get' + utc + 'Month']() + 1;
  3854. var d = date['get' + utc + 'Date']();
  3855. var h = date['get' + utc + 'Hours']();
  3856. var m = date['get' + utc + 'Minutes']();
  3857. var s = date['get' + utc + 'Seconds']();
  3858. tpl = tpl.replace('MM', s2d(M))
  3859. .toLowerCase()
  3860. .replace('yyyy', y)
  3861. .replace('yy', y % 100)
  3862. .replace('dd', s2d(d))
  3863. .replace('d', d)
  3864. .replace('hh', s2d(h))
  3865. .replace('h', h)
  3866. .replace('mm', s2d(m))
  3867. .replace('m', m)
  3868. .replace('ss', s2d(s))
  3869. .replace('s', s);
  3870. return tpl;
  3871. };
  3872. /**
  3873. * Capital first
  3874. * @param {string} str
  3875. * @return {string}
  3876. */
  3877. formatUtil.capitalFirst = function (str) {
  3878. return str ? str.charAt(0).toUpperCase() + str.substr(1) : str;
  3879. };
  3880. formatUtil.truncateText = textContain.truncateText;
  3881. module.exports = formatUtil;
  3882. /***/ },
  3883. /* 7 */
  3884. /***/ function(module, exports) {
  3885. /**
  3886. * 数值处理模块
  3887. * @module echarts/util/number
  3888. */
  3889. var number = {};
  3890. var RADIAN_EPSILON = 1e-4;
  3891. function _trim(str) {
  3892. return str.replace(/^\s+/, '').replace(/\s+$/, '');
  3893. }
  3894. /**
  3895. * Linear mapping a value from domain to range
  3896. * @memberOf module:echarts/util/number
  3897. * @param {(number|Array.<number>)} val
  3898. * @param {Array.<number>} domain Domain extent domain[0] can be bigger than domain[1]
  3899. * @param {Array.<number>} range Range extent range[0] can be bigger than range[1]
  3900. * @param {boolean} clamp
  3901. * @return {(number|Array.<number>}
  3902. */
  3903. number.linearMap = function (val, domain, range, clamp) {
  3904. var subDomain = domain[1] - domain[0];
  3905. var subRange = range[1] - range[0];
  3906. if (subDomain === 0) {
  3907. return subRange === 0
  3908. ? range[0]
  3909. : (range[0] + range[1]) / 2;
  3910. }
  3911. // Avoid accuracy problem in edge, such as
  3912. // 146.39 - 62.83 === 83.55999999999999.
  3913. // See echarts/test/ut/spec/util/number.js#linearMap#accuracyError
  3914. // It is a little verbose for efficiency considering this method
  3915. // is a hotspot.
  3916. if (clamp) {
  3917. if (subDomain > 0) {
  3918. if (val <= domain[0]) {
  3919. return range[0];
  3920. }
  3921. else if (val >= domain[1]) {
  3922. return range[1];
  3923. }
  3924. }
  3925. else {
  3926. if (val >= domain[0]) {
  3927. return range[0];
  3928. }
  3929. else if (val <= domain[1]) {
  3930. return range[1];
  3931. }
  3932. }
  3933. }
  3934. else {
  3935. if (val === domain[0]) {
  3936. return range[0];
  3937. }
  3938. if (val === domain[1]) {
  3939. return range[1];
  3940. }
  3941. }
  3942. return (val - domain[0]) / subDomain * subRange + range[0];
  3943. };
  3944. /**
  3945. * Convert a percent string to absolute number.
  3946. * Returns NaN if percent is not a valid string or number
  3947. * @memberOf module:echarts/util/number
  3948. * @param {string|number} percent
  3949. * @param {number} all
  3950. * @return {number}
  3951. */
  3952. number.parsePercent = function(percent, all) {
  3953. switch (percent) {
  3954. case 'center':
  3955. case 'middle':
  3956. percent = '50%';
  3957. break;
  3958. case 'left':
  3959. case 'top':
  3960. percent = '0%';
  3961. break;
  3962. case 'right':
  3963. case 'bottom':
  3964. percent = '100%';
  3965. break;
  3966. }
  3967. if (typeof percent === 'string') {
  3968. if (_trim(percent).match(/%$/)) {
  3969. return parseFloat(percent) / 100 * all;
  3970. }
  3971. return parseFloat(percent);
  3972. }
  3973. return percent == null ? NaN : +percent;
  3974. };
  3975. /**
  3976. * (1) Fix rounding error of float numbers.
  3977. * (2) Support return string to avoid scientific notation like '3.5e-7'.
  3978. *
  3979. * @param {number} x
  3980. * @param {number} [precision]
  3981. * @param {boolean} [returnStr]
  3982. * @return {number|string}
  3983. */
  3984. number.round = function (x, precision, returnStr) {
  3985. if (precision == null) {
  3986. precision = 10;
  3987. }
  3988. // Avoid range error
  3989. precision = Math.min(Math.max(0, precision), 20);
  3990. x = (+x).toFixed(precision);
  3991. return returnStr ? x : +x;
  3992. };
  3993. number.asc = function (arr) {
  3994. arr.sort(function (a, b) {
  3995. return a - b;
  3996. });
  3997. return arr;
  3998. };
  3999. /**
  4000. * Get precision
  4001. * @param {number} val
  4002. */
  4003. number.getPrecision = function (val) {
  4004. val = +val;
  4005. if (isNaN(val)) {
  4006. return 0;
  4007. }
  4008. // It is much faster than methods converting number to string as follows
  4009. // var tmp = val.toString();
  4010. // return tmp.length - 1 - tmp.indexOf('.');
  4011. // especially when precision is low
  4012. var e = 1;
  4013. var count = 0;
  4014. while (Math.round(val * e) / e !== val) {
  4015. e *= 10;
  4016. count++;
  4017. }
  4018. return count;
  4019. };
  4020. /**
  4021. * @param {string|number} val
  4022. * @return {number}
  4023. */
  4024. number.getPrecisionSafe = function (val) {
  4025. var str = val.toString();
  4026. // Consider scientific notation: '3.4e-12' '3.4e+12'
  4027. var eIndex = str.indexOf('e');
  4028. if (eIndex > 0) {
  4029. var precision = +str.slice(eIndex + 1);
  4030. return precision < 0 ? -precision : 0;
  4031. }
  4032. else {
  4033. var dotIndex = str.indexOf('.');
  4034. return dotIndex < 0 ? 0 : str.length - 1 - dotIndex;
  4035. }
  4036. };
  4037. /**
  4038. * Minimal dicernible data precisioin according to a single pixel.
  4039. *
  4040. * @param {Array.<number>} dataExtent
  4041. * @param {Array.<number>} pixelExtent
  4042. * @return {number} precision
  4043. */
  4044. number.getPixelPrecision = function (dataExtent, pixelExtent) {
  4045. var log = Math.log;
  4046. var LN10 = Math.LN10;
  4047. var dataQuantity = Math.floor(log(dataExtent[1] - dataExtent[0]) / LN10);
  4048. var sizeQuantity = Math.round(log(Math.abs(pixelExtent[1] - pixelExtent[0])) / LN10);
  4049. // toFixed() digits argument must be between 0 and 20.
  4050. var precision = Math.min(Math.max(-dataQuantity + sizeQuantity, 0), 20);
  4051. return !isFinite(precision) ? 20 : precision;
  4052. };
  4053. // Number.MAX_SAFE_INTEGER, ie do not support.
  4054. number.MAX_SAFE_INTEGER = 9007199254740991;
  4055. /**
  4056. * To 0 - 2 * PI, considering negative radian.
  4057. * @param {number} radian
  4058. * @return {number}
  4059. */
  4060. number.remRadian = function (radian) {
  4061. var pi2 = Math.PI * 2;
  4062. return (radian % pi2 + pi2) % pi2;
  4063. };
  4064. /**
  4065. * @param {type} radian
  4066. * @return {boolean}
  4067. */
  4068. number.isRadianAroundZero = function (val) {
  4069. return val > -RADIAN_EPSILON && val < RADIAN_EPSILON;
  4070. };
  4071. var TIME_REG = /^(?:(\d{4})(?:[-\/](\d{1,2})(?:[-\/](\d{1,2})(?:[T ](\d{1,2})(?::(\d\d)(?::(\d\d)(?:[.,](\d+))?)?)?(Z|[\+\-]\d\d:?\d\d)?)?)?)?)?$/; // jshint ignore:line
  4072. /**
  4073. * @return {number} in minutes
  4074. */
  4075. number.getTimezoneOffset = function () {
  4076. return (new Date()).getTimezoneOffset();
  4077. };
  4078. /**
  4079. * @param {string|Date|number} value These values can be accepted:
  4080. * + An instance of Date, represent a time in its own time zone.
  4081. * + Or string in a subset of ISO 8601, only including:
  4082. * + only year, month, date: '2012-03', '2012-03-01', '2012-03-01 05', '2012-03-01 05:06',
  4083. * + separated with T or space: '2012-03-01T12:22:33.123', '2012-03-01 12:22:33.123',
  4084. * + time zone: '2012-03-01T12:22:33Z', '2012-03-01T12:22:33+8000', '2012-03-01T12:22:33-05:00',
  4085. * all of which will be treated as local time if time zone is not specified
  4086. * (see <https://momentjs.com/>).
  4087. * + Or other string format, including (all of which will be treated as loacal time):
  4088. * '2012', '2012-3-1', '2012/3/1', '2012/03/01',
  4089. * '2009/6/12 2:00', '2009/6/12 2:05:08', '2009/6/12 2:05:08.123'
  4090. * + a timestamp, which represent a time in UTC.
  4091. * @return {Date} date
  4092. */
  4093. number.parseDate = function (value) {
  4094. if (value instanceof Date) {
  4095. return value;
  4096. }
  4097. else if (typeof value === 'string') {
  4098. // Different browsers parse date in different way, so we parse it manually.
  4099. // Some other issues:
  4100. // new Date('1970-01-01') is UTC,
  4101. // new Date('1970/01/01') and new Date('1970-1-01') is local.
  4102. // See issue #3623
  4103. var match = TIME_REG.exec(value);
  4104. if (!match) {
  4105. // return Invalid Date.
  4106. return new Date(NaN);
  4107. }
  4108. var timezoneOffset = number.getTimezoneOffset();
  4109. var timeOffset = !match[8]
  4110. ? 0
  4111. : match[8].toUpperCase() === 'Z'
  4112. ? timezoneOffset
  4113. : +match[8].slice(0, 3) * 60 + timezoneOffset;
  4114. // match[n] can only be string or undefined.
  4115. // But take care of '12' + 1 => '121'.
  4116. return new Date(
  4117. +match[1],
  4118. +(match[2] || 1) - 1,
  4119. +match[3] || 1,
  4120. +match[4] || 0,
  4121. +(match[5] || 0) - timeOffset,
  4122. +match[6] || 0,
  4123. +match[7] || 0
  4124. );
  4125. }
  4126. else if (value == null) {
  4127. return new Date(NaN);
  4128. }
  4129. return new Date(Math.round(value));
  4130. };
  4131. /**
  4132. * Quantity of a number. e.g. 0.1, 1, 10, 100
  4133. *
  4134. * @param {number} val
  4135. * @return {number}
  4136. */
  4137. number.quantity = function (val) {
  4138. return Math.pow(10, quantityExponent(val));
  4139. };
  4140. function quantityExponent(val) {
  4141. return Math.floor(Math.log(val) / Math.LN10);
  4142. }
  4143. /**
  4144. * find a “nice” number approximately equal to x. Round the number if round = true,
  4145. * take ceiling if round = false. The primary observation is that the “nicest”
  4146. * numbers in decimal are 1, 2, and 5, and all power-of-ten multiples of these numbers.
  4147. *
  4148. * See "Nice Numbers for Graph Labels" of Graphic Gems.
  4149. *
  4150. * @param {number} val Non-negative value.
  4151. * @param {boolean} round
  4152. * @return {number}
  4153. */
  4154. number.nice = function (val, round) {
  4155. var exponent = quantityExponent(val);
  4156. var exp10 = Math.pow(10, exponent);
  4157. var f = val / exp10; // 1 <= f < 10
  4158. var nf;
  4159. if (round) {
  4160. if (f < 1.5) { nf = 1; }
  4161. else if (f < 2.5) { nf = 2; }
  4162. else if (f < 4) { nf = 3; }
  4163. else if (f < 7) { nf = 5; }
  4164. else { nf = 10; }
  4165. }
  4166. else {
  4167. if (f < 1) { nf = 1; }
  4168. else if (f < 2) { nf = 2; }
  4169. else if (f < 3) { nf = 3; }
  4170. else if (f < 5) { nf = 5; }
  4171. else { nf = 10; }
  4172. }
  4173. val = nf * exp10;
  4174. // Fix 3 * 0.1 === 0.30000000000000004 issue (see IEEE 754).
  4175. // 20 is the uppper bound of toFixed.
  4176. return exponent >= -20 ? +val.toFixed(exponent < 0 ? -exponent : 0) : val;
  4177. };
  4178. /**
  4179. * Order intervals asc, and split them when overlap.
  4180. * expect(numberUtil.reformIntervals([
  4181. * {interval: [18, 62], close: [1, 1]},
  4182. * {interval: [-Infinity, -70], close: [0, 0]},
  4183. * {interval: [-70, -26], close: [1, 1]},
  4184. * {interval: [-26, 18], close: [1, 1]},
  4185. * {interval: [62, 150], close: [1, 1]},
  4186. * {interval: [106, 150], close: [1, 1]},
  4187. * {interval: [150, Infinity], close: [0, 0]}
  4188. * ])).toEqual([
  4189. * {interval: [-Infinity, -70], close: [0, 0]},
  4190. * {interval: [-70, -26], close: [1, 1]},
  4191. * {interval: [-26, 18], close: [0, 1]},
  4192. * {interval: [18, 62], close: [0, 1]},
  4193. * {interval: [62, 150], close: [0, 1]},
  4194. * {interval: [150, Infinity], close: [0, 0]}
  4195. * ]);
  4196. * @param {Array.<Object>} list, where `close` mean open or close
  4197. * of the interval, and Infinity can be used.
  4198. * @return {Array.<Object>} The origin list, which has been reformed.
  4199. */
  4200. number.reformIntervals = function (list) {
  4201. list.sort(function (a, b) {
  4202. return littleThan(a, b, 0) ? -1 : 1;
  4203. });
  4204. var curr = -Infinity;
  4205. var currClose = 1;
  4206. for (var i = 0; i < list.length;) {
  4207. var interval = list[i].interval;
  4208. var close = list[i].close;
  4209. for (var lg = 0; lg < 2; lg++) {
  4210. if (interval[lg] <= curr) {
  4211. interval[lg] = curr;
  4212. close[lg] = !lg ? 1 - currClose : 1;
  4213. }
  4214. curr = interval[lg];
  4215. currClose = close[lg];
  4216. }
  4217. if (interval[0] === interval[1] && close[0] * close[1] !== 1) {
  4218. list.splice(i, 1);
  4219. }
  4220. else {
  4221. i++;
  4222. }
  4223. }
  4224. return list;
  4225. function littleThan(a, b, lg) {
  4226. return a.interval[lg] < b.interval[lg]
  4227. || (
  4228. a.interval[lg] === b.interval[lg]
  4229. && (
  4230. (a.close[lg] - b.close[lg] === (!lg ? 1 : -1))
  4231. || (!lg && littleThan(a, b, 1))
  4232. )
  4233. );
  4234. }
  4235. };
  4236. /**
  4237. * parseFloat NaNs numeric-cast false positives (null|true|false|"")
  4238. * ...but misinterprets leading-number strings, particularly hex literals ("0x...")
  4239. * subtraction forces infinities to NaN
  4240. *
  4241. * @param {*} v
  4242. * @return {boolean}
  4243. */
  4244. number.isNumeric = function (v) {
  4245. return v - parseFloat(v) >= 0;
  4246. };
  4247. module.exports = number;
  4248. /***/ },
  4249. /* 8 */
  4250. /***/ function(module, exports, __webpack_require__) {
  4251. var textWidthCache = {};
  4252. var textWidthCacheCounter = 0;
  4253. var TEXT_CACHE_MAX = 5000;
  4254. var util = __webpack_require__(4);
  4255. var BoundingRect = __webpack_require__(9);
  4256. var retrieve = util.retrieve;
  4257. function getTextWidth(text, textFont) {
  4258. var key = text + ':' + textFont;
  4259. if (textWidthCache[key]) {
  4260. return textWidthCache[key];
  4261. }
  4262. var textLines = (text + '').split('\n');
  4263. var width = 0;
  4264. for (var i = 0, l = textLines.length; i < l; i++) {
  4265. // measureText 可以被覆盖以兼容不支持 Canvas 的环境
  4266. width = Math.max(textContain.measureText(textLines[i], textFont).width, width);
  4267. }
  4268. if (textWidthCacheCounter > TEXT_CACHE_MAX) {
  4269. textWidthCacheCounter = 0;
  4270. textWidthCache = {};
  4271. }
  4272. textWidthCacheCounter++;
  4273. textWidthCache[key] = width;
  4274. return width;
  4275. }
  4276. function getTextRect(text, textFont, textAlign, textBaseline) {
  4277. var textLineLen = ((text || '') + '').split('\n').length;
  4278. var width = getTextWidth(text, textFont);
  4279. // FIXME 高度计算比较粗暴
  4280. var lineHeight = getTextWidth('国', textFont);
  4281. var height = textLineLen * lineHeight;
  4282. var rect = new BoundingRect(0, 0, width, height);
  4283. // Text has a special line height property
  4284. rect.lineHeight = lineHeight;
  4285. switch (textBaseline) {
  4286. case 'bottom':
  4287. case 'alphabetic':
  4288. rect.y -= lineHeight;
  4289. break;
  4290. case 'middle':
  4291. rect.y -= lineHeight / 2;
  4292. break;
  4293. // case 'hanging':
  4294. // case 'top':
  4295. }
  4296. // FIXME Right to left language
  4297. switch (textAlign) {
  4298. case 'end':
  4299. case 'right':
  4300. rect.x -= rect.width;
  4301. break;
  4302. case 'center':
  4303. rect.x -= rect.width / 2;
  4304. break;
  4305. // case 'start':
  4306. // case 'left':
  4307. }
  4308. return rect;
  4309. }
  4310. function adjustTextPositionOnRect(textPosition, rect, textRect, distance) {
  4311. var x = rect.x;
  4312. var y = rect.y;
  4313. var height = rect.height;
  4314. var width = rect.width;
  4315. var textHeight = textRect.height;
  4316. var lineHeight = textRect.lineHeight;
  4317. var halfHeight = height / 2 - textHeight / 2 + lineHeight;
  4318. var textAlign = 'left';
  4319. switch (textPosition) {
  4320. case 'left':
  4321. x -= distance;
  4322. y += halfHeight;
  4323. textAlign = 'right';
  4324. break;
  4325. case 'right':
  4326. x += distance + width;
  4327. y += halfHeight;
  4328. textAlign = 'left';
  4329. break;
  4330. case 'top':
  4331. x += width / 2;
  4332. y -= distance + textHeight - lineHeight;
  4333. textAlign = 'center';
  4334. break;
  4335. case 'bottom':
  4336. x += width / 2;
  4337. y += height + distance + lineHeight;
  4338. textAlign = 'center';
  4339. break;
  4340. case 'inside':
  4341. x += width / 2;
  4342. y += halfHeight;
  4343. textAlign = 'center';
  4344. break;
  4345. case 'insideLeft':
  4346. x += distance;
  4347. y += halfHeight;
  4348. textAlign = 'left';
  4349. break;
  4350. case 'insideRight':
  4351. x += width - distance;
  4352. y += halfHeight;
  4353. textAlign = 'right';
  4354. break;
  4355. case 'insideTop':
  4356. x += width / 2;
  4357. y += distance + lineHeight;
  4358. textAlign = 'center';
  4359. break;
  4360. case 'insideBottom':
  4361. x += width / 2;
  4362. y += height - textHeight - distance + lineHeight;
  4363. textAlign = 'center';
  4364. break;
  4365. case 'insideTopLeft':
  4366. x += distance;
  4367. y += distance + lineHeight;
  4368. textAlign = 'left';
  4369. break;
  4370. case 'insideTopRight':
  4371. x += width - distance;
  4372. y += distance + lineHeight;
  4373. textAlign = 'right';
  4374. break;
  4375. case 'insideBottomLeft':
  4376. x += distance;
  4377. y += height - textHeight - distance + lineHeight;
  4378. break;
  4379. case 'insideBottomRight':
  4380. x += width - distance;
  4381. y += height - textHeight - distance + lineHeight;
  4382. textAlign = 'right';
  4383. break;
  4384. }
  4385. return {
  4386. x: x,
  4387. y: y,
  4388. textAlign: textAlign,
  4389. textBaseline: 'alphabetic'
  4390. };
  4391. }
  4392. /**
  4393. * Show ellipsis if overflow.
  4394. *
  4395. * @param {string} text
  4396. * @param {string} containerWidth
  4397. * @param {string} textFont
  4398. * @param {number} [ellipsis='...']
  4399. * @param {Object} [options]
  4400. * @param {number} [options.maxIterations=3]
  4401. * @param {number} [options.minChar=0] If truncate result are less
  4402. * then minChar, ellipsis will not show, which is
  4403. * better for user hint in some cases.
  4404. * @param {number} [options.placeholder=''] When all truncated, use the placeholder.
  4405. * @return {string}
  4406. */
  4407. function truncateText(text, containerWidth, textFont, ellipsis, options) {
  4408. if (!containerWidth) {
  4409. return '';
  4410. }
  4411. options = options || {};
  4412. ellipsis = retrieve(ellipsis, '...');
  4413. var maxIterations = retrieve(options.maxIterations, 2);
  4414. var minChar = retrieve(options.minChar, 0);
  4415. // FIXME
  4416. // Other languages?
  4417. var cnCharWidth = getTextWidth('国', textFont);
  4418. // FIXME
  4419. // Consider proportional font?
  4420. var ascCharWidth = getTextWidth('a', textFont);
  4421. var placeholder = retrieve(options.placeholder, '');
  4422. // Example 1: minChar: 3, text: 'asdfzxcv', truncate result: 'asdf', but not: 'a...'.
  4423. // Example 2: minChar: 3, text: '维度', truncate result: '维', but not: '...'.
  4424. var contentWidth = containerWidth = Math.max(0, containerWidth - 1); // Reserve some gap.
  4425. for (var i = 0; i < minChar && contentWidth >= ascCharWidth; i++) {
  4426. contentWidth -= ascCharWidth;
  4427. }
  4428. var ellipsisWidth = getTextWidth(ellipsis);
  4429. if (ellipsisWidth > contentWidth) {
  4430. ellipsis = '';
  4431. ellipsisWidth = 0;
  4432. }
  4433. contentWidth = containerWidth - ellipsisWidth;
  4434. var textLines = (text + '').split('\n');
  4435. for (var i = 0, len = textLines.length; i < len; i++) {
  4436. var textLine = textLines[i];
  4437. var lineWidth = getTextWidth(textLine, textFont);
  4438. if (lineWidth <= containerWidth) {
  4439. continue;
  4440. }
  4441. for (var j = 0;; j++) {
  4442. if (lineWidth <= contentWidth || j >= maxIterations) {
  4443. textLine += ellipsis;
  4444. break;
  4445. }
  4446. var subLength = j === 0
  4447. ? estimateLength(textLine, contentWidth, ascCharWidth, cnCharWidth)
  4448. : lineWidth > 0
  4449. ? Math.floor(textLine.length * contentWidth / lineWidth)
  4450. : 0;
  4451. textLine = textLine.substr(0, subLength);
  4452. lineWidth = getTextWidth(textLine, textFont);
  4453. }
  4454. if (textLine === '') {
  4455. textLine = placeholder;
  4456. }
  4457. textLines[i] = textLine;
  4458. }
  4459. return textLines.join('\n');
  4460. }
  4461. function estimateLength(text, contentWidth, ascCharWidth, cnCharWidth) {
  4462. var width = 0;
  4463. var i = 0;
  4464. for (var len = text.length; i < len && width < contentWidth; i++) {
  4465. var charCode = text.charCodeAt(i);
  4466. width += (0 <= charCode && charCode <= 127) ? ascCharWidth : cnCharWidth;
  4467. }
  4468. return i;
  4469. }
  4470. var textContain = {
  4471. getWidth: getTextWidth,
  4472. getBoundingRect: getTextRect,
  4473. adjustTextPositionOnRect: adjustTextPositionOnRect,
  4474. truncateText: truncateText,
  4475. measureText: function (text, textFont) {
  4476. var ctx = util.getContext();
  4477. ctx.font = textFont || '12px sans-serif';
  4478. return ctx.measureText(text);
  4479. }
  4480. };
  4481. module.exports = textContain;
  4482. /***/ },
  4483. /* 9 */
  4484. /***/ function(module, exports, __webpack_require__) {
  4485. 'use strict';
  4486. /**
  4487. * @module echarts/core/BoundingRect
  4488. */
  4489. var vec2 = __webpack_require__(10);
  4490. var matrix = __webpack_require__(11);
  4491. var v2ApplyTransform = vec2.applyTransform;
  4492. var mathMin = Math.min;
  4493. var mathMax = Math.max;
  4494. /**
  4495. * @alias module:echarts/core/BoundingRect
  4496. */
  4497. function BoundingRect(x, y, width, height) {
  4498. if (width < 0) {
  4499. x = x + width;
  4500. width = -width;
  4501. }
  4502. if (height < 0) {
  4503. y = y + height;
  4504. height = -height;
  4505. }
  4506. /**
  4507. * @type {number}
  4508. */
  4509. this.x = x;
  4510. /**
  4511. * @type {number}
  4512. */
  4513. this.y = y;
  4514. /**
  4515. * @type {number}
  4516. */
  4517. this.width = width;
  4518. /**
  4519. * @type {number}
  4520. */
  4521. this.height = height;
  4522. }
  4523. BoundingRect.prototype = {
  4524. constructor: BoundingRect,
  4525. /**
  4526. * @param {module:echarts/core/BoundingRect} other
  4527. */
  4528. union: function (other) {
  4529. var x = mathMin(other.x, this.x);
  4530. var y = mathMin(other.y, this.y);
  4531. this.width = mathMax(
  4532. other.x + other.width,
  4533. this.x + this.width
  4534. ) - x;
  4535. this.height = mathMax(
  4536. other.y + other.height,
  4537. this.y + this.height
  4538. ) - y;
  4539. this.x = x;
  4540. this.y = y;
  4541. },
  4542. /**
  4543. * @param {Array.<number>} m
  4544. * @methods
  4545. */
  4546. applyTransform: (function () {
  4547. var lt = [];
  4548. var rb = [];
  4549. var lb = [];
  4550. var rt = [];
  4551. return function (m) {
  4552. // In case usage like this
  4553. // el.getBoundingRect().applyTransform(el.transform)
  4554. // And element has no transform
  4555. if (!m) {
  4556. return;
  4557. }
  4558. lt[0] = lb[0] = this.x;
  4559. lt[1] = rt[1] = this.y;
  4560. rb[0] = rt[0] = this.x + this.width;
  4561. rb[1] = lb[1] = this.y + this.height;
  4562. v2ApplyTransform(lt, lt, m);
  4563. v2ApplyTransform(rb, rb, m);
  4564. v2ApplyTransform(lb, lb, m);
  4565. v2ApplyTransform(rt, rt, m);
  4566. this.x = mathMin(lt[0], rb[0], lb[0], rt[0]);
  4567. this.y = mathMin(lt[1], rb[1], lb[1], rt[1]);
  4568. var maxX = mathMax(lt[0], rb[0], lb[0], rt[0]);
  4569. var maxY = mathMax(lt[1], rb[1], lb[1], rt[1]);
  4570. this.width = maxX - this.x;
  4571. this.height = maxY - this.y;
  4572. };
  4573. })(),
  4574. /**
  4575. * Calculate matrix of transforming from self to target rect
  4576. * @param {module:zrender/core/BoundingRect} b
  4577. * @return {Array.<number>}
  4578. */
  4579. calculateTransform: function (b) {
  4580. var a = this;
  4581. var sx = b.width / a.width;
  4582. var sy = b.height / a.height;
  4583. var m = matrix.create();
  4584. // 矩阵右乘
  4585. matrix.translate(m, m, [-a.x, -a.y]);
  4586. matrix.scale(m, m, [sx, sy]);
  4587. matrix.translate(m, m, [b.x, b.y]);
  4588. return m;
  4589. },
  4590. /**
  4591. * @param {(module:echarts/core/BoundingRect|Object)} b
  4592. * @return {boolean}
  4593. */
  4594. intersect: function (b) {
  4595. if (!b) {
  4596. return false;
  4597. }
  4598. if (!(b instanceof BoundingRect)) {
  4599. // Normalize negative width/height.
  4600. b = BoundingRect.create(b);
  4601. }
  4602. var a = this;
  4603. var ax0 = a.x;
  4604. var ax1 = a.x + a.width;
  4605. var ay0 = a.y;
  4606. var ay1 = a.y + a.height;
  4607. var bx0 = b.x;
  4608. var bx1 = b.x + b.width;
  4609. var by0 = b.y;
  4610. var by1 = b.y + b.height;
  4611. return ! (ax1 < bx0 || bx1 < ax0 || ay1 < by0 || by1 < ay0);
  4612. },
  4613. contain: function (x, y) {
  4614. var rect = this;
  4615. return x >= rect.x
  4616. && x <= (rect.x + rect.width)
  4617. && y >= rect.y
  4618. && y <= (rect.y + rect.height);
  4619. },
  4620. /**
  4621. * @return {module:echarts/core/BoundingRect}
  4622. */
  4623. clone: function () {
  4624. return new BoundingRect(this.x, this.y, this.width, this.height);
  4625. },
  4626. /**
  4627. * Copy from another rect
  4628. */
  4629. copy: function (other) {
  4630. this.x = other.x;
  4631. this.y = other.y;
  4632. this.width = other.width;
  4633. this.height = other.height;
  4634. },
  4635. plain: function () {
  4636. return {
  4637. x: this.x,
  4638. y: this.y,
  4639. width: this.width,
  4640. height: this.height
  4641. };
  4642. }
  4643. };
  4644. /**
  4645. * @param {Object|module:zrender/core/BoundingRect} rect
  4646. * @param {number} rect.x
  4647. * @param {number} rect.y
  4648. * @param {number} rect.width
  4649. * @param {number} rect.height
  4650. * @return {module:zrender/core/BoundingRect}
  4651. */
  4652. BoundingRect.create = function (rect) {
  4653. return new BoundingRect(rect.x, rect.y, rect.width, rect.height);
  4654. };
  4655. module.exports = BoundingRect;
  4656. /***/ },
  4657. /* 10 */
  4658. /***/ function(module, exports) {
  4659. var ArrayCtor = typeof Float32Array === 'undefined'
  4660. ? Array
  4661. : Float32Array;
  4662. /**
  4663. * @typedef {Float32Array|Array.<number>} Vector2
  4664. */
  4665. /**
  4666. * 二维向量类
  4667. * @exports zrender/tool/vector
  4668. */
  4669. var vector = {
  4670. /**
  4671. * 创建一个向量
  4672. * @param {number} [x=0]
  4673. * @param {number} [y=0]
  4674. * @return {Vector2}
  4675. */
  4676. create: function (x, y) {
  4677. var out = new ArrayCtor(2);
  4678. if (x == null) {
  4679. x = 0;
  4680. }
  4681. if (y == null) {
  4682. y = 0;
  4683. }
  4684. out[0] = x;
  4685. out[1] = y;
  4686. return out;
  4687. },
  4688. /**
  4689. * 复制向量数据
  4690. * @param {Vector2} out
  4691. * @param {Vector2} v
  4692. * @return {Vector2}
  4693. */
  4694. copy: function (out, v) {
  4695. out[0] = v[0];
  4696. out[1] = v[1];
  4697. return out;
  4698. },
  4699. /**
  4700. * 克隆一个向量
  4701. * @param {Vector2} v
  4702. * @return {Vector2}
  4703. */
  4704. clone: function (v) {
  4705. var out = new ArrayCtor(2);
  4706. out[0] = v[0];
  4707. out[1] = v[1];
  4708. return out;
  4709. },
  4710. /**
  4711. * 设置向量的两个项
  4712. * @param {Vector2} out
  4713. * @param {number} a
  4714. * @param {number} b
  4715. * @return {Vector2} 结果
  4716. */
  4717. set: function (out, a, b) {
  4718. out[0] = a;
  4719. out[1] = b;
  4720. return out;
  4721. },
  4722. /**
  4723. * 向量相加
  4724. * @param {Vector2} out
  4725. * @param {Vector2} v1
  4726. * @param {Vector2} v2
  4727. */
  4728. add: function (out, v1, v2) {
  4729. out[0] = v1[0] + v2[0];
  4730. out[1] = v1[1] + v2[1];
  4731. return out;
  4732. },
  4733. /**
  4734. * 向量缩放后相加
  4735. * @param {Vector2} out
  4736. * @param {Vector2} v1
  4737. * @param {Vector2} v2
  4738. * @param {number} a
  4739. */
  4740. scaleAndAdd: function (out, v1, v2, a) {
  4741. out[0] = v1[0] + v2[0] * a;
  4742. out[1] = v1[1] + v2[1] * a;
  4743. return out;
  4744. },
  4745. /**
  4746. * 向量相减
  4747. * @param {Vector2} out
  4748. * @param {Vector2} v1
  4749. * @param {Vector2} v2
  4750. */
  4751. sub: function (out, v1, v2) {
  4752. out[0] = v1[0] - v2[0];
  4753. out[1] = v1[1] - v2[1];
  4754. return out;
  4755. },
  4756. /**
  4757. * 向量长度
  4758. * @param {Vector2} v
  4759. * @return {number}
  4760. */
  4761. len: function (v) {
  4762. return Math.sqrt(this.lenSquare(v));
  4763. },
  4764. /**
  4765. * 向量长度平方
  4766. * @param {Vector2} v
  4767. * @return {number}
  4768. */
  4769. lenSquare: function (v) {
  4770. return v[0] * v[0] + v[1] * v[1];
  4771. },
  4772. /**
  4773. * 向量乘法
  4774. * @param {Vector2} out
  4775. * @param {Vector2} v1
  4776. * @param {Vector2} v2
  4777. */
  4778. mul: function (out, v1, v2) {
  4779. out[0] = v1[0] * v2[0];
  4780. out[1] = v1[1] * v2[1];
  4781. return out;
  4782. },
  4783. /**
  4784. * 向量除法
  4785. * @param {Vector2} out
  4786. * @param {Vector2} v1
  4787. * @param {Vector2} v2
  4788. */
  4789. div: function (out, v1, v2) {
  4790. out[0] = v1[0] / v2[0];
  4791. out[1] = v1[1] / v2[1];
  4792. return out;
  4793. },
  4794. /**
  4795. * 向量点乘
  4796. * @param {Vector2} v1
  4797. * @param {Vector2} v2
  4798. * @return {number}
  4799. */
  4800. dot: function (v1, v2) {
  4801. return v1[0] * v2[0] + v1[1] * v2[1];
  4802. },
  4803. /**
  4804. * 向量缩放
  4805. * @param {Vector2} out
  4806. * @param {Vector2} v
  4807. * @param {number} s
  4808. */
  4809. scale: function (out, v, s) {
  4810. out[0] = v[0] * s;
  4811. out[1] = v[1] * s;
  4812. return out;
  4813. },
  4814. /**
  4815. * 向量归一化
  4816. * @param {Vector2} out
  4817. * @param {Vector2} v
  4818. */
  4819. normalize: function (out, v) {
  4820. var d = vector.len(v);
  4821. if (d === 0) {
  4822. out[0] = 0;
  4823. out[1] = 0;
  4824. }
  4825. else {
  4826. out[0] = v[0] / d;
  4827. out[1] = v[1] / d;
  4828. }
  4829. return out;
  4830. },
  4831. /**
  4832. * 计算向量间距离
  4833. * @param {Vector2} v1
  4834. * @param {Vector2} v2
  4835. * @return {number}
  4836. */
  4837. distance: function (v1, v2) {
  4838. return Math.sqrt(
  4839. (v1[0] - v2[0]) * (v1[0] - v2[0])
  4840. + (v1[1] - v2[1]) * (v1[1] - v2[1])
  4841. );
  4842. },
  4843. /**
  4844. * 向量距离平方
  4845. * @param {Vector2} v1
  4846. * @param {Vector2} v2
  4847. * @return {number}
  4848. */
  4849. distanceSquare: function (v1, v2) {
  4850. return (v1[0] - v2[0]) * (v1[0] - v2[0])
  4851. + (v1[1] - v2[1]) * (v1[1] - v2[1]);
  4852. },
  4853. /**
  4854. * 求负向量
  4855. * @param {Vector2} out
  4856. * @param {Vector2} v
  4857. */
  4858. negate: function (out, v) {
  4859. out[0] = -v[0];
  4860. out[1] = -v[1];
  4861. return out;
  4862. },
  4863. /**
  4864. * 插值两个点
  4865. * @param {Vector2} out
  4866. * @param {Vector2} v1
  4867. * @param {Vector2} v2
  4868. * @param {number} t
  4869. */
  4870. lerp: function (out, v1, v2, t) {
  4871. out[0] = v1[0] + t * (v2[0] - v1[0]);
  4872. out[1] = v1[1] + t * (v2[1] - v1[1]);
  4873. return out;
  4874. },
  4875. /**
  4876. * 矩阵左乘向量
  4877. * @param {Vector2} out
  4878. * @param {Vector2} v
  4879. * @param {Vector2} m
  4880. */
  4881. applyTransform: function (out, v, m) {
  4882. var x = v[0];
  4883. var y = v[1];
  4884. out[0] = m[0] * x + m[2] * y + m[4];
  4885. out[1] = m[1] * x + m[3] * y + m[5];
  4886. return out;
  4887. },
  4888. /**
  4889. * 求两个向量最小值
  4890. * @param {Vector2} out
  4891. * @param {Vector2} v1
  4892. * @param {Vector2} v2
  4893. */
  4894. min: function (out, v1, v2) {
  4895. out[0] = Math.min(v1[0], v2[0]);
  4896. out[1] = Math.min(v1[1], v2[1]);
  4897. return out;
  4898. },
  4899. /**
  4900. * 求两个向量最大值
  4901. * @param {Vector2} out
  4902. * @param {Vector2} v1
  4903. * @param {Vector2} v2
  4904. */
  4905. max: function (out, v1, v2) {
  4906. out[0] = Math.max(v1[0], v2[0]);
  4907. out[1] = Math.max(v1[1], v2[1]);
  4908. return out;
  4909. }
  4910. };
  4911. vector.length = vector.len;
  4912. vector.lengthSquare = vector.lenSquare;
  4913. vector.dist = vector.distance;
  4914. vector.distSquare = vector.distanceSquare;
  4915. module.exports = vector;
  4916. /***/ },
  4917. /* 11 */
  4918. /***/ function(module, exports) {
  4919. var ArrayCtor = typeof Float32Array === 'undefined'
  4920. ? Array
  4921. : Float32Array;
  4922. /**
  4923. * 3x2矩阵操作类
  4924. * @exports zrender/tool/matrix
  4925. */
  4926. var matrix = {
  4927. /**
  4928. * 创建一个单位矩阵
  4929. * @return {Float32Array|Array.<number>}
  4930. */
  4931. create : function() {
  4932. var out = new ArrayCtor(6);
  4933. matrix.identity(out);
  4934. return out;
  4935. },
  4936. /**
  4937. * 设置矩阵为单位矩阵
  4938. * @param {Float32Array|Array.<number>} out
  4939. */
  4940. identity : function(out) {
  4941. out[0] = 1;
  4942. out[1] = 0;
  4943. out[2] = 0;
  4944. out[3] = 1;
  4945. out[4] = 0;
  4946. out[5] = 0;
  4947. return out;
  4948. },
  4949. /**
  4950. * 复制矩阵
  4951. * @param {Float32Array|Array.<number>} out
  4952. * @param {Float32Array|Array.<number>} m
  4953. */
  4954. copy: function(out, m) {
  4955. out[0] = m[0];
  4956. out[1] = m[1];
  4957. out[2] = m[2];
  4958. out[3] = m[3];
  4959. out[4] = m[4];
  4960. out[5] = m[5];
  4961. return out;
  4962. },
  4963. /**
  4964. * 矩阵相乘
  4965. * @param {Float32Array|Array.<number>} out
  4966. * @param {Float32Array|Array.<number>} m1
  4967. * @param {Float32Array|Array.<number>} m2
  4968. */
  4969. mul : function (out, m1, m2) {
  4970. // Consider matrix.mul(m, m2, m);
  4971. // where out is the same as m2.
  4972. // So use temp variable to escape error.
  4973. var out0 = m1[0] * m2[0] + m1[2] * m2[1];
  4974. var out1 = m1[1] * m2[0] + m1[3] * m2[1];
  4975. var out2 = m1[0] * m2[2] + m1[2] * m2[3];
  4976. var out3 = m1[1] * m2[2] + m1[3] * m2[3];
  4977. var out4 = m1[0] * m2[4] + m1[2] * m2[5] + m1[4];
  4978. var out5 = m1[1] * m2[4] + m1[3] * m2[5] + m1[5];
  4979. out[0] = out0;
  4980. out[1] = out1;
  4981. out[2] = out2;
  4982. out[3] = out3;
  4983. out[4] = out4;
  4984. out[5] = out5;
  4985. return out;
  4986. },
  4987. /**
  4988. * 平移变换
  4989. * @param {Float32Array|Array.<number>} out
  4990. * @param {Float32Array|Array.<number>} a
  4991. * @param {Float32Array|Array.<number>} v
  4992. */
  4993. translate : function(out, a, v) {
  4994. out[0] = a[0];
  4995. out[1] = a[1];
  4996. out[2] = a[2];
  4997. out[3] = a[3];
  4998. out[4] = a[4] + v[0];
  4999. out[5] = a[5] + v[1];
  5000. return out;
  5001. },
  5002. /**
  5003. * 旋转变换
  5004. * @param {Float32Array|Array.<number>} out
  5005. * @param {Float32Array|Array.<number>} a
  5006. * @param {number} rad
  5007. */
  5008. rotate : function(out, a, rad) {
  5009. var aa = a[0];
  5010. var ac = a[2];
  5011. var atx = a[4];
  5012. var ab = a[1];
  5013. var ad = a[3];
  5014. var aty = a[5];
  5015. var st = Math.sin(rad);
  5016. var ct = Math.cos(rad);
  5017. out[0] = aa * ct + ab * st;
  5018. out[1] = -aa * st + ab * ct;
  5019. out[2] = ac * ct + ad * st;
  5020. out[3] = -ac * st + ct * ad;
  5021. out[4] = ct * atx + st * aty;
  5022. out[5] = ct * aty - st * atx;
  5023. return out;
  5024. },
  5025. /**
  5026. * 缩放变换
  5027. * @param {Float32Array|Array.<number>} out
  5028. * @param {Float32Array|Array.<number>} a
  5029. * @param {Float32Array|Array.<number>} v
  5030. */
  5031. scale : function(out, a, v) {
  5032. var vx = v[0];
  5033. var vy = v[1];
  5034. out[0] = a[0] * vx;
  5035. out[1] = a[1] * vy;
  5036. out[2] = a[2] * vx;
  5037. out[3] = a[3] * vy;
  5038. out[4] = a[4] * vx;
  5039. out[5] = a[5] * vy;
  5040. return out;
  5041. },
  5042. /**
  5043. * 求逆矩阵
  5044. * @param {Float32Array|Array.<number>} out
  5045. * @param {Float32Array|Array.<number>} a
  5046. */
  5047. invert : function(out, a) {
  5048. var aa = a[0];
  5049. var ac = a[2];
  5050. var atx = a[4];
  5051. var ab = a[1];
  5052. var ad = a[3];
  5053. var aty = a[5];
  5054. var det = aa * ad - ab * ac;
  5055. if (!det) {
  5056. return null;
  5057. }
  5058. det = 1.0 / det;
  5059. out[0] = ad * det;
  5060. out[1] = -ab * det;
  5061. out[2] = -ac * det;
  5062. out[3] = aa * det;
  5063. out[4] = (ac * aty - ad * atx) * det;
  5064. out[5] = (ab * atx - aa * aty) * det;
  5065. return out;
  5066. }
  5067. };
  5068. module.exports = matrix;
  5069. /***/ },
  5070. /* 12 */
  5071. /***/ function(module, exports, __webpack_require__) {
  5072. /**
  5073. * @module echarts/model/Model
  5074. */
  5075. var zrUtil = __webpack_require__(4);
  5076. var clazzUtil = __webpack_require__(13);
  5077. var env = __webpack_require__(2);
  5078. /**
  5079. * @alias module:echarts/model/Model
  5080. * @constructor
  5081. * @param {Object} option
  5082. * @param {module:echarts/model/Model} [parentModel]
  5083. * @param {module:echarts/model/Global} [ecModel]
  5084. */
  5085. function Model(option, parentModel, ecModel) {
  5086. /**
  5087. * @type {module:echarts/model/Model}
  5088. * @readOnly
  5089. */
  5090. this.parentModel = parentModel;
  5091. /**
  5092. * @type {module:echarts/model/Global}
  5093. * @readOnly
  5094. */
  5095. this.ecModel = ecModel;
  5096. /**
  5097. * @type {Object}
  5098. * @protected
  5099. */
  5100. this.option = option;
  5101. // Simple optimization
  5102. // if (this.init) {
  5103. // if (arguments.length <= 4) {
  5104. // this.init(option, parentModel, ecModel, extraOpt);
  5105. // }
  5106. // else {
  5107. // this.init.apply(this, arguments);
  5108. // }
  5109. // }
  5110. }
  5111. Model.prototype = {
  5112. constructor: Model,
  5113. /**
  5114. * Model 的初始化函数
  5115. * @param {Object} option
  5116. */
  5117. init: null,
  5118. /**
  5119. * 从新的 Option merge
  5120. */
  5121. mergeOption: function (option) {
  5122. zrUtil.merge(this.option, option, true);
  5123. },
  5124. /**
  5125. * @param {string|Array.<string>} path
  5126. * @param {boolean} [ignoreParent=false]
  5127. * @return {*}
  5128. */
  5129. get: function (path, ignoreParent) {
  5130. if (path == null) {
  5131. return this.option;
  5132. }
  5133. return doGet(
  5134. this.option,
  5135. this.parsePath(path),
  5136. !ignoreParent && getParent(this, path)
  5137. );
  5138. },
  5139. /**
  5140. * @param {string} key
  5141. * @param {boolean} [ignoreParent=false]
  5142. * @return {*}
  5143. */
  5144. getShallow: function (key, ignoreParent) {
  5145. var option = this.option;
  5146. var val = option == null ? option : option[key];
  5147. var parentModel = !ignoreParent && getParent(this, key);
  5148. if (val == null && parentModel) {
  5149. val = parentModel.getShallow(key);
  5150. }
  5151. return val;
  5152. },
  5153. /**
  5154. * @param {string|Array.<string>} path
  5155. * @param {module:echarts/model/Model} [parentModel]
  5156. * @return {module:echarts/model/Model}
  5157. */
  5158. getModel: function (path, parentModel) {
  5159. var obj = path == null
  5160. ? this.option
  5161. : doGet(this.option, path = this.parsePath(path));
  5162. var thisParentModel;
  5163. parentModel = parentModel || (
  5164. (thisParentModel = getParent(this, path))
  5165. && thisParentModel.getModel(path)
  5166. );
  5167. return new Model(obj, parentModel, this.ecModel);
  5168. },
  5169. /**
  5170. * If model has option
  5171. */
  5172. isEmpty: function () {
  5173. return this.option == null;
  5174. },
  5175. restoreData: function () {},
  5176. // Pending
  5177. clone: function () {
  5178. var Ctor = this.constructor;
  5179. return new Ctor(zrUtil.clone(this.option));
  5180. },
  5181. setReadOnly: function (properties) {
  5182. clazzUtil.setReadOnly(this, properties);
  5183. },
  5184. // If path is null/undefined, return null/undefined.
  5185. parsePath: function(path) {
  5186. if (typeof path === 'string') {
  5187. path = path.split('.');
  5188. }
  5189. return path;
  5190. },
  5191. /**
  5192. * @param {Function} getParentMethod
  5193. * param {Array.<string>|string} path
  5194. * return {module:echarts/model/Model}
  5195. */
  5196. customizeGetParent: function (getParentMethod) {
  5197. clazzUtil.set(this, 'getParent', getParentMethod);
  5198. },
  5199. isAnimationEnabled: function () {
  5200. if (!env.node) {
  5201. if (this.option.animation != null) {
  5202. return !!this.option.animation;
  5203. }
  5204. else if (this.parentModel) {
  5205. return this.parentModel.isAnimationEnabled();
  5206. }
  5207. }
  5208. }
  5209. };
  5210. function doGet(obj, pathArr, parentModel) {
  5211. for (var i = 0; i < pathArr.length; i++) {
  5212. // Ignore empty
  5213. if (!pathArr[i]) {
  5214. continue;
  5215. }
  5216. // obj could be number/string/... (like 0)
  5217. obj = (obj && typeof obj === 'object') ? obj[pathArr[i]] : null;
  5218. if (obj == null) {
  5219. break;
  5220. }
  5221. }
  5222. if (obj == null && parentModel) {
  5223. obj = parentModel.get(pathArr);
  5224. }
  5225. return obj;
  5226. }
  5227. function getParent(model, path) {
  5228. var getParentMethod = clazzUtil.get(model, 'getParent');
  5229. return getParentMethod ? getParentMethod.call(model, path) : model.parentModel;
  5230. }
  5231. // Enable Model.extend.
  5232. clazzUtil.enableClassExtend(Model);
  5233. var mixin = zrUtil.mixin;
  5234. mixin(Model, __webpack_require__(14));
  5235. mixin(Model, __webpack_require__(16));
  5236. mixin(Model, __webpack_require__(17));
  5237. mixin(Model, __webpack_require__(68));
  5238. module.exports = Model;
  5239. /***/ },
  5240. /* 13 */
  5241. /***/ function(module, exports, __webpack_require__) {
  5242. var zrUtil = __webpack_require__(4);
  5243. var clazz = {};
  5244. var TYPE_DELIMITER = '.';
  5245. var IS_CONTAINER = '___EC__COMPONENT__CONTAINER___';
  5246. var MEMBER_PRIFIX = '\0ec_\0';
  5247. /**
  5248. * Hide private class member.
  5249. * The same behavior as `host[name] = value;` (can be right-value)
  5250. * @public
  5251. */
  5252. clazz.set = function (host, name, value) {
  5253. return (host[MEMBER_PRIFIX + name] = value);
  5254. };
  5255. /**
  5256. * Hide private class member.
  5257. * The same behavior as `host[name];`
  5258. * @public
  5259. */
  5260. clazz.get = function (host, name) {
  5261. return host[MEMBER_PRIFIX + name];
  5262. };
  5263. /**
  5264. * For hidden private class member.
  5265. * The same behavior as `host.hasOwnProperty(name);`
  5266. * @public
  5267. */
  5268. clazz.hasOwn = function (host, name) {
  5269. return host.hasOwnProperty(MEMBER_PRIFIX + name);
  5270. };
  5271. /**
  5272. * Notice, parseClassType('') should returns {main: '', sub: ''}
  5273. * @public
  5274. */
  5275. var parseClassType = clazz.parseClassType = function (componentType) {
  5276. var ret = {main: '', sub: ''};
  5277. if (componentType) {
  5278. componentType = componentType.split(TYPE_DELIMITER);
  5279. ret.main = componentType[0] || '';
  5280. ret.sub = componentType[1] || '';
  5281. }
  5282. return ret;
  5283. };
  5284. /**
  5285. * @public
  5286. */
  5287. function checkClassType(componentType) {
  5288. zrUtil.assert(
  5289. /^[a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)?$/.test(componentType),
  5290. 'componentType "' + componentType + '" illegal'
  5291. );
  5292. }
  5293. /**
  5294. * @public
  5295. */
  5296. clazz.enableClassExtend = function (RootClass, mandatoryMethods) {
  5297. RootClass.$constructor = RootClass;
  5298. RootClass.extend = function (proto) {
  5299. if (true) {
  5300. zrUtil.each(mandatoryMethods, function (method) {
  5301. if (!proto[method]) {
  5302. console.warn(
  5303. 'Method `' + method + '` should be implemented'
  5304. + (proto.type ? ' in ' + proto.type : '') + '.'
  5305. );
  5306. }
  5307. });
  5308. }
  5309. var superClass = this;
  5310. var ExtendedClass = function () {
  5311. if (!proto.$constructor) {
  5312. superClass.apply(this, arguments);
  5313. }
  5314. else {
  5315. proto.$constructor.apply(this, arguments);
  5316. }
  5317. };
  5318. zrUtil.extend(ExtendedClass.prototype, proto);
  5319. ExtendedClass.extend = this.extend;
  5320. ExtendedClass.superCall = superCall;
  5321. ExtendedClass.superApply = superApply;
  5322. zrUtil.inherits(ExtendedClass, this);
  5323. ExtendedClass.superClass = superClass;
  5324. return ExtendedClass;
  5325. };
  5326. };
  5327. // superCall should have class info, which can not be fetch from 'this'.
  5328. // Consider this case:
  5329. // class A has method f,
  5330. // class B inherits class A, overrides method f, f call superApply('f'),
  5331. // class C inherits class B, do not overrides method f,
  5332. // then when method of class C is called, dead loop occured.
  5333. function superCall(context, methodName) {
  5334. var args = zrUtil.slice(arguments, 2);
  5335. return this.superClass.prototype[methodName].apply(context, args);
  5336. }
  5337. function superApply(context, methodName, args) {
  5338. return this.superClass.prototype[methodName].apply(context, args);
  5339. }
  5340. /**
  5341. * @param {Object} entity
  5342. * @param {Object} options
  5343. * @param {boolean} [options.registerWhenExtend]
  5344. * @public
  5345. */
  5346. clazz.enableClassManagement = function (entity, options) {
  5347. options = options || {};
  5348. /**
  5349. * Component model classes
  5350. * key: componentType,
  5351. * value:
  5352. * componentClass, when componentType is 'xxx'
  5353. * or Object.<subKey, componentClass>, when componentType is 'xxx.yy'
  5354. * @type {Object}
  5355. */
  5356. var storage = {};
  5357. entity.registerClass = function (Clazz, componentType) {
  5358. if (componentType) {
  5359. checkClassType(componentType);
  5360. componentType = parseClassType(componentType);
  5361. if (!componentType.sub) {
  5362. if (true) {
  5363. if (storage[componentType.main]) {
  5364. console.warn(componentType.main + ' exists.');
  5365. }
  5366. }
  5367. storage[componentType.main] = Clazz;
  5368. }
  5369. else if (componentType.sub !== IS_CONTAINER) {
  5370. var container = makeContainer(componentType);
  5371. container[componentType.sub] = Clazz;
  5372. }
  5373. }
  5374. return Clazz;
  5375. };
  5376. entity.getClass = function (componentMainType, subType, throwWhenNotFound) {
  5377. var Clazz = storage[componentMainType];
  5378. if (Clazz && Clazz[IS_CONTAINER]) {
  5379. Clazz = subType ? Clazz[subType] : null;
  5380. }
  5381. if (throwWhenNotFound && !Clazz) {
  5382. throw new Error(
  5383. !subType
  5384. ? componentMainType + '.' + 'type should be specified.'
  5385. : 'Component ' + componentMainType + '.' + (subType || '') + ' not exists. Load it first.'
  5386. );
  5387. }
  5388. return Clazz;
  5389. };
  5390. entity.getClassesByMainType = function (componentType) {
  5391. componentType = parseClassType(componentType);
  5392. var result = [];
  5393. var obj = storage[componentType.main];
  5394. if (obj && obj[IS_CONTAINER]) {
  5395. zrUtil.each(obj, function (o, type) {
  5396. type !== IS_CONTAINER && result.push(o);
  5397. });
  5398. }
  5399. else {
  5400. result.push(obj);
  5401. }
  5402. return result;
  5403. };
  5404. entity.hasClass = function (componentType) {
  5405. // Just consider componentType.main.
  5406. componentType = parseClassType(componentType);
  5407. return !!storage[componentType.main];
  5408. };
  5409. /**
  5410. * @return {Array.<string>} Like ['aa', 'bb'], but can not be ['aa.xx']
  5411. */
  5412. entity.getAllClassMainTypes = function () {
  5413. var types = [];
  5414. zrUtil.each(storage, function (obj, type) {
  5415. types.push(type);
  5416. });
  5417. return types;
  5418. };
  5419. /**
  5420. * If a main type is container and has sub types
  5421. * @param {string} mainType
  5422. * @return {boolean}
  5423. */
  5424. entity.hasSubTypes = function (componentType) {
  5425. componentType = parseClassType(componentType);
  5426. var obj = storage[componentType.main];
  5427. return obj && obj[IS_CONTAINER];
  5428. };
  5429. entity.parseClassType = parseClassType;
  5430. function makeContainer(componentType) {
  5431. var container = storage[componentType.main];
  5432. if (!container || !container[IS_CONTAINER]) {
  5433. container = storage[componentType.main] = {};
  5434. container[IS_CONTAINER] = true;
  5435. }
  5436. return container;
  5437. }
  5438. if (options.registerWhenExtend) {
  5439. var originalExtend = entity.extend;
  5440. if (originalExtend) {
  5441. entity.extend = function (proto) {
  5442. var ExtendedClass = originalExtend.call(this, proto);
  5443. return entity.registerClass(ExtendedClass, proto.type);
  5444. };
  5445. }
  5446. }
  5447. return entity;
  5448. };
  5449. /**
  5450. * @param {string|Array.<string>} properties
  5451. */
  5452. clazz.setReadOnly = function (obj, properties) {
  5453. // FIXME It seems broken in IE8 simulation of IE11
  5454. // if (!zrUtil.isArray(properties)) {
  5455. // properties = properties != null ? [properties] : [];
  5456. // }
  5457. // zrUtil.each(properties, function (prop) {
  5458. // var value = obj[prop];
  5459. // Object.defineProperty
  5460. // && Object.defineProperty(obj, prop, {
  5461. // value: value, writable: false
  5462. // });
  5463. // zrUtil.isArray(obj[prop])
  5464. // && Object.freeze
  5465. // && Object.freeze(obj[prop]);
  5466. // });
  5467. };
  5468. module.exports = clazz;
  5469. /***/ },
  5470. /* 14 */
  5471. /***/ function(module, exports, __webpack_require__) {
  5472. var getLineStyle = __webpack_require__(15)(
  5473. [
  5474. ['lineWidth', 'width'],
  5475. ['stroke', 'color'],
  5476. ['opacity'],
  5477. ['shadowBlur'],
  5478. ['shadowOffsetX'],
  5479. ['shadowOffsetY'],
  5480. ['shadowColor']
  5481. ]
  5482. );
  5483. module.exports = {
  5484. getLineStyle: function (excludes) {
  5485. var style = getLineStyle.call(this, excludes);
  5486. var lineDash = this.getLineDash(style.lineWidth);
  5487. lineDash && (style.lineDash = lineDash);
  5488. return style;
  5489. },
  5490. getLineDash: function (lineWidth) {
  5491. if (lineWidth == null) {
  5492. lineWidth = 1;
  5493. }
  5494. var lineType = this.get('type');
  5495. var dotSize = Math.max(lineWidth, 2);
  5496. var dashSize = lineWidth * 4;
  5497. return (lineType === 'solid' || lineType == null) ? null
  5498. : (lineType === 'dashed' ? [dashSize, dashSize] : [dotSize, dotSize]);
  5499. }
  5500. };
  5501. /***/ },
  5502. /* 15 */
  5503. /***/ function(module, exports, __webpack_require__) {
  5504. // TODO Parse shadow style
  5505. // TODO Only shallow path support
  5506. var zrUtil = __webpack_require__(4);
  5507. module.exports = function (properties) {
  5508. // Normalize
  5509. for (var i = 0; i < properties.length; i++) {
  5510. if (!properties[i][1]) {
  5511. properties[i][1] = properties[i][0];
  5512. }
  5513. }
  5514. return function (excludes, includes) {
  5515. var style = {};
  5516. for (var i = 0; i < properties.length; i++) {
  5517. var propName = properties[i][1];
  5518. if ((excludes && zrUtil.indexOf(excludes, propName) >= 0)
  5519. || (includes && zrUtil.indexOf(includes, propName) < 0)
  5520. ) {
  5521. continue;
  5522. }
  5523. var val = this.getShallow(propName);
  5524. if (val != null) {
  5525. style[properties[i][0]] = val;
  5526. }
  5527. }
  5528. return style;
  5529. };
  5530. };
  5531. /***/ },
  5532. /* 16 */
  5533. /***/ function(module, exports, __webpack_require__) {
  5534. module.exports = {
  5535. getAreaStyle: __webpack_require__(15)(
  5536. [
  5537. ['fill', 'color'],
  5538. ['shadowBlur'],
  5539. ['shadowOffsetX'],
  5540. ['shadowOffsetY'],
  5541. ['opacity'],
  5542. ['shadowColor']
  5543. ]
  5544. )
  5545. };
  5546. /***/ },
  5547. /* 17 */
  5548. /***/ function(module, exports, __webpack_require__) {
  5549. var textContain = __webpack_require__(8);
  5550. var graphicUtil = __webpack_require__(18);
  5551. module.exports = {
  5552. /**
  5553. * Get color property or get color from option.textStyle.color
  5554. * @return {string}
  5555. */
  5556. getTextColor: function () {
  5557. var ecModel = this.ecModel;
  5558. return this.getShallow('color')
  5559. || (ecModel && ecModel.get('textStyle.color'));
  5560. },
  5561. /**
  5562. * Create font string from fontStyle, fontWeight, fontSize, fontFamily
  5563. * @return {string}
  5564. */
  5565. getFont: function () {
  5566. return graphicUtil.getFont({
  5567. fontStyle: this.getShallow('fontStyle'),
  5568. fontWeight: this.getShallow('fontWeight'),
  5569. fontSize: this.getShallow('fontSize'),
  5570. fontFamily: this.getShallow('fontFamily')
  5571. }, this.ecModel);
  5572. },
  5573. getTextRect: function (text) {
  5574. return textContain.getBoundingRect(
  5575. text,
  5576. this.getFont(),
  5577. this.getShallow('align'),
  5578. this.getShallow('baseline')
  5579. );
  5580. },
  5581. truncateText: function (text, containerWidth, ellipsis, options) {
  5582. return textContain.truncateText(
  5583. text, containerWidth, this.getFont(), ellipsis, options
  5584. );
  5585. }
  5586. };
  5587. /***/ },
  5588. /* 18 */
  5589. /***/ function(module, exports, __webpack_require__) {
  5590. 'use strict';
  5591. var zrUtil = __webpack_require__(4);
  5592. var pathTool = __webpack_require__(19);
  5593. var Path = __webpack_require__(20);
  5594. var colorTool = __webpack_require__(31);
  5595. var matrix = __webpack_require__(11);
  5596. var vector = __webpack_require__(10);
  5597. var Transformable = __webpack_require__(26);
  5598. var BoundingRect = __webpack_require__(9);
  5599. var round = Math.round;
  5600. var mathMax = Math.max;
  5601. var mathMin = Math.min;
  5602. var graphic = {};
  5603. graphic.Group = __webpack_require__(48);
  5604. graphic.Image = __webpack_require__(49);
  5605. graphic.Text = __webpack_require__(50);
  5606. graphic.Circle = __webpack_require__(51);
  5607. graphic.Sector = __webpack_require__(52);
  5608. graphic.Ring = __webpack_require__(53);
  5609. graphic.Polygon = __webpack_require__(54);
  5610. graphic.Polyline = __webpack_require__(58);
  5611. graphic.Rect = __webpack_require__(59);
  5612. graphic.Line = __webpack_require__(61);
  5613. graphic.BezierCurve = __webpack_require__(62);
  5614. graphic.Arc = __webpack_require__(63);
  5615. graphic.CompoundPath = __webpack_require__(64);
  5616. graphic.LinearGradient = __webpack_require__(65);
  5617. graphic.RadialGradient = __webpack_require__(67);
  5618. graphic.BoundingRect = BoundingRect;
  5619. /**
  5620. * Extend shape with parameters
  5621. */
  5622. graphic.extendShape = function (opts) {
  5623. return Path.extend(opts);
  5624. };
  5625. /**
  5626. * Extend path
  5627. */
  5628. graphic.extendPath = function (pathData, opts) {
  5629. return pathTool.extendFromString(pathData, opts);
  5630. };
  5631. /**
  5632. * Create a path element from path data string
  5633. * @param {string} pathData
  5634. * @param {Object} opts
  5635. * @param {module:zrender/core/BoundingRect} rect
  5636. * @param {string} [layout=cover] 'center' or 'cover'
  5637. */
  5638. graphic.makePath = function (pathData, opts, rect, layout) {
  5639. var path = pathTool.createFromString(pathData, opts);
  5640. var boundingRect = path.getBoundingRect();
  5641. if (rect) {
  5642. var aspect = boundingRect.width / boundingRect.height;
  5643. if (layout === 'center') {
  5644. // Set rect to center, keep width / height ratio.
  5645. var width = rect.height * aspect;
  5646. var height;
  5647. if (width <= rect.width) {
  5648. height = rect.height;
  5649. }
  5650. else {
  5651. width = rect.width;
  5652. height = width / aspect;
  5653. }
  5654. var cx = rect.x + rect.width / 2;
  5655. var cy = rect.y + rect.height / 2;
  5656. rect.x = cx - width / 2;
  5657. rect.y = cy - height / 2;
  5658. rect.width = width;
  5659. rect.height = height;
  5660. }
  5661. graphic.resizePath(path, rect);
  5662. }
  5663. return path;
  5664. };
  5665. graphic.mergePath = pathTool.mergePath,
  5666. /**
  5667. * Resize a path to fit the rect
  5668. * @param {module:zrender/graphic/Path} path
  5669. * @param {Object} rect
  5670. */
  5671. graphic.resizePath = function (path, rect) {
  5672. if (!path.applyTransform) {
  5673. return;
  5674. }
  5675. var pathRect = path.getBoundingRect();
  5676. var m = pathRect.calculateTransform(rect);
  5677. path.applyTransform(m);
  5678. };
  5679. /**
  5680. * Sub pixel optimize line for canvas
  5681. *
  5682. * @param {Object} param
  5683. * @param {Object} [param.shape]
  5684. * @param {number} [param.shape.x1]
  5685. * @param {number} [param.shape.y1]
  5686. * @param {number} [param.shape.x2]
  5687. * @param {number} [param.shape.y2]
  5688. * @param {Object} [param.style]
  5689. * @param {number} [param.style.lineWidth]
  5690. * @return {Object} Modified param
  5691. */
  5692. graphic.subPixelOptimizeLine = function (param) {
  5693. var subPixelOptimize = graphic.subPixelOptimize;
  5694. var shape = param.shape;
  5695. var lineWidth = param.style.lineWidth;
  5696. if (round(shape.x1 * 2) === round(shape.x2 * 2)) {
  5697. shape.x1 = shape.x2 = subPixelOptimize(shape.x1, lineWidth, true);
  5698. }
  5699. if (round(shape.y1 * 2) === round(shape.y2 * 2)) {
  5700. shape.y1 = shape.y2 = subPixelOptimize(shape.y1, lineWidth, true);
  5701. }
  5702. return param;
  5703. };
  5704. /**
  5705. * Sub pixel optimize rect for canvas
  5706. *
  5707. * @param {Object} param
  5708. * @param {Object} [param.shape]
  5709. * @param {number} [param.shape.x]
  5710. * @param {number} [param.shape.y]
  5711. * @param {number} [param.shape.width]
  5712. * @param {number} [param.shape.height]
  5713. * @param {Object} [param.style]
  5714. * @param {number} [param.style.lineWidth]
  5715. * @return {Object} Modified param
  5716. */
  5717. graphic.subPixelOptimizeRect = function (param) {
  5718. var subPixelOptimize = graphic.subPixelOptimize;
  5719. var shape = param.shape;
  5720. var lineWidth = param.style.lineWidth;
  5721. var originX = shape.x;
  5722. var originY = shape.y;
  5723. var originWidth = shape.width;
  5724. var originHeight = shape.height;
  5725. shape.x = subPixelOptimize(shape.x, lineWidth, true);
  5726. shape.y = subPixelOptimize(shape.y, lineWidth, true);
  5727. shape.width = Math.max(
  5728. subPixelOptimize(originX + originWidth, lineWidth, false) - shape.x,
  5729. originWidth === 0 ? 0 : 1
  5730. );
  5731. shape.height = Math.max(
  5732. subPixelOptimize(originY + originHeight, lineWidth, false) - shape.y,
  5733. originHeight === 0 ? 0 : 1
  5734. );
  5735. return param;
  5736. };
  5737. /**
  5738. * Sub pixel optimize for canvas
  5739. *
  5740. * @param {number} position Coordinate, such as x, y
  5741. * @param {number} lineWidth Should be nonnegative integer.
  5742. * @param {boolean=} positiveOrNegative Default false (negative).
  5743. * @return {number} Optimized position.
  5744. */
  5745. graphic.subPixelOptimize = function (position, lineWidth, positiveOrNegative) {
  5746. // Assure that (position + lineWidth / 2) is near integer edge,
  5747. // otherwise line will be fuzzy in canvas.
  5748. var doubledPosition = round(position * 2);
  5749. return (doubledPosition + round(lineWidth)) % 2 === 0
  5750. ? doubledPosition / 2
  5751. : (doubledPosition + (positiveOrNegative ? 1 : -1)) / 2;
  5752. };
  5753. function hasFillOrStroke(fillOrStroke) {
  5754. return fillOrStroke != null && fillOrStroke != 'none';
  5755. }
  5756. function liftColor(color) {
  5757. return typeof color === 'string' ? colorTool.lift(color, -0.1) : color;
  5758. }
  5759. /**
  5760. * @private
  5761. */
  5762. function cacheElementStl(el) {
  5763. if (el.__hoverStlDirty) {
  5764. var stroke = el.style.stroke;
  5765. var fill = el.style.fill;
  5766. // Create hoverStyle on mouseover
  5767. var hoverStyle = el.__hoverStl;
  5768. hoverStyle.fill = hoverStyle.fill
  5769. || (hasFillOrStroke(fill) ? liftColor(fill) : null);
  5770. hoverStyle.stroke = hoverStyle.stroke
  5771. || (hasFillOrStroke(stroke) ? liftColor(stroke) : null);
  5772. var normalStyle = {};
  5773. for (var name in hoverStyle) {
  5774. if (hoverStyle.hasOwnProperty(name)) {
  5775. normalStyle[name] = el.style[name];
  5776. }
  5777. }
  5778. el.__normalStl = normalStyle;
  5779. el.__hoverStlDirty = false;
  5780. }
  5781. }
  5782. /**
  5783. * @private
  5784. */
  5785. function doSingleEnterHover(el) {
  5786. if (el.__isHover) {
  5787. return;
  5788. }
  5789. cacheElementStl(el);
  5790. if (el.useHoverLayer) {
  5791. el.__zr && el.__zr.addHover(el, el.__hoverStl);
  5792. }
  5793. else {
  5794. el.setStyle(el.__hoverStl);
  5795. el.z2 += 1;
  5796. }
  5797. el.__isHover = true;
  5798. }
  5799. /**
  5800. * @inner
  5801. */
  5802. function doSingleLeaveHover(el) {
  5803. if (!el.__isHover) {
  5804. return;
  5805. }
  5806. var normalStl = el.__normalStl;
  5807. if (el.useHoverLayer) {
  5808. el.__zr && el.__zr.removeHover(el);
  5809. }
  5810. else {
  5811. normalStl && el.setStyle(normalStl);
  5812. el.z2 -= 1;
  5813. }
  5814. el.__isHover = false;
  5815. }
  5816. /**
  5817. * @inner
  5818. */
  5819. function doEnterHover(el) {
  5820. el.type === 'group'
  5821. ? el.traverse(function (child) {
  5822. if (child.type !== 'group') {
  5823. doSingleEnterHover(child);
  5824. }
  5825. })
  5826. : doSingleEnterHover(el);
  5827. }
  5828. function doLeaveHover(el) {
  5829. el.type === 'group'
  5830. ? el.traverse(function (child) {
  5831. if (child.type !== 'group') {
  5832. doSingleLeaveHover(child);
  5833. }
  5834. })
  5835. : doSingleLeaveHover(el);
  5836. }
  5837. /**
  5838. * @inner
  5839. */
  5840. function setElementHoverStl(el, hoverStl) {
  5841. // If element has sepcified hoverStyle, then use it instead of given hoverStyle
  5842. // Often used when item group has a label element and it's hoverStyle is different
  5843. el.__hoverStl = el.hoverStyle || hoverStl || {};
  5844. el.__hoverStlDirty = true;
  5845. if (el.__isHover) {
  5846. cacheElementStl(el);
  5847. }
  5848. }
  5849. /**
  5850. * @inner
  5851. */
  5852. function onElementMouseOver(e) {
  5853. if (this.__hoverSilentOnTouch && e.zrByTouch) {
  5854. return;
  5855. }
  5856. // Only if element is not in emphasis status
  5857. !this.__isEmphasis && doEnterHover(this);
  5858. }
  5859. /**
  5860. * @inner
  5861. */
  5862. function onElementMouseOut(e) {
  5863. if (this.__hoverSilentOnTouch && e.zrByTouch) {
  5864. return;
  5865. }
  5866. // Only if element is not in emphasis status
  5867. !this.__isEmphasis && doLeaveHover(this);
  5868. }
  5869. /**
  5870. * @inner
  5871. */
  5872. function enterEmphasis() {
  5873. this.__isEmphasis = true;
  5874. doEnterHover(this);
  5875. }
  5876. /**
  5877. * @inner
  5878. */
  5879. function leaveEmphasis() {
  5880. this.__isEmphasis = false;
  5881. doLeaveHover(this);
  5882. }
  5883. /**
  5884. * Set hover style of element.
  5885. * This method can be called repeatly without side-effects.
  5886. * @param {module:zrender/Element} el
  5887. * @param {Object} [hoverStyle]
  5888. * @param {Object} [opt]
  5889. * @param {boolean} [opt.hoverSilentOnTouch=false]
  5890. * In touch device, mouseover event will be trigger on touchstart event
  5891. * (see module:zrender/dom/HandlerProxy). By this mechanism, we can
  5892. * conviniently use hoverStyle when tap on touch screen without additional
  5893. * code for compatibility.
  5894. * But if the chart/component has select feature, which usually also use
  5895. * hoverStyle, there might be conflict between 'select-highlight' and
  5896. * 'hover-highlight' especially when roam is enabled (see geo for example).
  5897. * In this case, hoverSilentOnTouch should be used to disable hover-highlight
  5898. * on touch device.
  5899. */
  5900. graphic.setHoverStyle = function (el, hoverStyle, opt) {
  5901. el.__hoverSilentOnTouch = opt && opt.hoverSilentOnTouch;
  5902. el.type === 'group'
  5903. ? el.traverse(function (child) {
  5904. if (child.type !== 'group') {
  5905. setElementHoverStl(child, hoverStyle);
  5906. }
  5907. })
  5908. : setElementHoverStl(el, hoverStyle);
  5909. // Duplicated function will be auto-ignored, see Eventful.js.
  5910. el.on('mouseover', onElementMouseOver)
  5911. .on('mouseout', onElementMouseOut);
  5912. // Emphasis, normal can be triggered manually
  5913. el.on('emphasis', enterEmphasis)
  5914. .on('normal', leaveEmphasis);
  5915. };
  5916. /**
  5917. * Set text option in the style
  5918. * @param {Object} textStyle
  5919. * @param {module:echarts/model/Model} labelModel
  5920. * @param {string} color
  5921. */
  5922. graphic.setText = function (textStyle, labelModel, color) {
  5923. var labelPosition = labelModel.getShallow('position') || 'inside';
  5924. var labelOffset = labelModel.getShallow('offset');
  5925. var labelColor = labelPosition.indexOf('inside') >= 0 ? 'white' : color;
  5926. var textStyleModel = labelModel.getModel('textStyle');
  5927. zrUtil.extend(textStyle, {
  5928. textDistance: labelModel.getShallow('distance') || 5,
  5929. textFont: textStyleModel.getFont(),
  5930. textPosition: labelPosition,
  5931. textOffset: labelOffset,
  5932. textFill: textStyleModel.getTextColor() || labelColor
  5933. });
  5934. };
  5935. graphic.getFont = function (opt, ecModel) {
  5936. var gTextStyleModel = ecModel && ecModel.getModel('textStyle');
  5937. return [
  5938. // FIXME in node-canvas fontWeight is before fontStyle
  5939. opt.fontStyle || gTextStyleModel && gTextStyleModel.getShallow('fontStyle') || '',
  5940. opt.fontWeight || gTextStyleModel && gTextStyleModel.getShallow('fontWeight') || '',
  5941. (opt.fontSize || gTextStyleModel && gTextStyleModel.getShallow('fontSize') || 12) + 'px',
  5942. opt.fontFamily || gTextStyleModel && gTextStyleModel.getShallow('fontFamily') || 'sans-serif'
  5943. ].join(' ');
  5944. };
  5945. function animateOrSetProps(isUpdate, el, props, animatableModel, dataIndex, cb) {
  5946. if (typeof dataIndex === 'function') {
  5947. cb = dataIndex;
  5948. dataIndex = null;
  5949. }
  5950. // Do not check 'animation' property directly here. Consider this case:
  5951. // animation model is an `itemModel`, whose does not have `isAnimationEnabled`
  5952. // but its parent model (`seriesModel`) does.
  5953. var animationEnabled = animatableModel && animatableModel.isAnimationEnabled();
  5954. if (animationEnabled) {
  5955. var postfix = isUpdate ? 'Update' : '';
  5956. var duration = animatableModel.getShallow('animationDuration' + postfix);
  5957. var animationEasing = animatableModel.getShallow('animationEasing' + postfix);
  5958. var animationDelay = animatableModel.getShallow('animationDelay' + postfix);
  5959. if (typeof animationDelay === 'function') {
  5960. animationDelay = animationDelay(
  5961. dataIndex,
  5962. animatableModel.getAnimationDelayParams
  5963. ? animatableModel.getAnimationDelayParams(el, dataIndex)
  5964. : null
  5965. );
  5966. }
  5967. if (typeof duration === 'function') {
  5968. duration = duration(dataIndex);
  5969. }
  5970. duration > 0
  5971. ? el.animateTo(props, duration, animationDelay || 0, animationEasing, cb)
  5972. : (el.stopAnimation(), el.attr(props), cb && cb());
  5973. }
  5974. else {
  5975. el.stopAnimation();
  5976. el.attr(props);
  5977. cb && cb();
  5978. }
  5979. }
  5980. /**
  5981. * Update graphic element properties with or without animation according to the configuration in series
  5982. * @param {module:zrender/Element} el
  5983. * @param {Object} props
  5984. * @param {module:echarts/model/Model} [animatableModel]
  5985. * @param {number} [dataIndex]
  5986. * @param {Function} [cb]
  5987. * @example
  5988. * graphic.updateProps(el, {
  5989. * position: [100, 100]
  5990. * }, seriesModel, dataIndex, function () { console.log('Animation done!'); });
  5991. * // Or
  5992. * graphic.updateProps(el, {
  5993. * position: [100, 100]
  5994. * }, seriesModel, function () { console.log('Animation done!'); });
  5995. */
  5996. graphic.updateProps = function (el, props, animatableModel, dataIndex, cb) {
  5997. animateOrSetProps(true, el, props, animatableModel, dataIndex, cb);
  5998. };
  5999. /**
  6000. * Init graphic element properties with or without animation according to the configuration in series
  6001. * @param {module:zrender/Element} el
  6002. * @param {Object} props
  6003. * @param {module:echarts/model/Model} [animatableModel]
  6004. * @param {number} [dataIndex]
  6005. * @param {Function} cb
  6006. */
  6007. graphic.initProps = function (el, props, animatableModel, dataIndex, cb) {
  6008. animateOrSetProps(false, el, props, animatableModel, dataIndex, cb);
  6009. };
  6010. /**
  6011. * Get transform matrix of target (param target),
  6012. * in coordinate of its ancestor (param ancestor)
  6013. *
  6014. * @param {module:zrender/mixin/Transformable} target
  6015. * @param {module:zrender/mixin/Transformable} [ancestor]
  6016. */
  6017. graphic.getTransform = function (target, ancestor) {
  6018. var mat = matrix.identity([]);
  6019. while (target && target !== ancestor) {
  6020. matrix.mul(mat, target.getLocalTransform(), mat);
  6021. target = target.parent;
  6022. }
  6023. return mat;
  6024. };
  6025. /**
  6026. * Apply transform to an vertex.
  6027. * @param {Array.<number>} target [x, y]
  6028. * @param {Array.<number>|TypedArray.<number>|Object} transform Can be:
  6029. * + Transform matrix: like [1, 0, 0, 1, 0, 0]
  6030. * + {position, rotation, scale}, the same as `zrender/Transformable`.
  6031. * @param {boolean=} invert Whether use invert matrix.
  6032. * @return {Array.<number>} [x, y]
  6033. */
  6034. graphic.applyTransform = function (target, transform, invert) {
  6035. if (transform && !zrUtil.isArrayLike(transform)) {
  6036. transform = Transformable.getLocalTransform(transform);
  6037. }
  6038. if (invert) {
  6039. transform = matrix.invert([], transform);
  6040. }
  6041. return vector.applyTransform([], target, transform);
  6042. };
  6043. /**
  6044. * @param {string} direction 'left' 'right' 'top' 'bottom'
  6045. * @param {Array.<number>} transform Transform matrix: like [1, 0, 0, 1, 0, 0]
  6046. * @param {boolean=} invert Whether use invert matrix.
  6047. * @return {string} Transformed direction. 'left' 'right' 'top' 'bottom'
  6048. */
  6049. graphic.transformDirection = function (direction, transform, invert) {
  6050. // Pick a base, ensure that transform result will not be (0, 0).
  6051. var hBase = (transform[4] === 0 || transform[5] === 0 || transform[0] === 0)
  6052. ? 1 : Math.abs(2 * transform[4] / transform[0]);
  6053. var vBase = (transform[4] === 0 || transform[5] === 0 || transform[2] === 0)
  6054. ? 1 : Math.abs(2 * transform[4] / transform[2]);
  6055. var vertex = [
  6056. direction === 'left' ? -hBase : direction === 'right' ? hBase : 0,
  6057. direction === 'top' ? -vBase : direction === 'bottom' ? vBase : 0
  6058. ];
  6059. vertex = graphic.applyTransform(vertex, transform, invert);
  6060. return Math.abs(vertex[0]) > Math.abs(vertex[1])
  6061. ? (vertex[0] > 0 ? 'right' : 'left')
  6062. : (vertex[1] > 0 ? 'bottom' : 'top');
  6063. };
  6064. /**
  6065. * Apply group transition animation from g1 to g2.
  6066. * If no animatableModel, no animation.
  6067. */
  6068. graphic.groupTransition = function (g1, g2, animatableModel, cb) {
  6069. if (!g1 || !g2) {
  6070. return;
  6071. }
  6072. function getElMap(g) {
  6073. var elMap = {};
  6074. g.traverse(function (el) {
  6075. if (!el.isGroup && el.anid) {
  6076. elMap[el.anid] = el;
  6077. }
  6078. });
  6079. return elMap;
  6080. }
  6081. function getAnimatableProps(el) {
  6082. var obj = {
  6083. position: vector.clone(el.position),
  6084. rotation: el.rotation
  6085. };
  6086. if (el.shape) {
  6087. obj.shape = zrUtil.extend({}, el.shape);
  6088. }
  6089. return obj;
  6090. }
  6091. var elMap1 = getElMap(g1);
  6092. g2.traverse(function (el) {
  6093. if (!el.isGroup && el.anid) {
  6094. var oldEl = elMap1[el.anid];
  6095. if (oldEl) {
  6096. var newProp = getAnimatableProps(el);
  6097. el.attr(getAnimatableProps(oldEl));
  6098. graphic.updateProps(el, newProp, animatableModel, el.dataIndex);
  6099. }
  6100. // else {
  6101. // if (el.previousProps) {
  6102. // graphic.updateProps
  6103. // }
  6104. // }
  6105. }
  6106. });
  6107. };
  6108. /**
  6109. * @param {Array.<Array.<number>>} points Like: [[23, 44], [53, 66], ...]
  6110. * @param {Object} rect {x, y, width, height}
  6111. * @return {Array.<Array.<number>>} A new clipped points.
  6112. */
  6113. graphic.clipPointsByRect = function (points, rect) {
  6114. return zrUtil.map(points, function (point) {
  6115. var x = point[0];
  6116. x = mathMax(x, rect.x);
  6117. x = mathMin(x, rect.x + rect.width);
  6118. var y = point[1];
  6119. y = mathMax(y, rect.y);
  6120. y = mathMin(y, rect.y + rect.height);
  6121. return [x, y];
  6122. });
  6123. };
  6124. /**
  6125. * @param {Object} targetRect {x, y, width, height}
  6126. * @param {Object} rect {x, y, width, height}
  6127. * @return {Object} A new clipped rect. If rect size are negative, return undefined.
  6128. */
  6129. graphic.clipRectByRect = function (targetRect, rect) {
  6130. var x = mathMax(targetRect.x, rect.x);
  6131. var x2 = mathMin(targetRect.x + targetRect.width, rect.x + rect.width);
  6132. var y = mathMax(targetRect.y, rect.y);
  6133. var y2 = mathMin(targetRect.y + targetRect.height, rect.y + rect.height);
  6134. if (x2 >= x && y2 >= y) {
  6135. return {
  6136. x: x,
  6137. y: y,
  6138. width: x2 - x,
  6139. height: y2 - y
  6140. };
  6141. }
  6142. };
  6143. module.exports = graphic;
  6144. /***/ },
  6145. /* 19 */
  6146. /***/ function(module, exports, __webpack_require__) {
  6147. var Path = __webpack_require__(20);
  6148. var PathProxy = __webpack_require__(36);
  6149. var transformPath = __webpack_require__(47);
  6150. // command chars
  6151. var cc = [
  6152. 'm', 'M', 'l', 'L', 'v', 'V', 'h', 'H', 'z', 'Z',
  6153. 'c', 'C', 'q', 'Q', 't', 'T', 's', 'S', 'a', 'A'
  6154. ];
  6155. var mathSqrt = Math.sqrt;
  6156. var mathSin = Math.sin;
  6157. var mathCos = Math.cos;
  6158. var PI = Math.PI;
  6159. var vMag = function(v) {
  6160. return Math.sqrt(v[0] * v[0] + v[1] * v[1]);
  6161. };
  6162. var vRatio = function(u, v) {
  6163. return (u[0] * v[0] + u[1] * v[1]) / (vMag(u) * vMag(v));
  6164. };
  6165. var vAngle = function(u, v) {
  6166. return (u[0] * v[1] < u[1] * v[0] ? -1 : 1)
  6167. * Math.acos(vRatio(u, v));
  6168. };
  6169. function processArc(x1, y1, x2, y2, fa, fs, rx, ry, psiDeg, cmd, path) {
  6170. var psi = psiDeg * (PI / 180.0);
  6171. var xp = mathCos(psi) * (x1 - x2) / 2.0
  6172. + mathSin(psi) * (y1 - y2) / 2.0;
  6173. var yp = -1 * mathSin(psi) * (x1 - x2) / 2.0
  6174. + mathCos(psi) * (y1 - y2) / 2.0;
  6175. var lambda = (xp * xp) / (rx * rx) + (yp * yp) / (ry * ry);
  6176. if (lambda > 1) {
  6177. rx *= mathSqrt(lambda);
  6178. ry *= mathSqrt(lambda);
  6179. }
  6180. var f = (fa === fs ? -1 : 1)
  6181. * mathSqrt((((rx * rx) * (ry * ry))
  6182. - ((rx * rx) * (yp * yp))
  6183. - ((ry * ry) * (xp * xp))) / ((rx * rx) * (yp * yp)
  6184. + (ry * ry) * (xp * xp))
  6185. ) || 0;
  6186. var cxp = f * rx * yp / ry;
  6187. var cyp = f * -ry * xp / rx;
  6188. var cx = (x1 + x2) / 2.0
  6189. + mathCos(psi) * cxp
  6190. - mathSin(psi) * cyp;
  6191. var cy = (y1 + y2) / 2.0
  6192. + mathSin(psi) * cxp
  6193. + mathCos(psi) * cyp;
  6194. var theta = vAngle([ 1, 0 ], [ (xp - cxp) / rx, (yp - cyp) / ry ]);
  6195. var u = [ (xp - cxp) / rx, (yp - cyp) / ry ];
  6196. var v = [ (-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry ];
  6197. var dTheta = vAngle(u, v);
  6198. if (vRatio(u, v) <= -1) {
  6199. dTheta = PI;
  6200. }
  6201. if (vRatio(u, v) >= 1) {
  6202. dTheta = 0;
  6203. }
  6204. if (fs === 0 && dTheta > 0) {
  6205. dTheta = dTheta - 2 * PI;
  6206. }
  6207. if (fs === 1 && dTheta < 0) {
  6208. dTheta = dTheta + 2 * PI;
  6209. }
  6210. path.addData(cmd, cx, cy, rx, ry, theta, dTheta, psi, fs);
  6211. }
  6212. function createPathProxyFromString(data) {
  6213. if (!data) {
  6214. return [];
  6215. }
  6216. // command string
  6217. var cs = data.replace(/-/g, ' -')
  6218. .replace(/ /g, ' ')
  6219. .replace(/ /g, ',')
  6220. .replace(/,,/g, ',');
  6221. var n;
  6222. // create pipes so that we can split the data
  6223. for (n = 0; n < cc.length; n++) {
  6224. cs = cs.replace(new RegExp(cc[n], 'g'), '|' + cc[n]);
  6225. }
  6226. // create array
  6227. var arr = cs.split('|');
  6228. // init context point
  6229. var cpx = 0;
  6230. var cpy = 0;
  6231. var path = new PathProxy();
  6232. var CMD = PathProxy.CMD;
  6233. var prevCmd;
  6234. for (n = 1; n < arr.length; n++) {
  6235. var str = arr[n];
  6236. var c = str.charAt(0);
  6237. var off = 0;
  6238. var p = str.slice(1).replace(/e,-/g, 'e-').split(',');
  6239. var cmd;
  6240. if (p.length > 0 && p[0] === '') {
  6241. p.shift();
  6242. }
  6243. for (var i = 0; i < p.length; i++) {
  6244. p[i] = parseFloat(p[i]);
  6245. }
  6246. while (off < p.length && !isNaN(p[off])) {
  6247. if (isNaN(p[0])) {
  6248. break;
  6249. }
  6250. var ctlPtx;
  6251. var ctlPty;
  6252. var rx;
  6253. var ry;
  6254. var psi;
  6255. var fa;
  6256. var fs;
  6257. var x1 = cpx;
  6258. var y1 = cpy;
  6259. // convert l, H, h, V, and v to L
  6260. switch (c) {
  6261. case 'l':
  6262. cpx += p[off++];
  6263. cpy += p[off++];
  6264. cmd = CMD.L;
  6265. path.addData(cmd, cpx, cpy);
  6266. break;
  6267. case 'L':
  6268. cpx = p[off++];
  6269. cpy = p[off++];
  6270. cmd = CMD.L;
  6271. path.addData(cmd, cpx, cpy);
  6272. break;
  6273. case 'm':
  6274. cpx += p[off++];
  6275. cpy += p[off++];
  6276. cmd = CMD.M;
  6277. path.addData(cmd, cpx, cpy);
  6278. c = 'l';
  6279. break;
  6280. case 'M':
  6281. cpx = p[off++];
  6282. cpy = p[off++];
  6283. cmd = CMD.M;
  6284. path.addData(cmd, cpx, cpy);
  6285. c = 'L';
  6286. break;
  6287. case 'h':
  6288. cpx += p[off++];
  6289. cmd = CMD.L;
  6290. path.addData(cmd, cpx, cpy);
  6291. break;
  6292. case 'H':
  6293. cpx = p[off++];
  6294. cmd = CMD.L;
  6295. path.addData(cmd, cpx, cpy);
  6296. break;
  6297. case 'v':
  6298. cpy += p[off++];
  6299. cmd = CMD.L;
  6300. path.addData(cmd, cpx, cpy);
  6301. break;
  6302. case 'V':
  6303. cpy = p[off++];
  6304. cmd = CMD.L;
  6305. path.addData(cmd, cpx, cpy);
  6306. break;
  6307. case 'C':
  6308. cmd = CMD.C;
  6309. path.addData(
  6310. cmd, p[off++], p[off++], p[off++], p[off++], p[off++], p[off++]
  6311. );
  6312. cpx = p[off - 2];
  6313. cpy = p[off - 1];
  6314. break;
  6315. case 'c':
  6316. cmd = CMD.C;
  6317. path.addData(
  6318. cmd,
  6319. p[off++] + cpx, p[off++] + cpy,
  6320. p[off++] + cpx, p[off++] + cpy,
  6321. p[off++] + cpx, p[off++] + cpy
  6322. );
  6323. cpx += p[off - 2];
  6324. cpy += p[off - 1];
  6325. break;
  6326. case 'S':
  6327. ctlPtx = cpx;
  6328. ctlPty = cpy;
  6329. var len = path.len();
  6330. var pathData = path.data;
  6331. if (prevCmd === CMD.C) {
  6332. ctlPtx += cpx - pathData[len - 4];
  6333. ctlPty += cpy - pathData[len - 3];
  6334. }
  6335. cmd = CMD.C;
  6336. x1 = p[off++];
  6337. y1 = p[off++];
  6338. cpx = p[off++];
  6339. cpy = p[off++];
  6340. path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy);
  6341. break;
  6342. case 's':
  6343. ctlPtx = cpx;
  6344. ctlPty = cpy;
  6345. var len = path.len();
  6346. var pathData = path.data;
  6347. if (prevCmd === CMD.C) {
  6348. ctlPtx += cpx - pathData[len - 4];
  6349. ctlPty += cpy - pathData[len - 3];
  6350. }
  6351. cmd = CMD.C;
  6352. x1 = cpx + p[off++];
  6353. y1 = cpy + p[off++];
  6354. cpx += p[off++];
  6355. cpy += p[off++];
  6356. path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy);
  6357. break;
  6358. case 'Q':
  6359. x1 = p[off++];
  6360. y1 = p[off++];
  6361. cpx = p[off++];
  6362. cpy = p[off++];
  6363. cmd = CMD.Q;
  6364. path.addData(cmd, x1, y1, cpx, cpy);
  6365. break;
  6366. case 'q':
  6367. x1 = p[off++] + cpx;
  6368. y1 = p[off++] + cpy;
  6369. cpx += p[off++];
  6370. cpy += p[off++];
  6371. cmd = CMD.Q;
  6372. path.addData(cmd, x1, y1, cpx, cpy);
  6373. break;
  6374. case 'T':
  6375. ctlPtx = cpx;
  6376. ctlPty = cpy;
  6377. var len = path.len();
  6378. var pathData = path.data;
  6379. if (prevCmd === CMD.Q) {
  6380. ctlPtx += cpx - pathData[len - 4];
  6381. ctlPty += cpy - pathData[len - 3];
  6382. }
  6383. cpx = p[off++];
  6384. cpy = p[off++];
  6385. cmd = CMD.Q;
  6386. path.addData(cmd, ctlPtx, ctlPty, cpx, cpy);
  6387. break;
  6388. case 't':
  6389. ctlPtx = cpx;
  6390. ctlPty = cpy;
  6391. var len = path.len();
  6392. var pathData = path.data;
  6393. if (prevCmd === CMD.Q) {
  6394. ctlPtx += cpx - pathData[len - 4];
  6395. ctlPty += cpy - pathData[len - 3];
  6396. }
  6397. cpx += p[off++];
  6398. cpy += p[off++];
  6399. cmd = CMD.Q;
  6400. path.addData(cmd, ctlPtx, ctlPty, cpx, cpy);
  6401. break;
  6402. case 'A':
  6403. rx = p[off++];
  6404. ry = p[off++];
  6405. psi = p[off++];
  6406. fa = p[off++];
  6407. fs = p[off++];
  6408. x1 = cpx, y1 = cpy;
  6409. cpx = p[off++];
  6410. cpy = p[off++];
  6411. cmd = CMD.A;
  6412. processArc(
  6413. x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path
  6414. );
  6415. break;
  6416. case 'a':
  6417. rx = p[off++];
  6418. ry = p[off++];
  6419. psi = p[off++];
  6420. fa = p[off++];
  6421. fs = p[off++];
  6422. x1 = cpx, y1 = cpy;
  6423. cpx += p[off++];
  6424. cpy += p[off++];
  6425. cmd = CMD.A;
  6426. processArc(
  6427. x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path
  6428. );
  6429. break;
  6430. }
  6431. }
  6432. if (c === 'z' || c === 'Z') {
  6433. cmd = CMD.Z;
  6434. path.addData(cmd);
  6435. }
  6436. prevCmd = cmd;
  6437. }
  6438. path.toStatic();
  6439. return path;
  6440. }
  6441. // TODO Optimize double memory cost problem
  6442. function createPathOptions(str, opts) {
  6443. var pathProxy = createPathProxyFromString(str);
  6444. opts = opts || {};
  6445. opts.buildPath = function (path) {
  6446. if (path.setData) {
  6447. path.setData(pathProxy.data);
  6448. // Svg and vml renderer don't have context
  6449. var ctx = path.getContext();
  6450. if (ctx) {
  6451. path.rebuildPath(ctx);
  6452. }
  6453. }
  6454. else {
  6455. var ctx = path;
  6456. pathProxy.rebuildPath(ctx);
  6457. }
  6458. };
  6459. opts.applyTransform = function (m) {
  6460. transformPath(pathProxy, m);
  6461. this.dirty(true);
  6462. };
  6463. return opts;
  6464. }
  6465. module.exports = {
  6466. /**
  6467. * Create a Path object from path string data
  6468. * http://www.w3.org/TR/SVG/paths.html#PathData
  6469. * @param {Object} opts Other options
  6470. */
  6471. createFromString: function (str, opts) {
  6472. return new Path(createPathOptions(str, opts));
  6473. },
  6474. /**
  6475. * Create a Path class from path string data
  6476. * @param {string} str
  6477. * @param {Object} opts Other options
  6478. */
  6479. extendFromString: function (str, opts) {
  6480. return Path.extend(createPathOptions(str, opts));
  6481. },
  6482. /**
  6483. * Merge multiple paths
  6484. */
  6485. // TODO Apply transform
  6486. // TODO stroke dash
  6487. // TODO Optimize double memory cost problem
  6488. mergePath: function (pathEls, opts) {
  6489. var pathList = [];
  6490. var len = pathEls.length;
  6491. for (var i = 0; i < len; i++) {
  6492. var pathEl = pathEls[i];
  6493. if (!pathEl.path) {
  6494. pathEl.createPathProxy();
  6495. }
  6496. if (pathEl.__dirtyPath) {
  6497. pathEl.buildPath(pathEl.path, pathEl.shape, true);
  6498. }
  6499. pathList.push(pathEl.path);
  6500. }
  6501. var pathBundle = new Path(opts);
  6502. // Need path proxy.
  6503. pathBundle.createPathProxy();
  6504. pathBundle.buildPath = function (path) {
  6505. path.appendPath(pathList);
  6506. // Svg and vml renderer don't have context
  6507. var ctx = path.getContext();
  6508. if (ctx) {
  6509. path.rebuildPath(ctx);
  6510. }
  6511. };
  6512. return pathBundle;
  6513. }
  6514. };
  6515. /***/ },
  6516. /* 20 */
  6517. /***/ function(module, exports, __webpack_require__) {
  6518. /**
  6519. * Path element
  6520. * @module zrender/graphic/Path
  6521. */
  6522. var Displayable = __webpack_require__(21);
  6523. var zrUtil = __webpack_require__(4);
  6524. var PathProxy = __webpack_require__(36);
  6525. var pathContain = __webpack_require__(39);
  6526. var Pattern = __webpack_require__(46);
  6527. var getCanvasPattern = Pattern.prototype.getCanvasPattern;
  6528. var abs = Math.abs;
  6529. var pathProxyForDraw = new PathProxy(true);
  6530. /**
  6531. * @alias module:zrender/graphic/Path
  6532. * @extends module:zrender/graphic/Displayable
  6533. * @constructor
  6534. * @param {Object} opts
  6535. */
  6536. function Path(opts) {
  6537. Displayable.call(this, opts);
  6538. /**
  6539. * @type {module:zrender/core/PathProxy}
  6540. * @readOnly
  6541. */
  6542. this.path = null;
  6543. }
  6544. Path.prototype = {
  6545. constructor: Path,
  6546. type: 'path',
  6547. __dirtyPath: true,
  6548. strokeContainThreshold: 5,
  6549. brush: function (ctx, prevEl) {
  6550. var style = this.style;
  6551. var path = this.path || pathProxyForDraw;
  6552. var hasStroke = style.hasStroke();
  6553. var hasFill = style.hasFill();
  6554. var fill = style.fill;
  6555. var stroke = style.stroke;
  6556. var hasFillGradient = hasFill && !!(fill.colorStops);
  6557. var hasStrokeGradient = hasStroke && !!(stroke.colorStops);
  6558. var hasFillPattern = hasFill && !!(fill.image);
  6559. var hasStrokePattern = hasStroke && !!(stroke.image);
  6560. style.bind(ctx, this, prevEl);
  6561. this.setTransform(ctx);
  6562. if (this.__dirty) {
  6563. var rect;
  6564. // Update gradient because bounding rect may changed
  6565. if (hasFillGradient) {
  6566. rect = rect || this.getBoundingRect();
  6567. this._fillGradient = style.getGradient(ctx, fill, rect);
  6568. }
  6569. if (hasStrokeGradient) {
  6570. rect = rect || this.getBoundingRect();
  6571. this._strokeGradient = style.getGradient(ctx, stroke, rect);
  6572. }
  6573. }
  6574. // Use the gradient or pattern
  6575. if (hasFillGradient) {
  6576. // PENDING If may have affect the state
  6577. ctx.fillStyle = this._fillGradient;
  6578. }
  6579. else if (hasFillPattern) {
  6580. ctx.fillStyle = getCanvasPattern.call(fill, ctx);
  6581. }
  6582. if (hasStrokeGradient) {
  6583. ctx.strokeStyle = this._strokeGradient;
  6584. }
  6585. else if (hasStrokePattern) {
  6586. ctx.strokeStyle = getCanvasPattern.call(stroke, ctx);
  6587. }
  6588. var lineDash = style.lineDash;
  6589. var lineDashOffset = style.lineDashOffset;
  6590. var ctxLineDash = !!ctx.setLineDash;
  6591. // Update path sx, sy
  6592. var scale = this.getGlobalScale();
  6593. path.setScale(scale[0], scale[1]);
  6594. // Proxy context
  6595. // Rebuild path in following 2 cases
  6596. // 1. Path is dirty
  6597. // 2. Path needs javascript implemented lineDash stroking.
  6598. // In this case, lineDash information will not be saved in PathProxy
  6599. if (this.__dirtyPath
  6600. || (lineDash && !ctxLineDash && hasStroke)
  6601. ) {
  6602. path.beginPath(ctx);
  6603. // Setting line dash before build path
  6604. if (lineDash && !ctxLineDash) {
  6605. path.setLineDash(lineDash);
  6606. path.setLineDashOffset(lineDashOffset);
  6607. }
  6608. this.buildPath(path, this.shape, false);
  6609. // Clear path dirty flag
  6610. if (this.path) {
  6611. this.__dirtyPath = false;
  6612. }
  6613. }
  6614. else {
  6615. // Replay path building
  6616. ctx.beginPath();
  6617. this.path.rebuildPath(ctx);
  6618. }
  6619. hasFill && path.fill(ctx);
  6620. if (lineDash && ctxLineDash) {
  6621. ctx.setLineDash(lineDash);
  6622. ctx.lineDashOffset = lineDashOffset;
  6623. }
  6624. hasStroke && path.stroke(ctx);
  6625. if (lineDash && ctxLineDash) {
  6626. // PENDING
  6627. // Remove lineDash
  6628. ctx.setLineDash([]);
  6629. }
  6630. this.restoreTransform(ctx);
  6631. // Draw rect text
  6632. if (style.text != null) {
  6633. // var rect = this.getBoundingRect();
  6634. this.drawRectText(ctx, this.getBoundingRect());
  6635. }
  6636. },
  6637. // When bundling path, some shape may decide if use moveTo to begin a new subpath or closePath
  6638. // Like in circle
  6639. buildPath: function (ctx, shapeCfg, inBundle) {},
  6640. createPathProxy: function () {
  6641. this.path = new PathProxy();
  6642. },
  6643. getBoundingRect: function () {
  6644. var rect = this._rect;
  6645. var style = this.style;
  6646. var needsUpdateRect = !rect;
  6647. if (needsUpdateRect) {
  6648. var path = this.path;
  6649. if (!path) {
  6650. // Create path on demand.
  6651. path = this.path = new PathProxy();
  6652. }
  6653. if (this.__dirtyPath) {
  6654. path.beginPath();
  6655. this.buildPath(path, this.shape, false);
  6656. }
  6657. rect = path.getBoundingRect();
  6658. }
  6659. this._rect = rect;
  6660. if (style.hasStroke()) {
  6661. // Needs update rect with stroke lineWidth when
  6662. // 1. Element changes scale or lineWidth
  6663. // 2. Shape is changed
  6664. var rectWithStroke = this._rectWithStroke || (this._rectWithStroke = rect.clone());
  6665. if (this.__dirty || needsUpdateRect) {
  6666. rectWithStroke.copy(rect);
  6667. // FIXME Must after updateTransform
  6668. var w = style.lineWidth;
  6669. // PENDING, Min line width is needed when line is horizontal or vertical
  6670. var lineScale = style.strokeNoScale ? this.getLineScale() : 1;
  6671. // Only add extra hover lineWidth when there are no fill
  6672. if (!style.hasFill()) {
  6673. w = Math.max(w, this.strokeContainThreshold || 4);
  6674. }
  6675. // Consider line width
  6676. // Line scale can't be 0;
  6677. if (lineScale > 1e-10) {
  6678. rectWithStroke.width += w / lineScale;
  6679. rectWithStroke.height += w / lineScale;
  6680. rectWithStroke.x -= w / lineScale / 2;
  6681. rectWithStroke.y -= w / lineScale / 2;
  6682. }
  6683. }
  6684. // Return rect with stroke
  6685. return rectWithStroke;
  6686. }
  6687. return rect;
  6688. },
  6689. contain: function (x, y) {
  6690. var localPos = this.transformCoordToLocal(x, y);
  6691. var rect = this.getBoundingRect();
  6692. var style = this.style;
  6693. x = localPos[0];
  6694. y = localPos[1];
  6695. if (rect.contain(x, y)) {
  6696. var pathData = this.path.data;
  6697. if (style.hasStroke()) {
  6698. var lineWidth = style.lineWidth;
  6699. var lineScale = style.strokeNoScale ? this.getLineScale() : 1;
  6700. // Line scale can't be 0;
  6701. if (lineScale > 1e-10) {
  6702. // Only add extra hover lineWidth when there are no fill
  6703. if (!style.hasFill()) {
  6704. lineWidth = Math.max(lineWidth, this.strokeContainThreshold);
  6705. }
  6706. if (pathContain.containStroke(
  6707. pathData, lineWidth / lineScale, x, y
  6708. )) {
  6709. return true;
  6710. }
  6711. }
  6712. }
  6713. if (style.hasFill()) {
  6714. return pathContain.contain(pathData, x, y);
  6715. }
  6716. }
  6717. return false;
  6718. },
  6719. /**
  6720. * @param {boolean} dirtyPath
  6721. */
  6722. dirty: function (dirtyPath) {
  6723. if (dirtyPath == null) {
  6724. dirtyPath = true;
  6725. }
  6726. // Only mark dirty, not mark clean
  6727. if (dirtyPath) {
  6728. this.__dirtyPath = dirtyPath;
  6729. this._rect = null;
  6730. }
  6731. this.__dirty = true;
  6732. this.__zr && this.__zr.refresh();
  6733. // Used as a clipping path
  6734. if (this.__clipTarget) {
  6735. this.__clipTarget.dirty();
  6736. }
  6737. },
  6738. /**
  6739. * Alias for animate('shape')
  6740. * @param {boolean} loop
  6741. */
  6742. animateShape: function (loop) {
  6743. return this.animate('shape', loop);
  6744. },
  6745. // Overwrite attrKV
  6746. attrKV: function (key, value) {
  6747. // FIXME
  6748. if (key === 'shape') {
  6749. this.setShape(value);
  6750. this.__dirtyPath = true;
  6751. this._rect = null;
  6752. }
  6753. else {
  6754. Displayable.prototype.attrKV.call(this, key, value);
  6755. }
  6756. },
  6757. /**
  6758. * @param {Object|string} key
  6759. * @param {*} value
  6760. */
  6761. setShape: function (key, value) {
  6762. var shape = this.shape;
  6763. // Path from string may not have shape
  6764. if (shape) {
  6765. if (zrUtil.isObject(key)) {
  6766. for (var name in key) {
  6767. if (key.hasOwnProperty(name)) {
  6768. shape[name] = key[name];
  6769. }
  6770. }
  6771. }
  6772. else {
  6773. shape[key] = value;
  6774. }
  6775. this.dirty(true);
  6776. }
  6777. return this;
  6778. },
  6779. getLineScale: function () {
  6780. var m = this.transform;
  6781. // Get the line scale.
  6782. // Determinant of `m` means how much the area is enlarged by the
  6783. // transformation. So its square root can be used as a scale factor
  6784. // for width.
  6785. return m && abs(m[0] - 1) > 1e-10 && abs(m[3] - 1) > 1e-10
  6786. ? Math.sqrt(abs(m[0] * m[3] - m[2] * m[1]))
  6787. : 1;
  6788. }
  6789. };
  6790. /**
  6791. * 扩展一个 Path element, 比如星形,圆等。
  6792. * Extend a path element
  6793. * @param {Object} props
  6794. * @param {string} props.type Path type
  6795. * @param {Function} props.init Initialize
  6796. * @param {Function} props.buildPath Overwrite buildPath method
  6797. * @param {Object} [props.style] Extended default style config
  6798. * @param {Object} [props.shape] Extended default shape config
  6799. */
  6800. Path.extend = function (defaults) {
  6801. var Sub = function (opts) {
  6802. Path.call(this, opts);
  6803. if (defaults.style) {
  6804. // Extend default style
  6805. this.style.extendFrom(defaults.style, false);
  6806. }
  6807. // Extend default shape
  6808. var defaultShape = defaults.shape;
  6809. if (defaultShape) {
  6810. this.shape = this.shape || {};
  6811. var thisShape = this.shape;
  6812. for (var name in defaultShape) {
  6813. if (
  6814. ! thisShape.hasOwnProperty(name)
  6815. && defaultShape.hasOwnProperty(name)
  6816. ) {
  6817. thisShape[name] = defaultShape[name];
  6818. }
  6819. }
  6820. }
  6821. defaults.init && defaults.init.call(this, opts);
  6822. };
  6823. zrUtil.inherits(Sub, Path);
  6824. // FIXME 不能 extend position, rotation 等引用对象
  6825. for (var name in defaults) {
  6826. // Extending prototype values and methods
  6827. if (name !== 'style' && name !== 'shape') {
  6828. Sub.prototype[name] = defaults[name];
  6829. }
  6830. }
  6831. return Sub;
  6832. };
  6833. zrUtil.inherits(Path, Displayable);
  6834. module.exports = Path;
  6835. /***/ },
  6836. /* 21 */
  6837. /***/ function(module, exports, __webpack_require__) {
  6838. /**
  6839. * 可绘制的图形基类
  6840. * Base class of all displayable graphic objects
  6841. * @module zrender/graphic/Displayable
  6842. */
  6843. var zrUtil = __webpack_require__(4);
  6844. var Style = __webpack_require__(22);
  6845. var Element = __webpack_require__(23);
  6846. var RectText = __webpack_require__(35);
  6847. // var Stateful = require('./mixin/Stateful');
  6848. /**
  6849. * @alias module:zrender/graphic/Displayable
  6850. * @extends module:zrender/Element
  6851. * @extends module:zrender/graphic/mixin/RectText
  6852. */
  6853. function Displayable(opts) {
  6854. opts = opts || {};
  6855. Element.call(this, opts);
  6856. // Extend properties
  6857. for (var name in opts) {
  6858. if (
  6859. opts.hasOwnProperty(name) &&
  6860. name !== 'style'
  6861. ) {
  6862. this[name] = opts[name];
  6863. }
  6864. }
  6865. /**
  6866. * @type {module:zrender/graphic/Style}
  6867. */
  6868. this.style = new Style(opts.style);
  6869. this._rect = null;
  6870. // Shapes for cascade clipping.
  6871. this.__clipPaths = [];
  6872. // FIXME Stateful must be mixined after style is setted
  6873. // Stateful.call(this, opts);
  6874. }
  6875. Displayable.prototype = {
  6876. constructor: Displayable,
  6877. type: 'displayable',
  6878. /**
  6879. * Displayable 是否为脏,Painter 中会根据该标记判断是否需要是否需要重新绘制
  6880. * Dirty flag. From which painter will determine if this displayable object needs brush
  6881. * @name module:zrender/graphic/Displayable#__dirty
  6882. * @type {boolean}
  6883. */
  6884. __dirty: true,
  6885. /**
  6886. * 图形是否可见,为true时不绘制图形,但是仍能触发鼠标事件
  6887. * If ignore drawing of the displayable object. Mouse event will still be triggered
  6888. * @name module:/zrender/graphic/Displayable#invisible
  6889. * @type {boolean}
  6890. * @default false
  6891. */
  6892. invisible: false,
  6893. /**
  6894. * @name module:/zrender/graphic/Displayable#z
  6895. * @type {number}
  6896. * @default 0
  6897. */
  6898. z: 0,
  6899. /**
  6900. * @name module:/zrender/graphic/Displayable#z
  6901. * @type {number}
  6902. * @default 0
  6903. */
  6904. z2: 0,
  6905. /**
  6906. * z层level,决定绘画在哪层canvas中
  6907. * @name module:/zrender/graphic/Displayable#zlevel
  6908. * @type {number}
  6909. * @default 0
  6910. */
  6911. zlevel: 0,
  6912. /**
  6913. * 是否可拖拽
  6914. * @name module:/zrender/graphic/Displayable#draggable
  6915. * @type {boolean}
  6916. * @default false
  6917. */
  6918. draggable: false,
  6919. /**
  6920. * 是否正在拖拽
  6921. * @name module:/zrender/graphic/Displayable#draggable
  6922. * @type {boolean}
  6923. * @default false
  6924. */
  6925. dragging: false,
  6926. /**
  6927. * 是否相应鼠标事件
  6928. * @name module:/zrender/graphic/Displayable#silent
  6929. * @type {boolean}
  6930. * @default false
  6931. */
  6932. silent: false,
  6933. /**
  6934. * If enable culling
  6935. * @type {boolean}
  6936. * @default false
  6937. */
  6938. culling: false,
  6939. /**
  6940. * Mouse cursor when hovered
  6941. * @name module:/zrender/graphic/Displayable#cursor
  6942. * @type {string}
  6943. */
  6944. cursor: 'pointer',
  6945. /**
  6946. * If hover area is bounding rect
  6947. * @name module:/zrender/graphic/Displayable#rectHover
  6948. * @type {string}
  6949. */
  6950. rectHover: false,
  6951. /**
  6952. * Render the element progressively when the value >= 0,
  6953. * usefull for large data.
  6954. * @type {number}
  6955. */
  6956. progressive: -1,
  6957. beforeBrush: function (ctx) {},
  6958. afterBrush: function (ctx) {},
  6959. /**
  6960. * 图形绘制方法
  6961. * @param {Canvas2DRenderingContext} ctx
  6962. */
  6963. // Interface
  6964. brush: function (ctx, prevEl) {},
  6965. /**
  6966. * 获取最小包围盒
  6967. * @return {module:zrender/core/BoundingRect}
  6968. */
  6969. // Interface
  6970. getBoundingRect: function () {},
  6971. /**
  6972. * 判断坐标 x, y 是否在图形上
  6973. * If displayable element contain coord x, y
  6974. * @param {number} x
  6975. * @param {number} y
  6976. * @return {boolean}
  6977. */
  6978. contain: function (x, y) {
  6979. return this.rectContain(x, y);
  6980. },
  6981. /**
  6982. * @param {Function} cb
  6983. * @param {} context
  6984. */
  6985. traverse: function (cb, context) {
  6986. cb.call(context, this);
  6987. },
  6988. /**
  6989. * 判断坐标 x, y 是否在图形的包围盒上
  6990. * If bounding rect of element contain coord x, y
  6991. * @param {number} x
  6992. * @param {number} y
  6993. * @return {boolean}
  6994. */
  6995. rectContain: function (x, y) {
  6996. var coord = this.transformCoordToLocal(x, y);
  6997. var rect = this.getBoundingRect();
  6998. return rect.contain(coord[0], coord[1]);
  6999. },
  7000. /**
  7001. * 标记图形元素为脏,并且在下一帧重绘
  7002. * Mark displayable element dirty and refresh next frame
  7003. */
  7004. dirty: function () {
  7005. this.__dirty = true;
  7006. this._rect = null;
  7007. this.__zr && this.__zr.refresh();
  7008. },
  7009. /**
  7010. * 图形是否会触发事件
  7011. * If displayable object binded any event
  7012. * @return {boolean}
  7013. */
  7014. // TODO, 通过 bind 绑定的事件
  7015. // isSilent: function () {
  7016. // return !(
  7017. // this.hoverable || this.draggable
  7018. // || this.onmousemove || this.onmouseover || this.onmouseout
  7019. // || this.onmousedown || this.onmouseup || this.onclick
  7020. // || this.ondragenter || this.ondragover || this.ondragleave
  7021. // || this.ondrop
  7022. // );
  7023. // },
  7024. /**
  7025. * Alias for animate('style')
  7026. * @param {boolean} loop
  7027. */
  7028. animateStyle: function (loop) {
  7029. return this.animate('style', loop);
  7030. },
  7031. attrKV: function (key, value) {
  7032. if (key !== 'style') {
  7033. Element.prototype.attrKV.call(this, key, value);
  7034. }
  7035. else {
  7036. this.style.set(value);
  7037. }
  7038. },
  7039. /**
  7040. * @param {Object|string} key
  7041. * @param {*} value
  7042. */
  7043. setStyle: function (key, value) {
  7044. this.style.set(key, value);
  7045. this.dirty(false);
  7046. return this;
  7047. },
  7048. /**
  7049. * Use given style object
  7050. * @param {Object} obj
  7051. */
  7052. useStyle: function (obj) {
  7053. this.style = new Style(obj);
  7054. this.dirty(false);
  7055. return this;
  7056. }
  7057. };
  7058. zrUtil.inherits(Displayable, Element);
  7059. zrUtil.mixin(Displayable, RectText);
  7060. // zrUtil.mixin(Displayable, Stateful);
  7061. module.exports = Displayable;
  7062. /***/ },
  7063. /* 22 */
  7064. /***/ function(module, exports) {
  7065. /**
  7066. * @module zrender/graphic/Style
  7067. */
  7068. var STYLE_COMMON_PROPS = [
  7069. ['shadowBlur', 0], ['shadowOffsetX', 0], ['shadowOffsetY', 0], ['shadowColor', '#000'],
  7070. ['lineCap', 'butt'], ['lineJoin', 'miter'], ['miterLimit', 10]
  7071. ];
  7072. // var SHADOW_PROPS = STYLE_COMMON_PROPS.slice(0, 4);
  7073. // var LINE_PROPS = STYLE_COMMON_PROPS.slice(4);
  7074. var Style = function (opts) {
  7075. this.extendFrom(opts);
  7076. };
  7077. function createLinearGradient(ctx, obj, rect) {
  7078. var x = obj.x == null ? 0 : obj.x;
  7079. var x2 = obj.x2 == null ? 1 : obj.x2;
  7080. var y = obj.y == null ? 0 : obj.y;
  7081. var y2 = obj.y2 == null ? 0 : obj.y2;
  7082. if (!obj.global) {
  7083. x = x * rect.width + rect.x;
  7084. x2 = x2 * rect.width + rect.x;
  7085. y = y * rect.height + rect.y;
  7086. y2 = y2 * rect.height + rect.y;
  7087. }
  7088. var canvasGradient = ctx.createLinearGradient(x, y, x2, y2);
  7089. return canvasGradient;
  7090. }
  7091. function createRadialGradient(ctx, obj, rect) {
  7092. var width = rect.width;
  7093. var height = rect.height;
  7094. var min = Math.min(width, height);
  7095. var x = obj.x == null ? 0.5 : obj.x;
  7096. var y = obj.y == null ? 0.5 : obj.y;
  7097. var r = obj.r == null ? 0.5 : obj.r;
  7098. if (!obj.global) {
  7099. x = x * width + rect.x;
  7100. y = y * height + rect.y;
  7101. r = r * min;
  7102. }
  7103. var canvasGradient = ctx.createRadialGradient(x, y, 0, x, y, r);
  7104. return canvasGradient;
  7105. }
  7106. Style.prototype = {
  7107. constructor: Style,
  7108. /**
  7109. * @type {string}
  7110. */
  7111. fill: '#000000',
  7112. /**
  7113. * @type {string}
  7114. */
  7115. stroke: null,
  7116. /**
  7117. * @type {number}
  7118. */
  7119. opacity: 1,
  7120. /**
  7121. * @type {Array.<number>}
  7122. */
  7123. lineDash: null,
  7124. /**
  7125. * @type {number}
  7126. */
  7127. lineDashOffset: 0,
  7128. /**
  7129. * @type {number}
  7130. */
  7131. shadowBlur: 0,
  7132. /**
  7133. * @type {number}
  7134. */
  7135. shadowOffsetX: 0,
  7136. /**
  7137. * @type {number}
  7138. */
  7139. shadowOffsetY: 0,
  7140. /**
  7141. * @type {number}
  7142. */
  7143. lineWidth: 1,
  7144. /**
  7145. * If stroke ignore scale
  7146. * @type {Boolean}
  7147. */
  7148. strokeNoScale: false,
  7149. // Bounding rect text configuration
  7150. // Not affected by element transform
  7151. /**
  7152. * @type {string}
  7153. */
  7154. text: null,
  7155. /**
  7156. * @type {string}
  7157. */
  7158. textFill: '#000',
  7159. /**
  7160. * @type {string}
  7161. */
  7162. textStroke: null,
  7163. /**
  7164. * 'inside', 'left', 'right', 'top', 'bottom'
  7165. * [x, y]
  7166. * @type {string|Array.<number>}
  7167. * @default 'inside'
  7168. */
  7169. textPosition: 'inside',
  7170. /**
  7171. * [x, y]
  7172. * @type {Array.<number>}
  7173. */
  7174. textOffset: null,
  7175. /**
  7176. * @type {string}
  7177. */
  7178. textBaseline: null,
  7179. /**
  7180. * @type {string}
  7181. */
  7182. textAlign: null,
  7183. /**
  7184. * @type {string}
  7185. */
  7186. textVerticalAlign: null,
  7187. /**
  7188. * Only useful in Path and Image element
  7189. * @type {number}
  7190. */
  7191. textDistance: 5,
  7192. /**
  7193. * Only useful in Path and Image element
  7194. * @type {number}
  7195. */
  7196. textShadowBlur: 0,
  7197. /**
  7198. * Only useful in Path and Image element
  7199. * @type {number}
  7200. */
  7201. textShadowOffsetX: 0,
  7202. /**
  7203. * Only useful in Path and Image element
  7204. * @type {number}
  7205. */
  7206. textShadowOffsetY: 0,
  7207. /**
  7208. * If transform text
  7209. * Only useful in Path and Image element
  7210. * @type {boolean}
  7211. */
  7212. textTransform: false,
  7213. /**
  7214. * Text rotate around position of Path or Image
  7215. * Only useful in Path and Image element and textTransform is false.
  7216. */
  7217. textRotation: 0,
  7218. /**
  7219. * @type {string}
  7220. * https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
  7221. */
  7222. blend: null,
  7223. /**
  7224. * @param {CanvasRenderingContext2D} ctx
  7225. */
  7226. bind: function (ctx, el, prevEl) {
  7227. var style = this;
  7228. var prevStyle = prevEl && prevEl.style;
  7229. var firstDraw = !prevStyle;
  7230. for (var i = 0; i < STYLE_COMMON_PROPS.length; i++) {
  7231. var prop = STYLE_COMMON_PROPS[i];
  7232. var styleName = prop[0];
  7233. if (firstDraw || style[styleName] !== prevStyle[styleName]) {
  7234. // FIXME Invalid property value will cause style leak from previous element.
  7235. ctx[styleName] = style[styleName] || prop[1];
  7236. }
  7237. }
  7238. if ((firstDraw || style.fill !== prevStyle.fill)) {
  7239. ctx.fillStyle = style.fill;
  7240. }
  7241. if ((firstDraw || style.stroke !== prevStyle.stroke)) {
  7242. ctx.strokeStyle = style.stroke;
  7243. }
  7244. if ((firstDraw || style.opacity !== prevStyle.opacity)) {
  7245. ctx.globalAlpha = style.opacity == null ? 1 : style.opacity;
  7246. }
  7247. if ((firstDraw || style.blend !== prevStyle.blend)) {
  7248. ctx.globalCompositeOperation = style.blend || 'source-over';
  7249. }
  7250. if (this.hasStroke()) {
  7251. var lineWidth = style.lineWidth;
  7252. ctx.lineWidth = lineWidth / (
  7253. (this.strokeNoScale && el && el.getLineScale) ? el.getLineScale() : 1
  7254. );
  7255. }
  7256. },
  7257. hasFill: function () {
  7258. var fill = this.fill;
  7259. return fill != null && fill !== 'none';
  7260. },
  7261. hasStroke: function () {
  7262. var stroke = this.stroke;
  7263. return stroke != null && stroke !== 'none' && this.lineWidth > 0;
  7264. },
  7265. /**
  7266. * Extend from other style
  7267. * @param {zrender/graphic/Style} otherStyle
  7268. * @param {boolean} overwrite
  7269. */
  7270. extendFrom: function (otherStyle, overwrite) {
  7271. if (otherStyle) {
  7272. var target = this;
  7273. for (var name in otherStyle) {
  7274. if (otherStyle.hasOwnProperty(name)
  7275. && (overwrite || ! target.hasOwnProperty(name))
  7276. ) {
  7277. target[name] = otherStyle[name];
  7278. }
  7279. }
  7280. }
  7281. },
  7282. /**
  7283. * Batch setting style with a given object
  7284. * @param {Object|string} obj
  7285. * @param {*} [obj]
  7286. */
  7287. set: function (obj, value) {
  7288. if (typeof obj === 'string') {
  7289. this[obj] = value;
  7290. }
  7291. else {
  7292. this.extendFrom(obj, true);
  7293. }
  7294. },
  7295. /**
  7296. * Clone
  7297. * @return {zrender/graphic/Style} [description]
  7298. */
  7299. clone: function () {
  7300. var newStyle = new this.constructor();
  7301. newStyle.extendFrom(this, true);
  7302. return newStyle;
  7303. },
  7304. getGradient: function (ctx, obj, rect) {
  7305. var method = obj.type === 'radial' ? createRadialGradient : createLinearGradient;
  7306. var canvasGradient = method(ctx, obj, rect);
  7307. var colorStops = obj.colorStops;
  7308. for (var i = 0; i < colorStops.length; i++) {
  7309. canvasGradient.addColorStop(
  7310. colorStops[i].offset, colorStops[i].color
  7311. );
  7312. }
  7313. return canvasGradient;
  7314. }
  7315. };
  7316. var styleProto = Style.prototype;
  7317. for (var i = 0; i < STYLE_COMMON_PROPS.length; i++) {
  7318. var prop = STYLE_COMMON_PROPS[i];
  7319. if (!(prop[0] in styleProto)) {
  7320. styleProto[prop[0]] = prop[1];
  7321. }
  7322. }
  7323. // Provide for others
  7324. Style.getGradient = styleProto.getGradient;
  7325. module.exports = Style;
  7326. /***/ },
  7327. /* 23 */
  7328. /***/ function(module, exports, __webpack_require__) {
  7329. 'use strict';
  7330. /**
  7331. * @module zrender/Element
  7332. */
  7333. var guid = __webpack_require__(24);
  7334. var Eventful = __webpack_require__(25);
  7335. var Transformable = __webpack_require__(26);
  7336. var Animatable = __webpack_require__(27);
  7337. var zrUtil = __webpack_require__(4);
  7338. /**
  7339. * @alias module:zrender/Element
  7340. * @constructor
  7341. * @extends {module:zrender/mixin/Animatable}
  7342. * @extends {module:zrender/mixin/Transformable}
  7343. * @extends {module:zrender/mixin/Eventful}
  7344. */
  7345. var Element = function (opts) {
  7346. Transformable.call(this, opts);
  7347. Eventful.call(this, opts);
  7348. Animatable.call(this, opts);
  7349. /**
  7350. * 画布元素ID
  7351. * @type {string}
  7352. */
  7353. this.id = opts.id || guid();
  7354. };
  7355. Element.prototype = {
  7356. /**
  7357. * 元素类型
  7358. * Element type
  7359. * @type {string}
  7360. */
  7361. type: 'element',
  7362. /**
  7363. * 元素名字
  7364. * Element name
  7365. * @type {string}
  7366. */
  7367. name: '',
  7368. /**
  7369. * ZRender 实例对象,会在 element 添加到 zrender 实例中后自动赋值
  7370. * ZRender instance will be assigned when element is associated with zrender
  7371. * @name module:/zrender/Element#__zr
  7372. * @type {module:zrender/ZRender}
  7373. */
  7374. __zr: null,
  7375. /**
  7376. * 图形是否忽略,为true时忽略图形的绘制以及事件触发
  7377. * If ignore drawing and events of the element object
  7378. * @name module:/zrender/Element#ignore
  7379. * @type {boolean}
  7380. * @default false
  7381. */
  7382. ignore: false,
  7383. /**
  7384. * 用于裁剪的路径(shape),所有 Group 内的路径在绘制时都会被这个路径裁剪
  7385. * 该路径会继承被裁减对象的变换
  7386. * @type {module:zrender/graphic/Path}
  7387. * @see http://www.w3.org/TR/2dcontext/#clipping-region
  7388. * @readOnly
  7389. */
  7390. clipPath: null,
  7391. /**
  7392. * Drift element
  7393. * @param {number} dx dx on the global space
  7394. * @param {number} dy dy on the global space
  7395. */
  7396. drift: function (dx, dy) {
  7397. switch (this.draggable) {
  7398. case 'horizontal':
  7399. dy = 0;
  7400. break;
  7401. case 'vertical':
  7402. dx = 0;
  7403. break;
  7404. }
  7405. var m = this.transform;
  7406. if (!m) {
  7407. m = this.transform = [1, 0, 0, 1, 0, 0];
  7408. }
  7409. m[4] += dx;
  7410. m[5] += dy;
  7411. this.decomposeTransform();
  7412. this.dirty(false);
  7413. },
  7414. /**
  7415. * Hook before update
  7416. */
  7417. beforeUpdate: function () {},
  7418. /**
  7419. * Hook after update
  7420. */
  7421. afterUpdate: function () {},
  7422. /**
  7423. * Update each frame
  7424. */
  7425. update: function () {
  7426. this.updateTransform();
  7427. },
  7428. /**
  7429. * @param {Function} cb
  7430. * @param {} context
  7431. */
  7432. traverse: function (cb, context) {},
  7433. /**
  7434. * @protected
  7435. */
  7436. attrKV: function (key, value) {
  7437. if (key === 'position' || key === 'scale' || key === 'origin') {
  7438. // Copy the array
  7439. if (value) {
  7440. var target = this[key];
  7441. if (!target) {
  7442. target = this[key] = [];
  7443. }
  7444. target[0] = value[0];
  7445. target[1] = value[1];
  7446. }
  7447. }
  7448. else {
  7449. this[key] = value;
  7450. }
  7451. },
  7452. /**
  7453. * Hide the element
  7454. */
  7455. hide: function () {
  7456. this.ignore = true;
  7457. this.__zr && this.__zr.refresh();
  7458. },
  7459. /**
  7460. * Show the element
  7461. */
  7462. show: function () {
  7463. this.ignore = false;
  7464. this.__zr && this.__zr.refresh();
  7465. },
  7466. /**
  7467. * @param {string|Object} key
  7468. * @param {*} value
  7469. */
  7470. attr: function (key, value) {
  7471. if (typeof key === 'string') {
  7472. this.attrKV(key, value);
  7473. }
  7474. else if (zrUtil.isObject(key)) {
  7475. for (var name in key) {
  7476. if (key.hasOwnProperty(name)) {
  7477. this.attrKV(name, key[name]);
  7478. }
  7479. }
  7480. }
  7481. this.dirty(false);
  7482. return this;
  7483. },
  7484. /**
  7485. * @param {module:zrender/graphic/Path} clipPath
  7486. */
  7487. setClipPath: function (clipPath) {
  7488. var zr = this.__zr;
  7489. if (zr) {
  7490. clipPath.addSelfToZr(zr);
  7491. }
  7492. // Remove previous clip path
  7493. if (this.clipPath && this.clipPath !== clipPath) {
  7494. this.removeClipPath();
  7495. }
  7496. this.clipPath = clipPath;
  7497. clipPath.__zr = zr;
  7498. clipPath.__clipTarget = this;
  7499. this.dirty(false);
  7500. },
  7501. /**
  7502. */
  7503. removeClipPath: function () {
  7504. var clipPath = this.clipPath;
  7505. if (clipPath) {
  7506. if (clipPath.__zr) {
  7507. clipPath.removeSelfFromZr(clipPath.__zr);
  7508. }
  7509. clipPath.__zr = null;
  7510. clipPath.__clipTarget = null;
  7511. this.clipPath = null;
  7512. this.dirty(false);
  7513. }
  7514. },
  7515. /**
  7516. * Add self from zrender instance.
  7517. * Not recursively because it will be invoked when element added to storage.
  7518. * @param {module:zrender/ZRender} zr
  7519. */
  7520. addSelfToZr: function (zr) {
  7521. this.__zr = zr;
  7522. // 添加动画
  7523. var animators = this.animators;
  7524. if (animators) {
  7525. for (var i = 0; i < animators.length; i++) {
  7526. zr.animation.addAnimator(animators[i]);
  7527. }
  7528. }
  7529. if (this.clipPath) {
  7530. this.clipPath.addSelfToZr(zr);
  7531. }
  7532. },
  7533. /**
  7534. * Remove self from zrender instance.
  7535. * Not recursively because it will be invoked when element added to storage.
  7536. * @param {module:zrender/ZRender} zr
  7537. */
  7538. removeSelfFromZr: function (zr) {
  7539. this.__zr = null;
  7540. // 移除动画
  7541. var animators = this.animators;
  7542. if (animators) {
  7543. for (var i = 0; i < animators.length; i++) {
  7544. zr.animation.removeAnimator(animators[i]);
  7545. }
  7546. }
  7547. if (this.clipPath) {
  7548. this.clipPath.removeSelfFromZr(zr);
  7549. }
  7550. }
  7551. };
  7552. zrUtil.mixin(Element, Animatable);
  7553. zrUtil.mixin(Element, Transformable);
  7554. zrUtil.mixin(Element, Eventful);
  7555. module.exports = Element;
  7556. /***/ },
  7557. /* 24 */
  7558. /***/ function(module, exports) {
  7559. /**
  7560. * zrender: 生成唯一id
  7561. *
  7562. * @author errorrik (errorrik@gmail.com)
  7563. */
  7564. var idStart = 0x0907;
  7565. module.exports = function () {
  7566. return idStart++;
  7567. };
  7568. /***/ },
  7569. /* 25 */
  7570. /***/ function(module, exports) {
  7571. /**
  7572. * 事件扩展
  7573. * @module zrender/mixin/Eventful
  7574. * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
  7575. * pissang (https://www.github.com/pissang)
  7576. */
  7577. var arrySlice = Array.prototype.slice;
  7578. /**
  7579. * 事件分发器
  7580. * @alias module:zrender/mixin/Eventful
  7581. * @constructor
  7582. */
  7583. var Eventful = function () {
  7584. this._$handlers = {};
  7585. };
  7586. Eventful.prototype = {
  7587. constructor: Eventful,
  7588. /**
  7589. * 单次触发绑定,trigger后销毁
  7590. *
  7591. * @param {string} event 事件名
  7592. * @param {Function} handler 响应函数
  7593. * @param {Object} context
  7594. */
  7595. one: function (event, handler, context) {
  7596. var _h = this._$handlers;
  7597. if (!handler || !event) {
  7598. return this;
  7599. }
  7600. if (!_h[event]) {
  7601. _h[event] = [];
  7602. }
  7603. for (var i = 0; i < _h[event].length; i++) {
  7604. if (_h[event][i].h === handler) {
  7605. return this;
  7606. }
  7607. }
  7608. _h[event].push({
  7609. h: handler,
  7610. one: true,
  7611. ctx: context || this
  7612. });
  7613. return this;
  7614. },
  7615. /**
  7616. * 绑定事件
  7617. * @param {string} event 事件名
  7618. * @param {Function} handler 事件处理函数
  7619. * @param {Object} [context]
  7620. */
  7621. on: function (event, handler, context) {
  7622. var _h = this._$handlers;
  7623. if (!handler || !event) {
  7624. return this;
  7625. }
  7626. if (!_h[event]) {
  7627. _h[event] = [];
  7628. }
  7629. for (var i = 0; i < _h[event].length; i++) {
  7630. if (_h[event][i].h === handler) {
  7631. return this;
  7632. }
  7633. }
  7634. _h[event].push({
  7635. h: handler,
  7636. one: false,
  7637. ctx: context || this
  7638. });
  7639. return this;
  7640. },
  7641. /**
  7642. * 是否绑定了事件
  7643. * @param {string} event
  7644. * @return {boolean}
  7645. */
  7646. isSilent: function (event) {
  7647. var _h = this._$handlers;
  7648. return _h[event] && _h[event].length;
  7649. },
  7650. /**
  7651. * 解绑事件
  7652. * @param {string} event 事件名
  7653. * @param {Function} [handler] 事件处理函数
  7654. */
  7655. off: function (event, handler) {
  7656. var _h = this._$handlers;
  7657. if (!event) {
  7658. this._$handlers = {};
  7659. return this;
  7660. }
  7661. if (handler) {
  7662. if (_h[event]) {
  7663. var newList = [];
  7664. for (var i = 0, l = _h[event].length; i < l; i++) {
  7665. if (_h[event][i]['h'] != handler) {
  7666. newList.push(_h[event][i]);
  7667. }
  7668. }
  7669. _h[event] = newList;
  7670. }
  7671. if (_h[event] && _h[event].length === 0) {
  7672. delete _h[event];
  7673. }
  7674. }
  7675. else {
  7676. delete _h[event];
  7677. }
  7678. return this;
  7679. },
  7680. /**
  7681. * 事件分发
  7682. *
  7683. * @param {string} type 事件类型
  7684. */
  7685. trigger: function (type) {
  7686. if (this._$handlers[type]) {
  7687. var args = arguments;
  7688. var argLen = args.length;
  7689. if (argLen > 3) {
  7690. args = arrySlice.call(args, 1);
  7691. }
  7692. var _h = this._$handlers[type];
  7693. var len = _h.length;
  7694. for (var i = 0; i < len;) {
  7695. // Optimize advise from backbone
  7696. switch (argLen) {
  7697. case 1:
  7698. _h[i]['h'].call(_h[i]['ctx']);
  7699. break;
  7700. case 2:
  7701. _h[i]['h'].call(_h[i]['ctx'], args[1]);
  7702. break;
  7703. case 3:
  7704. _h[i]['h'].call(_h[i]['ctx'], args[1], args[2]);
  7705. break;
  7706. default:
  7707. // have more than 2 given arguments
  7708. _h[i]['h'].apply(_h[i]['ctx'], args);
  7709. break;
  7710. }
  7711. if (_h[i]['one']) {
  7712. _h.splice(i, 1);
  7713. len--;
  7714. }
  7715. else {
  7716. i++;
  7717. }
  7718. }
  7719. }
  7720. return this;
  7721. },
  7722. /**
  7723. * 带有context的事件分发, 最后一个参数是事件回调的context
  7724. * @param {string} type 事件类型
  7725. */
  7726. triggerWithContext: function (type) {
  7727. if (this._$handlers[type]) {
  7728. var args = arguments;
  7729. var argLen = args.length;
  7730. if (argLen > 4) {
  7731. args = arrySlice.call(args, 1, args.length - 1);
  7732. }
  7733. var ctx = args[args.length - 1];
  7734. var _h = this._$handlers[type];
  7735. var len = _h.length;
  7736. for (var i = 0; i < len;) {
  7737. // Optimize advise from backbone
  7738. switch (argLen) {
  7739. case 1:
  7740. _h[i]['h'].call(ctx);
  7741. break;
  7742. case 2:
  7743. _h[i]['h'].call(ctx, args[1]);
  7744. break;
  7745. case 3:
  7746. _h[i]['h'].call(ctx, args[1], args[2]);
  7747. break;
  7748. default:
  7749. // have more than 2 given arguments
  7750. _h[i]['h'].apply(ctx, args);
  7751. break;
  7752. }
  7753. if (_h[i]['one']) {
  7754. _h.splice(i, 1);
  7755. len--;
  7756. }
  7757. else {
  7758. i++;
  7759. }
  7760. }
  7761. }
  7762. return this;
  7763. }
  7764. };
  7765. // 对象可以通过 onxxxx 绑定事件
  7766. /**
  7767. * @event module:zrender/mixin/Eventful#onclick
  7768. * @type {Function}
  7769. * @default null
  7770. */
  7771. /**
  7772. * @event module:zrender/mixin/Eventful#onmouseover
  7773. * @type {Function}
  7774. * @default null
  7775. */
  7776. /**
  7777. * @event module:zrender/mixin/Eventful#onmouseout
  7778. * @type {Function}
  7779. * @default null
  7780. */
  7781. /**
  7782. * @event module:zrender/mixin/Eventful#onmousemove
  7783. * @type {Function}
  7784. * @default null
  7785. */
  7786. /**
  7787. * @event module:zrender/mixin/Eventful#onmousewheel
  7788. * @type {Function}
  7789. * @default null
  7790. */
  7791. /**
  7792. * @event module:zrender/mixin/Eventful#onmousedown
  7793. * @type {Function}
  7794. * @default null
  7795. */
  7796. /**
  7797. * @event module:zrender/mixin/Eventful#onmouseup
  7798. * @type {Function}
  7799. * @default null
  7800. */
  7801. /**
  7802. * @event module:zrender/mixin/Eventful#ondrag
  7803. * @type {Function}
  7804. * @default null
  7805. */
  7806. /**
  7807. * @event module:zrender/mixin/Eventful#ondragstart
  7808. * @type {Function}
  7809. * @default null
  7810. */
  7811. /**
  7812. * @event module:zrender/mixin/Eventful#ondragend
  7813. * @type {Function}
  7814. * @default null
  7815. */
  7816. /**
  7817. * @event module:zrender/mixin/Eventful#ondragenter
  7818. * @type {Function}
  7819. * @default null
  7820. */
  7821. /**
  7822. * @event module:zrender/mixin/Eventful#ondragleave
  7823. * @type {Function}
  7824. * @default null
  7825. */
  7826. /**
  7827. * @event module:zrender/mixin/Eventful#ondragover
  7828. * @type {Function}
  7829. * @default null
  7830. */
  7831. /**
  7832. * @event module:zrender/mixin/Eventful#ondrop
  7833. * @type {Function}
  7834. * @default null
  7835. */
  7836. module.exports = Eventful;
  7837. /***/ },
  7838. /* 26 */
  7839. /***/ function(module, exports, __webpack_require__) {
  7840. 'use strict';
  7841. /**
  7842. * 提供变换扩展
  7843. * @module zrender/mixin/Transformable
  7844. * @author pissang (https://www.github.com/pissang)
  7845. */
  7846. var matrix = __webpack_require__(11);
  7847. var vector = __webpack_require__(10);
  7848. var mIdentity = matrix.identity;
  7849. var EPSILON = 5e-5;
  7850. function isNotAroundZero(val) {
  7851. return val > EPSILON || val < -EPSILON;
  7852. }
  7853. /**
  7854. * @alias module:zrender/mixin/Transformable
  7855. * @constructor
  7856. */
  7857. var Transformable = function (opts) {
  7858. opts = opts || {};
  7859. // If there are no given position, rotation, scale
  7860. if (!opts.position) {
  7861. /**
  7862. * 平移
  7863. * @type {Array.<number>}
  7864. * @default [0, 0]
  7865. */
  7866. this.position = [0, 0];
  7867. }
  7868. if (opts.rotation == null) {
  7869. /**
  7870. * 旋转
  7871. * @type {Array.<number>}
  7872. * @default 0
  7873. */
  7874. this.rotation = 0;
  7875. }
  7876. if (!opts.scale) {
  7877. /**
  7878. * 缩放
  7879. * @type {Array.<number>}
  7880. * @default [1, 1]
  7881. */
  7882. this.scale = [1, 1];
  7883. }
  7884. /**
  7885. * 旋转和缩放的原点
  7886. * @type {Array.<number>}
  7887. * @default null
  7888. */
  7889. this.origin = this.origin || null;
  7890. };
  7891. var transformableProto = Transformable.prototype;
  7892. transformableProto.transform = null;
  7893. /**
  7894. * 判断是否需要有坐标变换
  7895. * 如果有坐标变换, 则从position, rotation, scale以及父节点的transform计算出自身的transform矩阵
  7896. */
  7897. transformableProto.needLocalTransform = function () {
  7898. return isNotAroundZero(this.rotation)
  7899. || isNotAroundZero(this.position[0])
  7900. || isNotAroundZero(this.position[1])
  7901. || isNotAroundZero(this.scale[0] - 1)
  7902. || isNotAroundZero(this.scale[1] - 1);
  7903. };
  7904. transformableProto.updateTransform = function () {
  7905. var parent = this.parent;
  7906. var parentHasTransform = parent && parent.transform;
  7907. var needLocalTransform = this.needLocalTransform();
  7908. var m = this.transform;
  7909. if (!(needLocalTransform || parentHasTransform)) {
  7910. m && mIdentity(m);
  7911. return;
  7912. }
  7913. m = m || matrix.create();
  7914. if (needLocalTransform) {
  7915. this.getLocalTransform(m);
  7916. }
  7917. else {
  7918. mIdentity(m);
  7919. }
  7920. // 应用父节点变换
  7921. if (parentHasTransform) {
  7922. if (needLocalTransform) {
  7923. matrix.mul(m, parent.transform, m);
  7924. }
  7925. else {
  7926. matrix.copy(m, parent.transform);
  7927. }
  7928. }
  7929. // 保存这个变换矩阵
  7930. this.transform = m;
  7931. this.invTransform = this.invTransform || matrix.create();
  7932. matrix.invert(this.invTransform, m);
  7933. };
  7934. transformableProto.getLocalTransform = function (m) {
  7935. return Transformable.getLocalTransform(this, m);
  7936. };
  7937. /**
  7938. * 将自己的transform应用到context上
  7939. * @param {Context2D} ctx
  7940. */
  7941. transformableProto.setTransform = function (ctx) {
  7942. var m = this.transform;
  7943. var dpr = ctx.dpr || 1;
  7944. if (m) {
  7945. ctx.setTransform(dpr * m[0], dpr * m[1], dpr * m[2], dpr * m[3], dpr * m[4], dpr * m[5]);
  7946. }
  7947. else {
  7948. ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  7949. }
  7950. };
  7951. transformableProto.restoreTransform = function (ctx) {
  7952. var dpr = ctx.dpr || 1;
  7953. ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  7954. };
  7955. var tmpTransform = [];
  7956. /**
  7957. * 分解`transform`矩阵到`position`, `rotation`, `scale`
  7958. */
  7959. transformableProto.decomposeTransform = function () {
  7960. if (!this.transform) {
  7961. return;
  7962. }
  7963. var parent = this.parent;
  7964. var m = this.transform;
  7965. if (parent && parent.transform) {
  7966. // Get local transform and decompose them to position, scale, rotation
  7967. matrix.mul(tmpTransform, parent.invTransform, m);
  7968. m = tmpTransform;
  7969. }
  7970. var sx = m[0] * m[0] + m[1] * m[1];
  7971. var sy = m[2] * m[2] + m[3] * m[3];
  7972. var position = this.position;
  7973. var scale = this.scale;
  7974. if (isNotAroundZero(sx - 1)) {
  7975. sx = Math.sqrt(sx);
  7976. }
  7977. if (isNotAroundZero(sy - 1)) {
  7978. sy = Math.sqrt(sy);
  7979. }
  7980. if (m[0] < 0) {
  7981. sx = -sx;
  7982. }
  7983. if (m[3] < 0) {
  7984. sy = -sy;
  7985. }
  7986. position[0] = m[4];
  7987. position[1] = m[5];
  7988. scale[0] = sx;
  7989. scale[1] = sy;
  7990. this.rotation = Math.atan2(-m[1] / sy, m[0] / sx);
  7991. };
  7992. /**
  7993. * Get global scale
  7994. * @return {Array.<number>}
  7995. */
  7996. transformableProto.getGlobalScale = function () {
  7997. var m = this.transform;
  7998. if (!m) {
  7999. return [1, 1];
  8000. }
  8001. var sx = Math.sqrt(m[0] * m[0] + m[1] * m[1]);
  8002. var sy = Math.sqrt(m[2] * m[2] + m[3] * m[3]);
  8003. if (m[0] < 0) {
  8004. sx = -sx;
  8005. }
  8006. if (m[3] < 0) {
  8007. sy = -sy;
  8008. }
  8009. return [sx, sy];
  8010. };
  8011. /**
  8012. * 变换坐标位置到 shape 的局部坐标空间
  8013. * @method
  8014. * @param {number} x
  8015. * @param {number} y
  8016. * @return {Array.<number>}
  8017. */
  8018. transformableProto.transformCoordToLocal = function (x, y) {
  8019. var v2 = [x, y];
  8020. var invTransform = this.invTransform;
  8021. if (invTransform) {
  8022. vector.applyTransform(v2, v2, invTransform);
  8023. }
  8024. return v2;
  8025. };
  8026. /**
  8027. * 变换局部坐标位置到全局坐标空间
  8028. * @method
  8029. * @param {number} x
  8030. * @param {number} y
  8031. * @return {Array.<number>}
  8032. */
  8033. transformableProto.transformCoordToGlobal = function (x, y) {
  8034. var v2 = [x, y];
  8035. var transform = this.transform;
  8036. if (transform) {
  8037. vector.applyTransform(v2, v2, transform);
  8038. }
  8039. return v2;
  8040. };
  8041. /**
  8042. * @static
  8043. * @param {Object} target
  8044. * @param {Array.<number>} target.origin
  8045. * @param {number} target.rotation
  8046. * @param {Array.<number>} target.position
  8047. * @param {Array.<number>} [m]
  8048. */
  8049. Transformable.getLocalTransform = function (target, m) {
  8050. m = m || [];
  8051. mIdentity(m);
  8052. var origin = target.origin;
  8053. var scale = target.scale || [1, 1];
  8054. var rotation = target.rotation || 0;
  8055. var position = target.position || [0, 0];
  8056. if (origin) {
  8057. // Translate to origin
  8058. m[4] -= origin[0];
  8059. m[5] -= origin[1];
  8060. }
  8061. matrix.scale(m, m, scale);
  8062. if (rotation) {
  8063. matrix.rotate(m, m, rotation);
  8064. }
  8065. if (origin) {
  8066. // Translate back from origin
  8067. m[4] += origin[0];
  8068. m[5] += origin[1];
  8069. }
  8070. m[4] += position[0];
  8071. m[5] += position[1];
  8072. return m;
  8073. };
  8074. module.exports = Transformable;
  8075. /***/ },
  8076. /* 27 */
  8077. /***/ function(module, exports, __webpack_require__) {
  8078. 'use strict';
  8079. /**
  8080. * @module zrender/mixin/Animatable
  8081. */
  8082. var Animator = __webpack_require__(28);
  8083. var util = __webpack_require__(4);
  8084. var isString = util.isString;
  8085. var isFunction = util.isFunction;
  8086. var isObject = util.isObject;
  8087. var log = __webpack_require__(33);
  8088. /**
  8089. * @alias modue:zrender/mixin/Animatable
  8090. * @constructor
  8091. */
  8092. var Animatable = function () {
  8093. /**
  8094. * @type {Array.<module:zrender/animation/Animator>}
  8095. * @readOnly
  8096. */
  8097. this.animators = [];
  8098. };
  8099. Animatable.prototype = {
  8100. constructor: Animatable,
  8101. /**
  8102. * 动画
  8103. *
  8104. * @param {string} path 需要添加动画的属性获取路径,可以通过a.b.c来获取深层的属性
  8105. * @param {boolean} [loop] 动画是否循环
  8106. * @return {module:zrender/animation/Animator}
  8107. * @example:
  8108. * el.animate('style', false)
  8109. * .when(1000, {x: 10} )
  8110. * .done(function(){ // Animation done })
  8111. * .start()
  8112. */
  8113. animate: function (path, loop) {
  8114. var target;
  8115. var animatingShape = false;
  8116. var el = this;
  8117. var zr = this.__zr;
  8118. if (path) {
  8119. var pathSplitted = path.split('.');
  8120. var prop = el;
  8121. // If animating shape
  8122. animatingShape = pathSplitted[0] === 'shape';
  8123. for (var i = 0, l = pathSplitted.length; i < l; i++) {
  8124. if (!prop) {
  8125. continue;
  8126. }
  8127. prop = prop[pathSplitted[i]];
  8128. }
  8129. if (prop) {
  8130. target = prop;
  8131. }
  8132. }
  8133. else {
  8134. target = el;
  8135. }
  8136. if (!target) {
  8137. log(
  8138. 'Property "'
  8139. + path
  8140. + '" is not existed in element '
  8141. + el.id
  8142. );
  8143. return;
  8144. }
  8145. var animators = el.animators;
  8146. var animator = new Animator(target, loop);
  8147. animator.during(function (target) {
  8148. el.dirty(animatingShape);
  8149. })
  8150. .done(function () {
  8151. // FIXME Animator will not be removed if use `Animator#stop` to stop animation
  8152. animators.splice(util.indexOf(animators, animator), 1);
  8153. });
  8154. animators.push(animator);
  8155. // If animate after added to the zrender
  8156. if (zr) {
  8157. zr.animation.addAnimator(animator);
  8158. }
  8159. return animator;
  8160. },
  8161. /**
  8162. * 停止动画
  8163. * @param {boolean} forwardToLast If move to last frame before stop
  8164. */
  8165. stopAnimation: function (forwardToLast) {
  8166. var animators = this.animators;
  8167. var len = animators.length;
  8168. for (var i = 0; i < len; i++) {
  8169. animators[i].stop(forwardToLast);
  8170. }
  8171. animators.length = 0;
  8172. return this;
  8173. },
  8174. /**
  8175. * @param {Object} target
  8176. * @param {number} [time=500] Time in ms
  8177. * @param {string} [easing='linear']
  8178. * @param {number} [delay=0]
  8179. * @param {Function} [callback]
  8180. *
  8181. * @example
  8182. * // Animate position
  8183. * el.animateTo({
  8184. * position: [10, 10]
  8185. * }, function () { // done })
  8186. *
  8187. * // Animate shape, style and position in 100ms, delayed 100ms, with cubicOut easing
  8188. * el.animateTo({
  8189. * shape: {
  8190. * width: 500
  8191. * },
  8192. * style: {
  8193. * fill: 'red'
  8194. * }
  8195. * position: [10, 10]
  8196. * }, 100, 100, 'cubicOut', function () { // done })
  8197. */
  8198. // TODO Return animation key
  8199. animateTo: function (target, time, delay, easing, callback) {
  8200. // animateTo(target, time, easing, callback);
  8201. if (isString(delay)) {
  8202. callback = easing;
  8203. easing = delay;
  8204. delay = 0;
  8205. }
  8206. // animateTo(target, time, delay, callback);
  8207. else if (isFunction(easing)) {
  8208. callback = easing;
  8209. easing = 'linear';
  8210. delay = 0;
  8211. }
  8212. // animateTo(target, time, callback);
  8213. else if (isFunction(delay)) {
  8214. callback = delay;
  8215. delay = 0;
  8216. }
  8217. // animateTo(target, callback)
  8218. else if (isFunction(time)) {
  8219. callback = time;
  8220. time = 500;
  8221. }
  8222. // animateTo(target)
  8223. else if (!time) {
  8224. time = 500;
  8225. }
  8226. // Stop all previous animations
  8227. this.stopAnimation();
  8228. this._animateToShallow('', this, target, time, delay, easing, callback);
  8229. // Animators may be removed immediately after start
  8230. // if there is nothing to animate
  8231. var animators = this.animators.slice();
  8232. var count = animators.length;
  8233. function done() {
  8234. count--;
  8235. if (!count) {
  8236. callback && callback();
  8237. }
  8238. }
  8239. // No animators. This should be checked before animators[i].start(),
  8240. // because 'done' may be executed immediately if no need to animate.
  8241. if (!count) {
  8242. callback && callback();
  8243. }
  8244. // Start after all animators created
  8245. // Incase any animator is done immediately when all animation properties are not changed
  8246. for (var i = 0; i < animators.length; i++) {
  8247. animators[i]
  8248. .done(done)
  8249. .start(easing);
  8250. }
  8251. },
  8252. /**
  8253. * @private
  8254. * @param {string} path=''
  8255. * @param {Object} source=this
  8256. * @param {Object} target
  8257. * @param {number} [time=500]
  8258. * @param {number} [delay=0]
  8259. *
  8260. * @example
  8261. * // Animate position
  8262. * el._animateToShallow({
  8263. * position: [10, 10]
  8264. * })
  8265. *
  8266. * // Animate shape, style and position in 100ms, delayed 100ms
  8267. * el._animateToShallow({
  8268. * shape: {
  8269. * width: 500
  8270. * },
  8271. * style: {
  8272. * fill: 'red'
  8273. * }
  8274. * position: [10, 10]
  8275. * }, 100, 100)
  8276. */
  8277. _animateToShallow: function (path, source, target, time, delay) {
  8278. var objShallow = {};
  8279. var propertyCount = 0;
  8280. for (var name in target) {
  8281. if (!target.hasOwnProperty(name)) {
  8282. continue;
  8283. }
  8284. if (source[name] != null) {
  8285. if (isObject(target[name]) && !util.isArrayLike(target[name])) {
  8286. this._animateToShallow(
  8287. path ? path + '.' + name : name,
  8288. source[name],
  8289. target[name],
  8290. time,
  8291. delay
  8292. );
  8293. }
  8294. else {
  8295. objShallow[name] = target[name];
  8296. propertyCount++;
  8297. }
  8298. }
  8299. else if (target[name] != null) {
  8300. // Attr directly if not has property
  8301. // FIXME, if some property not needed for element ?
  8302. if (!path) {
  8303. this.attr(name, target[name]);
  8304. }
  8305. else { // Shape or style
  8306. var props = {};
  8307. props[path] = {};
  8308. props[path][name] = target[name];
  8309. this.attr(props);
  8310. }
  8311. }
  8312. }
  8313. if (propertyCount > 0) {
  8314. this.animate(path, false)
  8315. .when(time == null ? 500 : time, objShallow)
  8316. .delay(delay || 0);
  8317. }
  8318. return this;
  8319. }
  8320. };
  8321. module.exports = Animatable;
  8322. /***/ },
  8323. /* 28 */
  8324. /***/ function(module, exports, __webpack_require__) {
  8325. /**
  8326. * @module echarts/animation/Animator
  8327. */
  8328. var Clip = __webpack_require__(29);
  8329. var color = __webpack_require__(31);
  8330. var util = __webpack_require__(4);
  8331. var isArrayLike = util.isArrayLike;
  8332. var arraySlice = Array.prototype.slice;
  8333. function defaultGetter(target, key) {
  8334. return target[key];
  8335. }
  8336. function defaultSetter(target, key, value) {
  8337. target[key] = value;
  8338. }
  8339. /**
  8340. * @param {number} p0
  8341. * @param {number} p1
  8342. * @param {number} percent
  8343. * @return {number}
  8344. */
  8345. function interpolateNumber(p0, p1, percent) {
  8346. return (p1 - p0) * percent + p0;
  8347. }
  8348. /**
  8349. * @param {string} p0
  8350. * @param {string} p1
  8351. * @param {number} percent
  8352. * @return {string}
  8353. */
  8354. function interpolateString(p0, p1, percent) {
  8355. return percent > 0.5 ? p1 : p0;
  8356. }
  8357. /**
  8358. * @param {Array} p0
  8359. * @param {Array} p1
  8360. * @param {number} percent
  8361. * @param {Array} out
  8362. * @param {number} arrDim
  8363. */
  8364. function interpolateArray(p0, p1, percent, out, arrDim) {
  8365. var len = p0.length;
  8366. if (arrDim == 1) {
  8367. for (var i = 0; i < len; i++) {
  8368. out[i] = interpolateNumber(p0[i], p1[i], percent);
  8369. }
  8370. }
  8371. else {
  8372. var len2 = len && p0[0].length;
  8373. for (var i = 0; i < len; i++) {
  8374. for (var j = 0; j < len2; j++) {
  8375. out[i][j] = interpolateNumber(
  8376. p0[i][j], p1[i][j], percent
  8377. );
  8378. }
  8379. }
  8380. }
  8381. }
  8382. // arr0 is source array, arr1 is target array.
  8383. // Do some preprocess to avoid error happened when interpolating from arr0 to arr1
  8384. function fillArr(arr0, arr1, arrDim) {
  8385. var arr0Len = arr0.length;
  8386. var arr1Len = arr1.length;
  8387. if (arr0Len !== arr1Len) {
  8388. // FIXME Not work for TypedArray
  8389. var isPreviousLarger = arr0Len > arr1Len;
  8390. if (isPreviousLarger) {
  8391. // Cut the previous
  8392. arr0.length = arr1Len;
  8393. }
  8394. else {
  8395. // Fill the previous
  8396. for (var i = arr0Len; i < arr1Len; i++) {
  8397. arr0.push(
  8398. arrDim === 1 ? arr1[i] : arraySlice.call(arr1[i])
  8399. );
  8400. }
  8401. }
  8402. }
  8403. // Handling NaN value
  8404. var len2 = arr0[0] && arr0[0].length;
  8405. for (var i = 0; i < arr0.length; i++) {
  8406. if (arrDim === 1) {
  8407. if (isNaN(arr0[i])) {
  8408. arr0[i] = arr1[i];
  8409. }
  8410. }
  8411. else {
  8412. for (var j = 0; j < len2; j++) {
  8413. if (isNaN(arr0[i][j])) {
  8414. arr0[i][j] = arr1[i][j];
  8415. }
  8416. }
  8417. }
  8418. }
  8419. }
  8420. /**
  8421. * @param {Array} arr0
  8422. * @param {Array} arr1
  8423. * @param {number} arrDim
  8424. * @return {boolean}
  8425. */
  8426. function isArraySame(arr0, arr1, arrDim) {
  8427. if (arr0 === arr1) {
  8428. return true;
  8429. }
  8430. var len = arr0.length;
  8431. if (len !== arr1.length) {
  8432. return false;
  8433. }
  8434. if (arrDim === 1) {
  8435. for (var i = 0; i < len; i++) {
  8436. if (arr0[i] !== arr1[i]) {
  8437. return false;
  8438. }
  8439. }
  8440. }
  8441. else {
  8442. var len2 = arr0[0].length;
  8443. for (var i = 0; i < len; i++) {
  8444. for (var j = 0; j < len2; j++) {
  8445. if (arr0[i][j] !== arr1[i][j]) {
  8446. return false;
  8447. }
  8448. }
  8449. }
  8450. }
  8451. return true;
  8452. }
  8453. /**
  8454. * Catmull Rom interpolate array
  8455. * @param {Array} p0
  8456. * @param {Array} p1
  8457. * @param {Array} p2
  8458. * @param {Array} p3
  8459. * @param {number} t
  8460. * @param {number} t2
  8461. * @param {number} t3
  8462. * @param {Array} out
  8463. * @param {number} arrDim
  8464. */
  8465. function catmullRomInterpolateArray(
  8466. p0, p1, p2, p3, t, t2, t3, out, arrDim
  8467. ) {
  8468. var len = p0.length;
  8469. if (arrDim == 1) {
  8470. for (var i = 0; i < len; i++) {
  8471. out[i] = catmullRomInterpolate(
  8472. p0[i], p1[i], p2[i], p3[i], t, t2, t3
  8473. );
  8474. }
  8475. }
  8476. else {
  8477. var len2 = p0[0].length;
  8478. for (var i = 0; i < len; i++) {
  8479. for (var j = 0; j < len2; j++) {
  8480. out[i][j] = catmullRomInterpolate(
  8481. p0[i][j], p1[i][j], p2[i][j], p3[i][j],
  8482. t, t2, t3
  8483. );
  8484. }
  8485. }
  8486. }
  8487. }
  8488. /**
  8489. * Catmull Rom interpolate number
  8490. * @param {number} p0
  8491. * @param {number} p1
  8492. * @param {number} p2
  8493. * @param {number} p3
  8494. * @param {number} t
  8495. * @param {number} t2
  8496. * @param {number} t3
  8497. * @return {number}
  8498. */
  8499. function catmullRomInterpolate(p0, p1, p2, p3, t, t2, t3) {
  8500. var v0 = (p2 - p0) * 0.5;
  8501. var v1 = (p3 - p1) * 0.5;
  8502. return (2 * (p1 - p2) + v0 + v1) * t3
  8503. + (-3 * (p1 - p2) - 2 * v0 - v1) * t2
  8504. + v0 * t + p1;
  8505. }
  8506. function cloneValue(value) {
  8507. if (isArrayLike(value)) {
  8508. var len = value.length;
  8509. if (isArrayLike(value[0])) {
  8510. var ret = [];
  8511. for (var i = 0; i < len; i++) {
  8512. ret.push(arraySlice.call(value[i]));
  8513. }
  8514. return ret;
  8515. }
  8516. return arraySlice.call(value);
  8517. }
  8518. return value;
  8519. }
  8520. function rgba2String(rgba) {
  8521. rgba[0] = Math.floor(rgba[0]);
  8522. rgba[1] = Math.floor(rgba[1]);
  8523. rgba[2] = Math.floor(rgba[2]);
  8524. return 'rgba(' + rgba.join(',') + ')';
  8525. }
  8526. function getArrayDim(keyframes) {
  8527. var lastValue = keyframes[keyframes.length - 1].value;
  8528. return isArrayLike(lastValue && lastValue[0]) ? 2 : 1;
  8529. }
  8530. function createTrackClip (animator, easing, oneTrackDone, keyframes, propName) {
  8531. var getter = animator._getter;
  8532. var setter = animator._setter;
  8533. var useSpline = easing === 'spline';
  8534. var trackLen = keyframes.length;
  8535. if (!trackLen) {
  8536. return;
  8537. }
  8538. // Guess data type
  8539. var firstVal = keyframes[0].value;
  8540. var isValueArray = isArrayLike(firstVal);
  8541. var isValueColor = false;
  8542. var isValueString = false;
  8543. // For vertices morphing
  8544. var arrDim = isValueArray ? getArrayDim(keyframes) : 0;
  8545. var trackMaxTime;
  8546. // Sort keyframe as ascending
  8547. keyframes.sort(function(a, b) {
  8548. return a.time - b.time;
  8549. });
  8550. trackMaxTime = keyframes[trackLen - 1].time;
  8551. // Percents of each keyframe
  8552. var kfPercents = [];
  8553. // Value of each keyframe
  8554. var kfValues = [];
  8555. var prevValue = keyframes[0].value;
  8556. var isAllValueEqual = true;
  8557. for (var i = 0; i < trackLen; i++) {
  8558. kfPercents.push(keyframes[i].time / trackMaxTime);
  8559. // Assume value is a color when it is a string
  8560. var value = keyframes[i].value;
  8561. // Check if value is equal, deep check if value is array
  8562. if (!((isValueArray && isArraySame(value, prevValue, arrDim))
  8563. || (!isValueArray && value === prevValue))) {
  8564. isAllValueEqual = false;
  8565. }
  8566. prevValue = value;
  8567. // Try converting a string to a color array
  8568. if (typeof value == 'string') {
  8569. var colorArray = color.parse(value);
  8570. if (colorArray) {
  8571. value = colorArray;
  8572. isValueColor = true;
  8573. }
  8574. else {
  8575. isValueString = true;
  8576. }
  8577. }
  8578. kfValues.push(value);
  8579. }
  8580. if (isAllValueEqual) {
  8581. return;
  8582. }
  8583. var lastValue = kfValues[trackLen - 1];
  8584. // Polyfill array and NaN value
  8585. for (var i = 0; i < trackLen - 1; i++) {
  8586. if (isValueArray) {
  8587. fillArr(kfValues[i], lastValue, arrDim);
  8588. }
  8589. else {
  8590. if (isNaN(kfValues[i]) && !isNaN(lastValue) && !isValueString && !isValueColor) {
  8591. kfValues[i] = lastValue;
  8592. }
  8593. }
  8594. }
  8595. isValueArray && fillArr(getter(animator._target, propName), lastValue, arrDim);
  8596. // Cache the key of last frame to speed up when
  8597. // animation playback is sequency
  8598. var lastFrame = 0;
  8599. var lastFramePercent = 0;
  8600. var start;
  8601. var w;
  8602. var p0;
  8603. var p1;
  8604. var p2;
  8605. var p3;
  8606. if (isValueColor) {
  8607. var rgba = [0, 0, 0, 0];
  8608. }
  8609. var onframe = function (target, percent) {
  8610. // Find the range keyframes
  8611. // kf1-----kf2---------current--------kf3
  8612. // find kf2 and kf3 and do interpolation
  8613. var frame;
  8614. // In the easing function like elasticOut, percent may less than 0
  8615. if (percent < 0) {
  8616. frame = 0;
  8617. }
  8618. else if (percent < lastFramePercent) {
  8619. // Start from next key
  8620. // PENDING start from lastFrame ?
  8621. start = Math.min(lastFrame + 1, trackLen - 1);
  8622. for (frame = start; frame >= 0; frame--) {
  8623. if (kfPercents[frame] <= percent) {
  8624. break;
  8625. }
  8626. }
  8627. // PENDING really need to do this ?
  8628. frame = Math.min(frame, trackLen - 2);
  8629. }
  8630. else {
  8631. for (frame = lastFrame; frame < trackLen; frame++) {
  8632. if (kfPercents[frame] > percent) {
  8633. break;
  8634. }
  8635. }
  8636. frame = Math.min(frame - 1, trackLen - 2);
  8637. }
  8638. lastFrame = frame;
  8639. lastFramePercent = percent;
  8640. var range = (kfPercents[frame + 1] - kfPercents[frame]);
  8641. if (range === 0) {
  8642. return;
  8643. }
  8644. else {
  8645. w = (percent - kfPercents[frame]) / range;
  8646. }
  8647. if (useSpline) {
  8648. p1 = kfValues[frame];
  8649. p0 = kfValues[frame === 0 ? frame : frame - 1];
  8650. p2 = kfValues[frame > trackLen - 2 ? trackLen - 1 : frame + 1];
  8651. p3 = kfValues[frame > trackLen - 3 ? trackLen - 1 : frame + 2];
  8652. if (isValueArray) {
  8653. catmullRomInterpolateArray(
  8654. p0, p1, p2, p3, w, w * w, w * w * w,
  8655. getter(target, propName),
  8656. arrDim
  8657. );
  8658. }
  8659. else {
  8660. var value;
  8661. if (isValueColor) {
  8662. value = catmullRomInterpolateArray(
  8663. p0, p1, p2, p3, w, w * w, w * w * w,
  8664. rgba, 1
  8665. );
  8666. value = rgba2String(rgba);
  8667. }
  8668. else if (isValueString) {
  8669. // String is step(0.5)
  8670. return interpolateString(p1, p2, w);
  8671. }
  8672. else {
  8673. value = catmullRomInterpolate(
  8674. p0, p1, p2, p3, w, w * w, w * w * w
  8675. );
  8676. }
  8677. setter(
  8678. target,
  8679. propName,
  8680. value
  8681. );
  8682. }
  8683. }
  8684. else {
  8685. if (isValueArray) {
  8686. interpolateArray(
  8687. kfValues[frame], kfValues[frame + 1], w,
  8688. getter(target, propName),
  8689. arrDim
  8690. );
  8691. }
  8692. else {
  8693. var value;
  8694. if (isValueColor) {
  8695. interpolateArray(
  8696. kfValues[frame], kfValues[frame + 1], w,
  8697. rgba, 1
  8698. );
  8699. value = rgba2String(rgba);
  8700. }
  8701. else if (isValueString) {
  8702. // String is step(0.5)
  8703. return interpolateString(kfValues[frame], kfValues[frame + 1], w);
  8704. }
  8705. else {
  8706. value = interpolateNumber(kfValues[frame], kfValues[frame + 1], w);
  8707. }
  8708. setter(
  8709. target,
  8710. propName,
  8711. value
  8712. );
  8713. }
  8714. }
  8715. };
  8716. var clip = new Clip({
  8717. target: animator._target,
  8718. life: trackMaxTime,
  8719. loop: animator._loop,
  8720. delay: animator._delay,
  8721. onframe: onframe,
  8722. ondestroy: oneTrackDone
  8723. });
  8724. if (easing && easing !== 'spline') {
  8725. clip.easing = easing;
  8726. }
  8727. return clip;
  8728. }
  8729. /**
  8730. * @alias module:zrender/animation/Animator
  8731. * @constructor
  8732. * @param {Object} target
  8733. * @param {boolean} loop
  8734. * @param {Function} getter
  8735. * @param {Function} setter
  8736. */
  8737. var Animator = function(target, loop, getter, setter) {
  8738. this._tracks = {};
  8739. this._target = target;
  8740. this._loop = loop || false;
  8741. this._getter = getter || defaultGetter;
  8742. this._setter = setter || defaultSetter;
  8743. this._clipCount = 0;
  8744. this._delay = 0;
  8745. this._doneList = [];
  8746. this._onframeList = [];
  8747. this._clipList = [];
  8748. };
  8749. Animator.prototype = {
  8750. /**
  8751. * 设置动画关键帧
  8752. * @param {number} time 关键帧时间,单位是ms
  8753. * @param {Object} props 关键帧的属性值,key-value表示
  8754. * @return {module:zrender/animation/Animator}
  8755. */
  8756. when: function(time /* ms */, props) {
  8757. var tracks = this._tracks;
  8758. for (var propName in props) {
  8759. if (!props.hasOwnProperty(propName)) {
  8760. continue;
  8761. }
  8762. if (!tracks[propName]) {
  8763. tracks[propName] = [];
  8764. // Invalid value
  8765. var value = this._getter(this._target, propName);
  8766. if (value == null) {
  8767. // zrLog('Invalid property ' + propName);
  8768. continue;
  8769. }
  8770. // If time is 0
  8771. // Then props is given initialize value
  8772. // Else
  8773. // Initialize value from current prop value
  8774. if (time !== 0) {
  8775. tracks[propName].push({
  8776. time: 0,
  8777. value: cloneValue(value)
  8778. });
  8779. }
  8780. }
  8781. tracks[propName].push({
  8782. time: time,
  8783. value: props[propName]
  8784. });
  8785. }
  8786. return this;
  8787. },
  8788. /**
  8789. * 添加动画每一帧的回调函数
  8790. * @param {Function} callback
  8791. * @return {module:zrender/animation/Animator}
  8792. */
  8793. during: function (callback) {
  8794. this._onframeList.push(callback);
  8795. return this;
  8796. },
  8797. pause: function () {
  8798. for (var i = 0; i < this._clipList.length; i++) {
  8799. this._clipList[i].pause();
  8800. }
  8801. this._paused = true;
  8802. },
  8803. resume: function () {
  8804. for (var i = 0; i < this._clipList.length; i++) {
  8805. this._clipList[i].resume();
  8806. }
  8807. this._paused = false;
  8808. },
  8809. isPaused: function () {
  8810. return !!this._paused;
  8811. },
  8812. _doneCallback: function () {
  8813. // Clear all tracks
  8814. this._tracks = {};
  8815. // Clear all clips
  8816. this._clipList.length = 0;
  8817. var doneList = this._doneList;
  8818. var len = doneList.length;
  8819. for (var i = 0; i < len; i++) {
  8820. doneList[i].call(this);
  8821. }
  8822. },
  8823. /**
  8824. * 开始执行动画
  8825. * @param {string|Function} easing
  8826. * 动画缓动函数,详见{@link module:zrender/animation/easing}
  8827. * @return {module:zrender/animation/Animator}
  8828. */
  8829. start: function (easing) {
  8830. var self = this;
  8831. var clipCount = 0;
  8832. var oneTrackDone = function() {
  8833. clipCount--;
  8834. if (!clipCount) {
  8835. self._doneCallback();
  8836. }
  8837. };
  8838. var lastClip;
  8839. for (var propName in this._tracks) {
  8840. if (!this._tracks.hasOwnProperty(propName)) {
  8841. continue;
  8842. }
  8843. var clip = createTrackClip(
  8844. this, easing, oneTrackDone,
  8845. this._tracks[propName], propName
  8846. );
  8847. if (clip) {
  8848. this._clipList.push(clip);
  8849. clipCount++;
  8850. // If start after added to animation
  8851. if (this.animation) {
  8852. this.animation.addClip(clip);
  8853. }
  8854. lastClip = clip;
  8855. }
  8856. }
  8857. // Add during callback on the last clip
  8858. if (lastClip) {
  8859. var oldOnFrame = lastClip.onframe;
  8860. lastClip.onframe = function (target, percent) {
  8861. oldOnFrame(target, percent);
  8862. for (var i = 0; i < self._onframeList.length; i++) {
  8863. self._onframeList[i](target, percent);
  8864. }
  8865. };
  8866. }
  8867. if (!clipCount) {
  8868. this._doneCallback();
  8869. }
  8870. return this;
  8871. },
  8872. /**
  8873. * 停止动画
  8874. * @param {boolean} forwardToLast If move to last frame before stop
  8875. */
  8876. stop: function (forwardToLast) {
  8877. var clipList = this._clipList;
  8878. var animation = this.animation;
  8879. for (var i = 0; i < clipList.length; i++) {
  8880. var clip = clipList[i];
  8881. if (forwardToLast) {
  8882. // Move to last frame before stop
  8883. clip.onframe(this._target, 1);
  8884. }
  8885. animation && animation.removeClip(clip);
  8886. }
  8887. clipList.length = 0;
  8888. },
  8889. /**
  8890. * 设置动画延迟开始的时间
  8891. * @param {number} time 单位ms
  8892. * @return {module:zrender/animation/Animator}
  8893. */
  8894. delay: function (time) {
  8895. this._delay = time;
  8896. return this;
  8897. },
  8898. /**
  8899. * 添加动画结束的回调
  8900. * @param {Function} cb
  8901. * @return {module:zrender/animation/Animator}
  8902. */
  8903. done: function(cb) {
  8904. if (cb) {
  8905. this._doneList.push(cb);
  8906. }
  8907. return this;
  8908. },
  8909. /**
  8910. * @return {Array.<module:zrender/animation/Clip>}
  8911. */
  8912. getClips: function () {
  8913. return this._clipList;
  8914. }
  8915. };
  8916. module.exports = Animator;
  8917. /***/ },
  8918. /* 29 */
  8919. /***/ function(module, exports, __webpack_require__) {
  8920. /**
  8921. * 动画主控制器
  8922. * @config target 动画对象,可以是数组,如果是数组的话会批量分发onframe等事件
  8923. * @config life(1000) 动画时长
  8924. * @config delay(0) 动画延迟时间
  8925. * @config loop(true)
  8926. * @config gap(0) 循环的间隔时间
  8927. * @config onframe
  8928. * @config easing(optional)
  8929. * @config ondestroy(optional)
  8930. * @config onrestart(optional)
  8931. *
  8932. * TODO pause
  8933. */
  8934. var easingFuncs = __webpack_require__(30);
  8935. function Clip(options) {
  8936. this._target = options.target;
  8937. // 生命周期
  8938. this._life = options.life || 1000;
  8939. // 延时
  8940. this._delay = options.delay || 0;
  8941. // 开始时间
  8942. // this._startTime = new Date().getTime() + this._delay;// 单位毫秒
  8943. this._initialized = false;
  8944. // 是否循环
  8945. this.loop = options.loop == null ? false : options.loop;
  8946. this.gap = options.gap || 0;
  8947. this.easing = options.easing || 'Linear';
  8948. this.onframe = options.onframe;
  8949. this.ondestroy = options.ondestroy;
  8950. this.onrestart = options.onrestart;
  8951. this._pausedTime = 0;
  8952. this._paused = false;
  8953. }
  8954. Clip.prototype = {
  8955. constructor: Clip,
  8956. step: function (globalTime, deltaTime) {
  8957. // Set startTime on first step, or _startTime may has milleseconds different between clips
  8958. // PENDING
  8959. if (!this._initialized) {
  8960. this._startTime = globalTime + this._delay;
  8961. this._initialized = true;
  8962. }
  8963. if (this._paused) {
  8964. this._pausedTime += deltaTime;
  8965. return;
  8966. }
  8967. var percent = (globalTime - this._startTime - this._pausedTime) / this._life;
  8968. // 还没开始
  8969. if (percent < 0) {
  8970. return;
  8971. }
  8972. percent = Math.min(percent, 1);
  8973. var easing = this.easing;
  8974. var easingFunc = typeof easing == 'string' ? easingFuncs[easing] : easing;
  8975. var schedule = typeof easingFunc === 'function'
  8976. ? easingFunc(percent)
  8977. : percent;
  8978. this.fire('frame', schedule);
  8979. // 结束
  8980. if (percent == 1) {
  8981. if (this.loop) {
  8982. this.restart (globalTime);
  8983. // 重新开始周期
  8984. // 抛出而不是直接调用事件直到 stage.update 后再统一调用这些事件
  8985. return 'restart';
  8986. }
  8987. // 动画完成将这个控制器标识为待删除
  8988. // 在Animation.update中进行批量删除
  8989. this._needsRemove = true;
  8990. return 'destroy';
  8991. }
  8992. return null;
  8993. },
  8994. restart: function (globalTime) {
  8995. var remainder = (globalTime - this._startTime - this._pausedTime) % this._life;
  8996. this._startTime = globalTime - remainder + this.gap;
  8997. this._pausedTime = 0;
  8998. this._needsRemove = false;
  8999. },
  9000. fire: function (eventType, arg) {
  9001. eventType = 'on' + eventType;
  9002. if (this[eventType]) {
  9003. this[eventType](this._target, arg);
  9004. }
  9005. },
  9006. pause: function () {
  9007. this._paused = true;
  9008. },
  9009. resume: function () {
  9010. this._paused = false;
  9011. }
  9012. };
  9013. module.exports = Clip;
  9014. /***/ },
  9015. /* 30 */
  9016. /***/ function(module, exports) {
  9017. /**
  9018. * 缓动代码来自 https://github.com/sole/tween.js/blob/master/src/Tween.js
  9019. * @see http://sole.github.io/tween.js/examples/03_graphs.html
  9020. * @exports zrender/animation/easing
  9021. */
  9022. var easing = {
  9023. /**
  9024. * @param {number} k
  9025. * @return {number}
  9026. */
  9027. linear: function (k) {
  9028. return k;
  9029. },
  9030. /**
  9031. * @param {number} k
  9032. * @return {number}
  9033. */
  9034. quadraticIn: function (k) {
  9035. return k * k;
  9036. },
  9037. /**
  9038. * @param {number} k
  9039. * @return {number}
  9040. */
  9041. quadraticOut: function (k) {
  9042. return k * (2 - k);
  9043. },
  9044. /**
  9045. * @param {number} k
  9046. * @return {number}
  9047. */
  9048. quadraticInOut: function (k) {
  9049. if ((k *= 2) < 1) {
  9050. return 0.5 * k * k;
  9051. }
  9052. return -0.5 * (--k * (k - 2) - 1);
  9053. },
  9054. // 三次方的缓动(t^3)
  9055. /**
  9056. * @param {number} k
  9057. * @return {number}
  9058. */
  9059. cubicIn: function (k) {
  9060. return k * k * k;
  9061. },
  9062. /**
  9063. * @param {number} k
  9064. * @return {number}
  9065. */
  9066. cubicOut: function (k) {
  9067. return --k * k * k + 1;
  9068. },
  9069. /**
  9070. * @param {number} k
  9071. * @return {number}
  9072. */
  9073. cubicInOut: function (k) {
  9074. if ((k *= 2) < 1) {
  9075. return 0.5 * k * k * k;
  9076. }
  9077. return 0.5 * ((k -= 2) * k * k + 2);
  9078. },
  9079. // 四次方的缓动(t^4)
  9080. /**
  9081. * @param {number} k
  9082. * @return {number}
  9083. */
  9084. quarticIn: function (k) {
  9085. return k * k * k * k;
  9086. },
  9087. /**
  9088. * @param {number} k
  9089. * @return {number}
  9090. */
  9091. quarticOut: function (k) {
  9092. return 1 - (--k * k * k * k);
  9093. },
  9094. /**
  9095. * @param {number} k
  9096. * @return {number}
  9097. */
  9098. quarticInOut: function (k) {
  9099. if ((k *= 2) < 1) {
  9100. return 0.5 * k * k * k * k;
  9101. }
  9102. return -0.5 * ((k -= 2) * k * k * k - 2);
  9103. },
  9104. // 五次方的缓动(t^5)
  9105. /**
  9106. * @param {number} k
  9107. * @return {number}
  9108. */
  9109. quinticIn: function (k) {
  9110. return k * k * k * k * k;
  9111. },
  9112. /**
  9113. * @param {number} k
  9114. * @return {number}
  9115. */
  9116. quinticOut: function (k) {
  9117. return --k * k * k * k * k + 1;
  9118. },
  9119. /**
  9120. * @param {number} k
  9121. * @return {number}
  9122. */
  9123. quinticInOut: function (k) {
  9124. if ((k *= 2) < 1) {
  9125. return 0.5 * k * k * k * k * k;
  9126. }
  9127. return 0.5 * ((k -= 2) * k * k * k * k + 2);
  9128. },
  9129. // 正弦曲线的缓动(sin(t))
  9130. /**
  9131. * @param {number} k
  9132. * @return {number}
  9133. */
  9134. sinusoidalIn: function (k) {
  9135. return 1 - Math.cos(k * Math.PI / 2);
  9136. },
  9137. /**
  9138. * @param {number} k
  9139. * @return {number}
  9140. */
  9141. sinusoidalOut: function (k) {
  9142. return Math.sin(k * Math.PI / 2);
  9143. },
  9144. /**
  9145. * @param {number} k
  9146. * @return {number}
  9147. */
  9148. sinusoidalInOut: function (k) {
  9149. return 0.5 * (1 - Math.cos(Math.PI * k));
  9150. },
  9151. // 指数曲线的缓动(2^t)
  9152. /**
  9153. * @param {number} k
  9154. * @return {number}
  9155. */
  9156. exponentialIn: function (k) {
  9157. return k === 0 ? 0 : Math.pow(1024, k - 1);
  9158. },
  9159. /**
  9160. * @param {number} k
  9161. * @return {number}
  9162. */
  9163. exponentialOut: function (k) {
  9164. return k === 1 ? 1 : 1 - Math.pow(2, -10 * k);
  9165. },
  9166. /**
  9167. * @param {number} k
  9168. * @return {number}
  9169. */
  9170. exponentialInOut: function (k) {
  9171. if (k === 0) {
  9172. return 0;
  9173. }
  9174. if (k === 1) {
  9175. return 1;
  9176. }
  9177. if ((k *= 2) < 1) {
  9178. return 0.5 * Math.pow(1024, k - 1);
  9179. }
  9180. return 0.5 * (-Math.pow(2, -10 * (k - 1)) + 2);
  9181. },
  9182. // 圆形曲线的缓动(sqrt(1-t^2))
  9183. /**
  9184. * @param {number} k
  9185. * @return {number}
  9186. */
  9187. circularIn: function (k) {
  9188. return 1 - Math.sqrt(1 - k * k);
  9189. },
  9190. /**
  9191. * @param {number} k
  9192. * @return {number}
  9193. */
  9194. circularOut: function (k) {
  9195. return Math.sqrt(1 - (--k * k));
  9196. },
  9197. /**
  9198. * @param {number} k
  9199. * @return {number}
  9200. */
  9201. circularInOut: function (k) {
  9202. if ((k *= 2) < 1) {
  9203. return -0.5 * (Math.sqrt(1 - k * k) - 1);
  9204. }
  9205. return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1);
  9206. },
  9207. // 创建类似于弹簧在停止前来回振荡的动画
  9208. /**
  9209. * @param {number} k
  9210. * @return {number}
  9211. */
  9212. elasticIn: function (k) {
  9213. var s;
  9214. var a = 0.1;
  9215. var p = 0.4;
  9216. if (k === 0) {
  9217. return 0;
  9218. }
  9219. if (k === 1) {
  9220. return 1;
  9221. }
  9222. if (!a || a < 1) {
  9223. a = 1; s = p / 4;
  9224. }
  9225. else {
  9226. s = p * Math.asin(1 / a) / (2 * Math.PI);
  9227. }
  9228. return -(a * Math.pow(2, 10 * (k -= 1)) *
  9229. Math.sin((k - s) * (2 * Math.PI) / p));
  9230. },
  9231. /**
  9232. * @param {number} k
  9233. * @return {number}
  9234. */
  9235. elasticOut: function (k) {
  9236. var s;
  9237. var a = 0.1;
  9238. var p = 0.4;
  9239. if (k === 0) {
  9240. return 0;
  9241. }
  9242. if (k === 1) {
  9243. return 1;
  9244. }
  9245. if (!a || a < 1) {
  9246. a = 1; s = p / 4;
  9247. }
  9248. else {
  9249. s = p * Math.asin(1 / a) / (2 * Math.PI);
  9250. }
  9251. return (a * Math.pow(2, -10 * k) *
  9252. Math.sin((k - s) * (2 * Math.PI) / p) + 1);
  9253. },
  9254. /**
  9255. * @param {number} k
  9256. * @return {number}
  9257. */
  9258. elasticInOut: function (k) {
  9259. var s;
  9260. var a = 0.1;
  9261. var p = 0.4;
  9262. if (k === 0) {
  9263. return 0;
  9264. }
  9265. if (k === 1) {
  9266. return 1;
  9267. }
  9268. if (!a || a < 1) {
  9269. a = 1; s = p / 4;
  9270. }
  9271. else {
  9272. s = p * Math.asin(1 / a) / (2 * Math.PI);
  9273. }
  9274. if ((k *= 2) < 1) {
  9275. return -0.5 * (a * Math.pow(2, 10 * (k -= 1))
  9276. * Math.sin((k - s) * (2 * Math.PI) / p));
  9277. }
  9278. return a * Math.pow(2, -10 * (k -= 1))
  9279. * Math.sin((k - s) * (2 * Math.PI) / p) * 0.5 + 1;
  9280. },
  9281. // 在某一动画开始沿指示的路径进行动画处理前稍稍收回该动画的移动
  9282. /**
  9283. * @param {number} k
  9284. * @return {number}
  9285. */
  9286. backIn: function (k) {
  9287. var s = 1.70158;
  9288. return k * k * ((s + 1) * k - s);
  9289. },
  9290. /**
  9291. * @param {number} k
  9292. * @return {number}
  9293. */
  9294. backOut: function (k) {
  9295. var s = 1.70158;
  9296. return --k * k * ((s + 1) * k + s) + 1;
  9297. },
  9298. /**
  9299. * @param {number} k
  9300. * @return {number}
  9301. */
  9302. backInOut: function (k) {
  9303. var s = 1.70158 * 1.525;
  9304. if ((k *= 2) < 1) {
  9305. return 0.5 * (k * k * ((s + 1) * k - s));
  9306. }
  9307. return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2);
  9308. },
  9309. // 创建弹跳效果
  9310. /**
  9311. * @param {number} k
  9312. * @return {number}
  9313. */
  9314. bounceIn: function (k) {
  9315. return 1 - easing.bounceOut(1 - k);
  9316. },
  9317. /**
  9318. * @param {number} k
  9319. * @return {number}
  9320. */
  9321. bounceOut: function (k) {
  9322. if (k < (1 / 2.75)) {
  9323. return 7.5625 * k * k;
  9324. }
  9325. else if (k < (2 / 2.75)) {
  9326. return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75;
  9327. }
  9328. else if (k < (2.5 / 2.75)) {
  9329. return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375;
  9330. }
  9331. else {
  9332. return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375;
  9333. }
  9334. },
  9335. /**
  9336. * @param {number} k
  9337. * @return {number}
  9338. */
  9339. bounceInOut: function (k) {
  9340. if (k < 0.5) {
  9341. return easing.bounceIn(k * 2) * 0.5;
  9342. }
  9343. return easing.bounceOut(k * 2 - 1) * 0.5 + 0.5;
  9344. }
  9345. };
  9346. module.exports = easing;
  9347. /***/ },
  9348. /* 31 */
  9349. /***/ function(module, exports, __webpack_require__) {
  9350. /**
  9351. * @module zrender/tool/color
  9352. */
  9353. var LRU = __webpack_require__(32);
  9354. var kCSSColorTable = {
  9355. 'transparent': [0,0,0,0], 'aliceblue': [240,248,255,1],
  9356. 'antiquewhite': [250,235,215,1], 'aqua': [0,255,255,1],
  9357. 'aquamarine': [127,255,212,1], 'azure': [240,255,255,1],
  9358. 'beige': [245,245,220,1], 'bisque': [255,228,196,1],
  9359. 'black': [0,0,0,1], 'blanchedalmond': [255,235,205,1],
  9360. 'blue': [0,0,255,1], 'blueviolet': [138,43,226,1],
  9361. 'brown': [165,42,42,1], 'burlywood': [222,184,135,1],
  9362. 'cadetblue': [95,158,160,1], 'chartreuse': [127,255,0,1],
  9363. 'chocolate': [210,105,30,1], 'coral': [255,127,80,1],
  9364. 'cornflowerblue': [100,149,237,1], 'cornsilk': [255,248,220,1],
  9365. 'crimson': [220,20,60,1], 'cyan': [0,255,255,1],
  9366. 'darkblue': [0,0,139,1], 'darkcyan': [0,139,139,1],
  9367. 'darkgoldenrod': [184,134,11,1], 'darkgray': [169,169,169,1],
  9368. 'darkgreen': [0,100,0,1], 'darkgrey': [169,169,169,1],
  9369. 'darkkhaki': [189,183,107,1], 'darkmagenta': [139,0,139,1],
  9370. 'darkolivegreen': [85,107,47,1], 'darkorange': [255,140,0,1],
  9371. 'darkorchid': [153,50,204,1], 'darkred': [139,0,0,1],
  9372. 'darksalmon': [233,150,122,1], 'darkseagreen': [143,188,143,1],
  9373. 'darkslateblue': [72,61,139,1], 'darkslategray': [47,79,79,1],
  9374. 'darkslategrey': [47,79,79,1], 'darkturquoise': [0,206,209,1],
  9375. 'darkviolet': [148,0,211,1], 'deeppink': [255,20,147,1],
  9376. 'deepskyblue': [0,191,255,1], 'dimgray': [105,105,105,1],
  9377. 'dimgrey': [105,105,105,1], 'dodgerblue': [30,144,255,1],
  9378. 'firebrick': [178,34,34,1], 'floralwhite': [255,250,240,1],
  9379. 'forestgreen': [34,139,34,1], 'fuchsia': [255,0,255,1],
  9380. 'gainsboro': [220,220,220,1], 'ghostwhite': [248,248,255,1],
  9381. 'gold': [255,215,0,1], 'goldenrod': [218,165,32,1],
  9382. 'gray': [128,128,128,1], 'green': [0,128,0,1],
  9383. 'greenyellow': [173,255,47,1], 'grey': [128,128,128,1],
  9384. 'honeydew': [240,255,240,1], 'hotpink': [255,105,180,1],
  9385. 'indianred': [205,92,92,1], 'indigo': [75,0,130,1],
  9386. 'ivory': [255,255,240,1], 'khaki': [240,230,140,1],
  9387. 'lavender': [230,230,250,1], 'lavenderblush': [255,240,245,1],
  9388. 'lawngreen': [124,252,0,1], 'lemonchiffon': [255,250,205,1],
  9389. 'lightblue': [173,216,230,1], 'lightcoral': [240,128,128,1],
  9390. 'lightcyan': [224,255,255,1], 'lightgoldenrodyellow': [250,250,210,1],
  9391. 'lightgray': [211,211,211,1], 'lightgreen': [144,238,144,1],
  9392. 'lightgrey': [211,211,211,1], 'lightpink': [255,182,193,1],
  9393. 'lightsalmon': [255,160,122,1], 'lightseagreen': [32,178,170,1],
  9394. 'lightskyblue': [135,206,250,1], 'lightslategray': [119,136,153,1],
  9395. 'lightslategrey': [119,136,153,1], 'lightsteelblue': [176,196,222,1],
  9396. 'lightyellow': [255,255,224,1], 'lime': [0,255,0,1],
  9397. 'limegreen': [50,205,50,1], 'linen': [250,240,230,1],
  9398. 'magenta': [255,0,255,1], 'maroon': [128,0,0,1],
  9399. 'mediumaquamarine': [102,205,170,1], 'mediumblue': [0,0,205,1],
  9400. 'mediumorchid': [186,85,211,1], 'mediumpurple': [147,112,219,1],
  9401. 'mediumseagreen': [60,179,113,1], 'mediumslateblue': [123,104,238,1],
  9402. 'mediumspringgreen': [0,250,154,1], 'mediumturquoise': [72,209,204,1],
  9403. 'mediumvioletred': [199,21,133,1], 'midnightblue': [25,25,112,1],
  9404. 'mintcream': [245,255,250,1], 'mistyrose': [255,228,225,1],
  9405. 'moccasin': [255,228,181,1], 'navajowhite': [255,222,173,1],
  9406. 'navy': [0,0,128,1], 'oldlace': [253,245,230,1],
  9407. 'olive': [128,128,0,1], 'olivedrab': [107,142,35,1],
  9408. 'orange': [255,165,0,1], 'orangered': [255,69,0,1],
  9409. 'orchid': [218,112,214,1], 'palegoldenrod': [238,232,170,1],
  9410. 'palegreen': [152,251,152,1], 'paleturquoise': [175,238,238,1],
  9411. 'palevioletred': [219,112,147,1], 'papayawhip': [255,239,213,1],
  9412. 'peachpuff': [255,218,185,1], 'peru': [205,133,63,1],
  9413. 'pink': [255,192,203,1], 'plum': [221,160,221,1],
  9414. 'powderblue': [176,224,230,1], 'purple': [128,0,128,1],
  9415. 'red': [255,0,0,1], 'rosybrown': [188,143,143,1],
  9416. 'royalblue': [65,105,225,1], 'saddlebrown': [139,69,19,1],
  9417. 'salmon': [250,128,114,1], 'sandybrown': [244,164,96,1],
  9418. 'seagreen': [46,139,87,1], 'seashell': [255,245,238,1],
  9419. 'sienna': [160,82,45,1], 'silver': [192,192,192,1],
  9420. 'skyblue': [135,206,235,1], 'slateblue': [106,90,205,1],
  9421. 'slategray': [112,128,144,1], 'slategrey': [112,128,144,1],
  9422. 'snow': [255,250,250,1], 'springgreen': [0,255,127,1],
  9423. 'steelblue': [70,130,180,1], 'tan': [210,180,140,1],
  9424. 'teal': [0,128,128,1], 'thistle': [216,191,216,1],
  9425. 'tomato': [255,99,71,1], 'turquoise': [64,224,208,1],
  9426. 'violet': [238,130,238,1], 'wheat': [245,222,179,1],
  9427. 'white': [255,255,255,1], 'whitesmoke': [245,245,245,1],
  9428. 'yellow': [255,255,0,1], 'yellowgreen': [154,205,50,1]
  9429. };
  9430. function clampCssByte(i) { // Clamp to integer 0 .. 255.
  9431. i = Math.round(i); // Seems to be what Chrome does (vs truncation).
  9432. return i < 0 ? 0 : i > 255 ? 255 : i;
  9433. }
  9434. function clampCssAngle(i) { // Clamp to integer 0 .. 360.
  9435. i = Math.round(i); // Seems to be what Chrome does (vs truncation).
  9436. return i < 0 ? 0 : i > 360 ? 360 : i;
  9437. }
  9438. function clampCssFloat(f) { // Clamp to float 0.0 .. 1.0.
  9439. return f < 0 ? 0 : f > 1 ? 1 : f;
  9440. }
  9441. function parseCssInt(str) { // int or percentage.
  9442. if (str.length && str.charAt(str.length - 1) === '%') {
  9443. return clampCssByte(parseFloat(str) / 100 * 255);
  9444. }
  9445. return clampCssByte(parseInt(str, 10));
  9446. }
  9447. function parseCssFloat(str) { // float or percentage.
  9448. if (str.length && str.charAt(str.length - 1) === '%') {
  9449. return clampCssFloat(parseFloat(str) / 100);
  9450. }
  9451. return clampCssFloat(parseFloat(str));
  9452. }
  9453. function cssHueToRgb(m1, m2, h) {
  9454. if (h < 0) {
  9455. h += 1;
  9456. }
  9457. else if (h > 1) {
  9458. h -= 1;
  9459. }
  9460. if (h * 6 < 1) {
  9461. return m1 + (m2 - m1) * h * 6;
  9462. }
  9463. if (h * 2 < 1) {
  9464. return m2;
  9465. }
  9466. if (h * 3 < 2) {
  9467. return m1 + (m2 - m1) * (2/3 - h) * 6;
  9468. }
  9469. return m1;
  9470. }
  9471. function lerp(a, b, p) {
  9472. return a + (b - a) * p;
  9473. }
  9474. function setRgba(out, r, g, b, a) {
  9475. out[0] = r; out[1] = g; out[2] = b; out[3] = a;
  9476. return out;
  9477. }
  9478. function copyRgba(out, a) {
  9479. out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3];
  9480. return out;
  9481. }
  9482. var colorCache = new LRU(20);
  9483. var lastRemovedArr = null;
  9484. function putToCache(colorStr, rgbaArr) {
  9485. // Reuse removed array
  9486. if (lastRemovedArr) {
  9487. copyRgba(lastRemovedArr, rgbaArr);
  9488. }
  9489. lastRemovedArr = colorCache.put(colorStr, lastRemovedArr || (rgbaArr.slice()));
  9490. }
  9491. /**
  9492. * @param {string} colorStr
  9493. * @param {Array.<number>} out
  9494. * @return {Array.<number>}
  9495. * @memberOf module:zrender/util/color
  9496. */
  9497. function parse(colorStr, rgbaArr) {
  9498. if (!colorStr) {
  9499. return;
  9500. }
  9501. rgbaArr = rgbaArr || [];
  9502. var cached = colorCache.get(colorStr);
  9503. if (cached) {
  9504. return copyRgba(rgbaArr, cached);
  9505. }
  9506. // colorStr may be not string
  9507. colorStr = colorStr + '';
  9508. // Remove all whitespace, not compliant, but should just be more accepting.
  9509. var str = colorStr.replace(/ /g, '').toLowerCase();
  9510. // Color keywords (and transparent) lookup.
  9511. if (str in kCSSColorTable) {
  9512. copyRgba(rgbaArr, kCSSColorTable[str]);
  9513. putToCache(colorStr, rgbaArr);
  9514. return rgbaArr;
  9515. }
  9516. // #abc and #abc123 syntax.
  9517. if (str.charAt(0) === '#') {
  9518. if (str.length === 4) {
  9519. var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing.
  9520. if (!(iv >= 0 && iv <= 0xfff)) {
  9521. setRgba(rgbaArr, 0, 0, 0, 1);
  9522. return; // Covers NaN.
  9523. }
  9524. setRgba(rgbaArr,
  9525. ((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8),
  9526. (iv & 0xf0) | ((iv & 0xf0) >> 4),
  9527. (iv & 0xf) | ((iv & 0xf) << 4),
  9528. 1
  9529. );
  9530. putToCache(colorStr, rgbaArr);
  9531. return rgbaArr;
  9532. }
  9533. else if (str.length === 7) {
  9534. var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing.
  9535. if (!(iv >= 0 && iv <= 0xffffff)) {
  9536. setRgba(rgbaArr, 0, 0, 0, 1);
  9537. return; // Covers NaN.
  9538. }
  9539. setRgba(rgbaArr,
  9540. (iv & 0xff0000) >> 16,
  9541. (iv & 0xff00) >> 8,
  9542. iv & 0xff,
  9543. 1
  9544. );
  9545. putToCache(colorStr, rgbaArr);
  9546. return rgbaArr;
  9547. }
  9548. return;
  9549. }
  9550. var op = str.indexOf('('), ep = str.indexOf(')');
  9551. if (op !== -1 && ep + 1 === str.length) {
  9552. var fname = str.substr(0, op);
  9553. var params = str.substr(op + 1, ep - (op + 1)).split(',');
  9554. var alpha = 1; // To allow case fallthrough.
  9555. switch (fname) {
  9556. case 'rgba':
  9557. if (params.length !== 4) {
  9558. setRgba(rgbaArr, 0, 0, 0, 1);
  9559. return;
  9560. }
  9561. alpha = parseCssFloat(params.pop()); // jshint ignore:line
  9562. // Fall through.
  9563. case 'rgb':
  9564. if (params.length !== 3) {
  9565. setRgba(rgbaArr, 0, 0, 0, 1);
  9566. return;
  9567. }
  9568. setRgba(rgbaArr,
  9569. parseCssInt(params[0]),
  9570. parseCssInt(params[1]),
  9571. parseCssInt(params[2]),
  9572. alpha
  9573. );
  9574. putToCache(colorStr, rgbaArr);
  9575. return rgbaArr;
  9576. case 'hsla':
  9577. if (params.length !== 4) {
  9578. setRgba(rgbaArr, 0, 0, 0, 1);
  9579. return;
  9580. }
  9581. params[3] = parseCssFloat(params[3]);
  9582. hsla2rgba(params, rgbaArr);
  9583. putToCache(colorStr, rgbaArr);
  9584. return rgbaArr;
  9585. case 'hsl':
  9586. if (params.length !== 3) {
  9587. setRgba(rgbaArr, 0, 0, 0, 1);
  9588. return;
  9589. }
  9590. hsla2rgba(params, rgbaArr);
  9591. putToCache(colorStr, rgbaArr);
  9592. return rgbaArr;
  9593. default:
  9594. return;
  9595. }
  9596. }
  9597. setRgba(rgbaArr, 0, 0, 0, 1);
  9598. return;
  9599. }
  9600. /**
  9601. * @param {Array.<number>} hsla
  9602. * @param {Array.<number>} rgba
  9603. * @return {Array.<number>} rgba
  9604. */
  9605. function hsla2rgba(hsla, rgba) {
  9606. var h = (((parseFloat(hsla[0]) % 360) + 360) % 360) / 360; // 0 .. 1
  9607. // NOTE(deanm): According to the CSS spec s/l should only be
  9608. // percentages, but we don't bother and let float or percentage.
  9609. var s = parseCssFloat(hsla[1]);
  9610. var l = parseCssFloat(hsla[2]);
  9611. var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
  9612. var m1 = l * 2 - m2;
  9613. rgba = rgba || [];
  9614. setRgba(rgba,
  9615. clampCssByte(cssHueToRgb(m1, m2, h + 1 / 3) * 255),
  9616. clampCssByte(cssHueToRgb(m1, m2, h) * 255),
  9617. clampCssByte(cssHueToRgb(m1, m2, h - 1 / 3) * 255),
  9618. 1
  9619. );
  9620. if (hsla.length === 4) {
  9621. rgba[3] = hsla[3];
  9622. }
  9623. return rgba;
  9624. }
  9625. /**
  9626. * @param {Array.<number>} rgba
  9627. * @return {Array.<number>} hsla
  9628. */
  9629. function rgba2hsla(rgba) {
  9630. if (!rgba) {
  9631. return;
  9632. }
  9633. // RGB from 0 to 255
  9634. var R = rgba[0] / 255;
  9635. var G = rgba[1] / 255;
  9636. var B = rgba[2] / 255;
  9637. var vMin = Math.min(R, G, B); // Min. value of RGB
  9638. var vMax = Math.max(R, G, B); // Max. value of RGB
  9639. var delta = vMax - vMin; // Delta RGB value
  9640. var L = (vMax + vMin) / 2;
  9641. var H;
  9642. var S;
  9643. // HSL results from 0 to 1
  9644. if (delta === 0) {
  9645. H = 0;
  9646. S = 0;
  9647. }
  9648. else {
  9649. if (L < 0.5) {
  9650. S = delta / (vMax + vMin);
  9651. }
  9652. else {
  9653. S = delta / (2 - vMax - vMin);
  9654. }
  9655. var deltaR = (((vMax - R) / 6) + (delta / 2)) / delta;
  9656. var deltaG = (((vMax - G) / 6) + (delta / 2)) / delta;
  9657. var deltaB = (((vMax - B) / 6) + (delta / 2)) / delta;
  9658. if (R === vMax) {
  9659. H = deltaB - deltaG;
  9660. }
  9661. else if (G === vMax) {
  9662. H = (1 / 3) + deltaR - deltaB;
  9663. }
  9664. else if (B === vMax) {
  9665. H = (2 / 3) + deltaG - deltaR;
  9666. }
  9667. if (H < 0) {
  9668. H += 1;
  9669. }
  9670. if (H > 1) {
  9671. H -= 1;
  9672. }
  9673. }
  9674. var hsla = [H * 360, S, L];
  9675. if (rgba[3] != null) {
  9676. hsla.push(rgba[3]);
  9677. }
  9678. return hsla;
  9679. }
  9680. /**
  9681. * @param {string} color
  9682. * @param {number} level
  9683. * @return {string}
  9684. * @memberOf module:zrender/util/color
  9685. */
  9686. function lift(color, level) {
  9687. var colorArr = parse(color);
  9688. if (colorArr) {
  9689. for (var i = 0; i < 3; i++) {
  9690. if (level < 0) {
  9691. colorArr[i] = colorArr[i] * (1 - level) | 0;
  9692. }
  9693. else {
  9694. colorArr[i] = ((255 - colorArr[i]) * level + colorArr[i]) | 0;
  9695. }
  9696. }
  9697. return stringify(colorArr, colorArr.length === 4 ? 'rgba' : 'rgb');
  9698. }
  9699. }
  9700. /**
  9701. * @param {string} color
  9702. * @return {string}
  9703. * @memberOf module:zrender/util/color
  9704. */
  9705. function toHex(color, level) {
  9706. var colorArr = parse(color);
  9707. if (colorArr) {
  9708. return ((1 << 24) + (colorArr[0] << 16) + (colorArr[1] << 8) + (+colorArr[2])).toString(16).slice(1);
  9709. }
  9710. }
  9711. /**
  9712. * Map value to color. Faster than mapToColor methods because color is represented by rgba array.
  9713. * @param {number} normalizedValue A float between 0 and 1.
  9714. * @param {Array.<Array.<number>>} colors List of rgba color array
  9715. * @param {Array.<number>} [out] Mapped gba color array
  9716. * @return {Array.<number>} will be null/undefined if input illegal.
  9717. */
  9718. function fastMapToColor(normalizedValue, colors, out) {
  9719. if (!(colors && colors.length)
  9720. || !(normalizedValue >= 0 && normalizedValue <= 1)
  9721. ) {
  9722. return;
  9723. }
  9724. out = out || [];
  9725. var value = normalizedValue * (colors.length - 1);
  9726. var leftIndex = Math.floor(value);
  9727. var rightIndex = Math.ceil(value);
  9728. var leftColor = colors[leftIndex];
  9729. var rightColor = colors[rightIndex];
  9730. var dv = value - leftIndex;
  9731. out[0] = clampCssByte(lerp(leftColor[0], rightColor[0], dv));
  9732. out[1] = clampCssByte(lerp(leftColor[1], rightColor[1], dv));
  9733. out[2] = clampCssByte(lerp(leftColor[2], rightColor[2], dv));
  9734. out[3] = clampCssFloat(lerp(leftColor[3], rightColor[3], dv));
  9735. return out;
  9736. }
  9737. /**
  9738. * @param {number} normalizedValue A float between 0 and 1.
  9739. * @param {Array.<string>} colors Color list.
  9740. * @param {boolean=} fullOutput Default false.
  9741. * @return {(string|Object)} Result color. If fullOutput,
  9742. * return {color: ..., leftIndex: ..., rightIndex: ..., value: ...},
  9743. * @memberOf module:zrender/util/color
  9744. */
  9745. function mapToColor(normalizedValue, colors, fullOutput) {
  9746. if (!(colors && colors.length)
  9747. || !(normalizedValue >= 0 && normalizedValue <= 1)
  9748. ) {
  9749. return;
  9750. }
  9751. var value = normalizedValue * (colors.length - 1);
  9752. var leftIndex = Math.floor(value);
  9753. var rightIndex = Math.ceil(value);
  9754. var leftColor = parse(colors[leftIndex]);
  9755. var rightColor = parse(colors[rightIndex]);
  9756. var dv = value - leftIndex;
  9757. var color = stringify(
  9758. [
  9759. clampCssByte(lerp(leftColor[0], rightColor[0], dv)),
  9760. clampCssByte(lerp(leftColor[1], rightColor[1], dv)),
  9761. clampCssByte(lerp(leftColor[2], rightColor[2], dv)),
  9762. clampCssFloat(lerp(leftColor[3], rightColor[3], dv))
  9763. ],
  9764. 'rgba'
  9765. );
  9766. return fullOutput
  9767. ? {
  9768. color: color,
  9769. leftIndex: leftIndex,
  9770. rightIndex: rightIndex,
  9771. value: value
  9772. }
  9773. : color;
  9774. }
  9775. /**
  9776. * @param {string} color
  9777. * @param {number=} h 0 ~ 360, ignore when null.
  9778. * @param {number=} s 0 ~ 1, ignore when null.
  9779. * @param {number=} l 0 ~ 1, ignore when null.
  9780. * @return {string} Color string in rgba format.
  9781. * @memberOf module:zrender/util/color
  9782. */
  9783. function modifyHSL(color, h, s, l) {
  9784. color = parse(color);
  9785. if (color) {
  9786. color = rgba2hsla(color);
  9787. h != null && (color[0] = clampCssAngle(h));
  9788. s != null && (color[1] = parseCssFloat(s));
  9789. l != null && (color[2] = parseCssFloat(l));
  9790. return stringify(hsla2rgba(color), 'rgba');
  9791. }
  9792. }
  9793. /**
  9794. * @param {string} color
  9795. * @param {number=} alpha 0 ~ 1
  9796. * @return {string} Color string in rgba format.
  9797. * @memberOf module:zrender/util/color
  9798. */
  9799. function modifyAlpha(color, alpha) {
  9800. color = parse(color);
  9801. if (color && alpha != null) {
  9802. color[3] = clampCssFloat(alpha);
  9803. return stringify(color, 'rgba');
  9804. }
  9805. }
  9806. /**
  9807. * @param {Array.<number>} arrColor like [12,33,44,0.4]
  9808. * @param {string} type 'rgba', 'hsva', ...
  9809. * @return {string} Result color. (If input illegal, return undefined).
  9810. */
  9811. function stringify(arrColor, type) {
  9812. if (!arrColor || !arrColor.length) {
  9813. return;
  9814. }
  9815. var colorStr = arrColor[0] + ',' + arrColor[1] + ',' + arrColor[2];
  9816. if (type === 'rgba' || type === 'hsva' || type === 'hsla') {
  9817. colorStr += ',' + arrColor[3];
  9818. }
  9819. return type + '(' + colorStr + ')';
  9820. }
  9821. module.exports = {
  9822. parse: parse,
  9823. lift: lift,
  9824. toHex: toHex,
  9825. fastMapToColor: fastMapToColor,
  9826. mapToColor: mapToColor,
  9827. modifyHSL: modifyHSL,
  9828. modifyAlpha: modifyAlpha,
  9829. stringify: stringify
  9830. };
  9831. /***/ },
  9832. /* 32 */
  9833. /***/ function(module, exports) {
  9834. // Simple LRU cache use doubly linked list
  9835. // @module zrender/core/LRU
  9836. /**
  9837. * Simple double linked list. Compared with array, it has O(1) remove operation.
  9838. * @constructor
  9839. */
  9840. var LinkedList = function () {
  9841. /**
  9842. * @type {module:zrender/core/LRU~Entry}
  9843. */
  9844. this.head = null;
  9845. /**
  9846. * @type {module:zrender/core/LRU~Entry}
  9847. */
  9848. this.tail = null;
  9849. this._len = 0;
  9850. };
  9851. var linkedListProto = LinkedList.prototype;
  9852. /**
  9853. * Insert a new value at the tail
  9854. * @param {} val
  9855. * @return {module:zrender/core/LRU~Entry}
  9856. */
  9857. linkedListProto.insert = function (val) {
  9858. var entry = new Entry(val);
  9859. this.insertEntry(entry);
  9860. return entry;
  9861. };
  9862. /**
  9863. * Insert an entry at the tail
  9864. * @param {module:zrender/core/LRU~Entry} entry
  9865. */
  9866. linkedListProto.insertEntry = function (entry) {
  9867. if (!this.head) {
  9868. this.head = this.tail = entry;
  9869. }
  9870. else {
  9871. this.tail.next = entry;
  9872. entry.prev = this.tail;
  9873. entry.next = null;
  9874. this.tail = entry;
  9875. }
  9876. this._len++;
  9877. };
  9878. /**
  9879. * Remove entry.
  9880. * @param {module:zrender/core/LRU~Entry} entry
  9881. */
  9882. linkedListProto.remove = function (entry) {
  9883. var prev = entry.prev;
  9884. var next = entry.next;
  9885. if (prev) {
  9886. prev.next = next;
  9887. }
  9888. else {
  9889. // Is head
  9890. this.head = next;
  9891. }
  9892. if (next) {
  9893. next.prev = prev;
  9894. }
  9895. else {
  9896. // Is tail
  9897. this.tail = prev;
  9898. }
  9899. entry.next = entry.prev = null;
  9900. this._len--;
  9901. };
  9902. /**
  9903. * @return {number}
  9904. */
  9905. linkedListProto.len = function () {
  9906. return this._len;
  9907. };
  9908. /**
  9909. * Clear list
  9910. */
  9911. linkedListProto.clear = function () {
  9912. this.head = this.tail = null;
  9913. this._len = 0;
  9914. };
  9915. /**
  9916. * @constructor
  9917. * @param {} val
  9918. */
  9919. var Entry = function (val) {
  9920. /**
  9921. * @type {}
  9922. */
  9923. this.value = val;
  9924. /**
  9925. * @type {module:zrender/core/LRU~Entry}
  9926. */
  9927. this.next;
  9928. /**
  9929. * @type {module:zrender/core/LRU~Entry}
  9930. */
  9931. this.prev;
  9932. };
  9933. /**
  9934. * LRU Cache
  9935. * @constructor
  9936. * @alias module:zrender/core/LRU
  9937. */
  9938. var LRU = function (maxSize) {
  9939. this._list = new LinkedList();
  9940. this._map = {};
  9941. this._maxSize = maxSize || 10;
  9942. this._lastRemovedEntry = null;
  9943. };
  9944. var LRUProto = LRU.prototype;
  9945. /**
  9946. * @param {string} key
  9947. * @param {} value
  9948. * @return {} Removed value
  9949. */
  9950. LRUProto.put = function (key, value) {
  9951. var list = this._list;
  9952. var map = this._map;
  9953. var removed = null;
  9954. if (map[key] == null) {
  9955. var len = list.len();
  9956. // Reuse last removed entry
  9957. var entry = this._lastRemovedEntry;
  9958. if (len >= this._maxSize && len > 0) {
  9959. // Remove the least recently used
  9960. var leastUsedEntry = list.head;
  9961. list.remove(leastUsedEntry);
  9962. delete map[leastUsedEntry.key];
  9963. removed = leastUsedEntry.value;
  9964. this._lastRemovedEntry = leastUsedEntry;
  9965. }
  9966. if (entry) {
  9967. entry.value = value;
  9968. }
  9969. else {
  9970. entry = new Entry(value);
  9971. }
  9972. entry.key = key;
  9973. list.insertEntry(entry);
  9974. map[key] = entry;
  9975. }
  9976. return removed;
  9977. };
  9978. /**
  9979. * @param {string} key
  9980. * @return {}
  9981. */
  9982. LRUProto.get = function (key) {
  9983. var entry = this._map[key];
  9984. var list = this._list;
  9985. if (entry != null) {
  9986. // Put the latest used entry in the tail
  9987. if (entry !== list.tail) {
  9988. list.remove(entry);
  9989. list.insertEntry(entry);
  9990. }
  9991. return entry.value;
  9992. }
  9993. };
  9994. /**
  9995. * Clear the cache
  9996. */
  9997. LRUProto.clear = function () {
  9998. this._list.clear();
  9999. this._map = {};
  10000. };
  10001. module.exports = LRU;
  10002. /***/ },
  10003. /* 33 */
  10004. /***/ function(module, exports, __webpack_require__) {
  10005. var config = __webpack_require__(34);
  10006. /**
  10007. * @exports zrender/tool/log
  10008. * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
  10009. */
  10010. module.exports = function() {
  10011. if (config.debugMode === 0) {
  10012. return;
  10013. }
  10014. else if (config.debugMode == 1) {
  10015. for (var k in arguments) {
  10016. throw new Error(arguments[k]);
  10017. }
  10018. }
  10019. else if (config.debugMode > 1) {
  10020. for (var k in arguments) {
  10021. console.log(arguments[k]);
  10022. }
  10023. }
  10024. };
  10025. /* for debug
  10026. return function(mes) {
  10027. document.getElementById('wrong-message').innerHTML =
  10028. mes + ' ' + (new Date() - 0)
  10029. + '<br/>'
  10030. + document.getElementById('wrong-message').innerHTML;
  10031. };
  10032. */
  10033. /***/ },
  10034. /* 34 */
  10035. /***/ function(module, exports) {
  10036. var dpr = 1;
  10037. // If in browser environment
  10038. if (typeof window !== 'undefined') {
  10039. dpr = Math.max(window.devicePixelRatio || 1, 1);
  10040. }
  10041. /**
  10042. * config默认配置项
  10043. * @exports zrender/config
  10044. * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
  10045. */
  10046. var config = {
  10047. /**
  10048. * debug日志选项:catchBrushException为true下有效
  10049. * 0 : 不生成debug数据,发布用
  10050. * 1 : 异常抛出,调试用
  10051. * 2 : 控制台输出,调试用
  10052. */
  10053. debugMode: 0,
  10054. // retina 屏幕优化
  10055. devicePixelRatio: dpr
  10056. };
  10057. module.exports = config;
  10058. /***/ },
  10059. /* 35 */
  10060. /***/ function(module, exports, __webpack_require__) {
  10061. /**
  10062. * Mixin for drawing text in a element bounding rect
  10063. * @module zrender/mixin/RectText
  10064. */
  10065. var textContain = __webpack_require__(8);
  10066. var BoundingRect = __webpack_require__(9);
  10067. var tmpRect = new BoundingRect();
  10068. var RectText = function () {};
  10069. function parsePercent(value, maxValue) {
  10070. if (typeof value === 'string') {
  10071. if (value.lastIndexOf('%') >= 0) {
  10072. return parseFloat(value) / 100 * maxValue;
  10073. }
  10074. return parseFloat(value);
  10075. }
  10076. return value;
  10077. }
  10078. RectText.prototype = {
  10079. constructor: RectText,
  10080. /**
  10081. * Draw text in a rect with specified position.
  10082. * @param {CanvasRenderingContext} ctx
  10083. * @param {Object} rect Displayable rect
  10084. * @return {Object} textRect Alternative precalculated text bounding rect
  10085. */
  10086. drawRectText: function (ctx, rect, textRect) {
  10087. var style = this.style;
  10088. var text = style.text;
  10089. // Convert to string
  10090. text != null && (text += '');
  10091. if (!text) {
  10092. return;
  10093. }
  10094. // FIXME
  10095. ctx.save();
  10096. var x;
  10097. var y;
  10098. var textPosition = style.textPosition;
  10099. var textOffset = style.textOffset;
  10100. var distance = style.textDistance;
  10101. var align = style.textAlign;
  10102. var font = style.textFont || style.font;
  10103. var baseline = style.textBaseline;
  10104. var verticalAlign = style.textVerticalAlign;
  10105. textRect = textRect || textContain.getBoundingRect(text, font, align, baseline);
  10106. // Transform rect to view space
  10107. var transform = this.transform;
  10108. if (!style.textTransform) {
  10109. if (transform) {
  10110. tmpRect.copy(rect);
  10111. tmpRect.applyTransform(transform);
  10112. rect = tmpRect;
  10113. }
  10114. }
  10115. else {
  10116. this.setTransform(ctx);
  10117. }
  10118. // Text position represented by coord
  10119. if (textPosition instanceof Array) {
  10120. // Percent
  10121. x = rect.x + parsePercent(textPosition[0], rect.width);
  10122. y = rect.y + parsePercent(textPosition[1], rect.height);
  10123. align = align || 'left';
  10124. baseline = baseline || 'top';
  10125. if (verticalAlign) {
  10126. switch (verticalAlign) {
  10127. case 'middle':
  10128. y -= textRect.height / 2 - textRect.lineHeight / 2;
  10129. break;
  10130. case 'bottom':
  10131. y -= textRect.height - textRect.lineHeight / 2;
  10132. break;
  10133. default:
  10134. y += textRect.lineHeight / 2;
  10135. }
  10136. // Force bseline to be middle
  10137. baseline = 'middle';
  10138. }
  10139. }
  10140. else {
  10141. var res = textContain.adjustTextPositionOnRect(
  10142. textPosition, rect, textRect, distance
  10143. );
  10144. x = res.x;
  10145. y = res.y;
  10146. // Default align and baseline when has textPosition
  10147. align = align || res.textAlign;
  10148. baseline = baseline || res.textBaseline;
  10149. }
  10150. if (textOffset) {
  10151. x += textOffset[0];
  10152. y += textOffset[1];
  10153. }
  10154. // Use canvas default left textAlign. Giving invalid value will cause state not change
  10155. ctx.textAlign = align || 'left';
  10156. // Use canvas default alphabetic baseline
  10157. ctx.textBaseline = baseline || 'alphabetic';
  10158. var textFill = style.textFill;
  10159. var textStroke = style.textStroke;
  10160. textFill && (ctx.fillStyle = textFill);
  10161. textStroke && (ctx.strokeStyle = textStroke);
  10162. // TODO Invalid font
  10163. ctx.font = font || '12px sans-serif';
  10164. // Text shadow
  10165. // Always set shadowBlur and shadowOffset to avoid leak from displayable
  10166. ctx.shadowBlur = style.textShadowBlur;
  10167. ctx.shadowColor = style.textShadowColor || 'transparent';
  10168. ctx.shadowOffsetX = style.textShadowOffsetX;
  10169. ctx.shadowOffsetY = style.textShadowOffsetY;
  10170. var textLines = text.split('\n');
  10171. if (style.textRotation) {
  10172. transform && ctx.translate(transform[4], transform[5]);
  10173. ctx.rotate(style.textRotation);
  10174. transform && ctx.translate(-transform[4], -transform[5]);
  10175. }
  10176. for (var i = 0; i < textLines.length; i++) {
  10177. // Fill after stroke so the outline will not cover the main part.
  10178. textStroke && ctx.strokeText(textLines[i], x, y);
  10179. textFill && ctx.fillText(textLines[i], x, y);
  10180. y += textRect.lineHeight;
  10181. }
  10182. ctx.restore();
  10183. }
  10184. };
  10185. module.exports = RectText;
  10186. /***/ },
  10187. /* 36 */
  10188. /***/ function(module, exports, __webpack_require__) {
  10189. 'use strict';
  10190. /**
  10191. * Path 代理,可以在`buildPath`中用于替代`ctx`, 会保存每个path操作的命令到pathCommands属性中
  10192. * 可以用于 isInsidePath 判断以及获取boundingRect
  10193. *
  10194. * @module zrender/core/PathProxy
  10195. * @author Yi Shen (http://www.github.com/pissang)
  10196. */
  10197. // TODO getTotalLength, getPointAtLength
  10198. var curve = __webpack_require__(37);
  10199. var vec2 = __webpack_require__(10);
  10200. var bbox = __webpack_require__(38);
  10201. var BoundingRect = __webpack_require__(9);
  10202. var dpr = __webpack_require__(34).devicePixelRatio;
  10203. var CMD = {
  10204. M: 1,
  10205. L: 2,
  10206. C: 3,
  10207. Q: 4,
  10208. A: 5,
  10209. Z: 6,
  10210. // Rect
  10211. R: 7
  10212. };
  10213. // var CMD_MEM_SIZE = {
  10214. // M: 3,
  10215. // L: 3,
  10216. // C: 7,
  10217. // Q: 5,
  10218. // A: 9,
  10219. // R: 5,
  10220. // Z: 1
  10221. // };
  10222. var min = [];
  10223. var max = [];
  10224. var min2 = [];
  10225. var max2 = [];
  10226. var mathMin = Math.min;
  10227. var mathMax = Math.max;
  10228. var mathCos = Math.cos;
  10229. var mathSin = Math.sin;
  10230. var mathSqrt = Math.sqrt;
  10231. var mathAbs = Math.abs;
  10232. var hasTypedArray = typeof Float32Array != 'undefined';
  10233. /**
  10234. * @alias module:zrender/core/PathProxy
  10235. * @constructor
  10236. */
  10237. var PathProxy = function (notSaveData) {
  10238. this._saveData = !(notSaveData || false);
  10239. if (this._saveData) {
  10240. /**
  10241. * Path data. Stored as flat array
  10242. * @type {Array.<Object>}
  10243. */
  10244. this.data = [];
  10245. }
  10246. this._ctx = null;
  10247. };
  10248. /**
  10249. * 快速计算Path包围盒(并不是最小包围盒)
  10250. * @return {Object}
  10251. */
  10252. PathProxy.prototype = {
  10253. constructor: PathProxy,
  10254. _xi: 0,
  10255. _yi: 0,
  10256. _x0: 0,
  10257. _y0: 0,
  10258. // Unit x, Unit y. Provide for avoiding drawing that too short line segment
  10259. _ux: 0,
  10260. _uy: 0,
  10261. _len: 0,
  10262. _lineDash: null,
  10263. _dashOffset: 0,
  10264. _dashIdx: 0,
  10265. _dashSum: 0,
  10266. /**
  10267. * @readOnly
  10268. */
  10269. setScale: function (sx, sy) {
  10270. this._ux = mathAbs(1 / dpr / sx) || 0;
  10271. this._uy = mathAbs(1 / dpr / sy) || 0;
  10272. },
  10273. getContext: function () {
  10274. return this._ctx;
  10275. },
  10276. /**
  10277. * @param {CanvasRenderingContext2D} ctx
  10278. * @return {module:zrender/core/PathProxy}
  10279. */
  10280. beginPath: function (ctx) {
  10281. this._ctx = ctx;
  10282. ctx && ctx.beginPath();
  10283. ctx && (this.dpr = ctx.dpr);
  10284. // Reset
  10285. if (this._saveData) {
  10286. this._len = 0;
  10287. }
  10288. if (this._lineDash) {
  10289. this._lineDash = null;
  10290. this._dashOffset = 0;
  10291. }
  10292. return this;
  10293. },
  10294. /**
  10295. * @param {number} x
  10296. * @param {number} y
  10297. * @return {module:zrender/core/PathProxy}
  10298. */
  10299. moveTo: function (x, y) {
  10300. this.addData(CMD.M, x, y);
  10301. this._ctx && this._ctx.moveTo(x, y);
  10302. // x0, y0, xi, yi 是记录在 _dashedXXXXTo 方法中使用
  10303. // xi, yi 记录当前点, x0, y0 在 closePath 的时候回到起始点。
  10304. // 有可能在 beginPath 之后直接调用 lineTo,这时候 x0, y0 需要
  10305. // 在 lineTo 方法中记录,这里先不考虑这种情况,dashed line 也只在 IE10- 中不支持
  10306. this._x0 = x;
  10307. this._y0 = y;
  10308. this._xi = x;
  10309. this._yi = y;
  10310. return this;
  10311. },
  10312. /**
  10313. * @param {number} x
  10314. * @param {number} y
  10315. * @return {module:zrender/core/PathProxy}
  10316. */
  10317. lineTo: function (x, y) {
  10318. var exceedUnit = mathAbs(x - this._xi) > this._ux
  10319. || mathAbs(y - this._yi) > this._uy
  10320. // Force draw the first segment
  10321. || this._len < 5;
  10322. this.addData(CMD.L, x, y);
  10323. if (this._ctx && exceedUnit) {
  10324. this._needsDash() ? this._dashedLineTo(x, y)
  10325. : this._ctx.lineTo(x, y);
  10326. }
  10327. if (exceedUnit) {
  10328. this._xi = x;
  10329. this._yi = y;
  10330. }
  10331. return this;
  10332. },
  10333. /**
  10334. * @param {number} x1
  10335. * @param {number} y1
  10336. * @param {number} x2
  10337. * @param {number} y2
  10338. * @param {number} x3
  10339. * @param {number} y3
  10340. * @return {module:zrender/core/PathProxy}
  10341. */
  10342. bezierCurveTo: function (x1, y1, x2, y2, x3, y3) {
  10343. this.addData(CMD.C, x1, y1, x2, y2, x3, y3);
  10344. if (this._ctx) {
  10345. this._needsDash() ? this._dashedBezierTo(x1, y1, x2, y2, x3, y3)
  10346. : this._ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3);
  10347. }
  10348. this._xi = x3;
  10349. this._yi = y3;
  10350. return this;
  10351. },
  10352. /**
  10353. * @param {number} x1
  10354. * @param {number} y1
  10355. * @param {number} x2
  10356. * @param {number} y2
  10357. * @return {module:zrender/core/PathProxy}
  10358. */
  10359. quadraticCurveTo: function (x1, y1, x2, y2) {
  10360. this.addData(CMD.Q, x1, y1, x2, y2);
  10361. if (this._ctx) {
  10362. this._needsDash() ? this._dashedQuadraticTo(x1, y1, x2, y2)
  10363. : this._ctx.quadraticCurveTo(x1, y1, x2, y2);
  10364. }
  10365. this._xi = x2;
  10366. this._yi = y2;
  10367. return this;
  10368. },
  10369. /**
  10370. * @param {number} cx
  10371. * @param {number} cy
  10372. * @param {number} r
  10373. * @param {number} startAngle
  10374. * @param {number} endAngle
  10375. * @param {boolean} anticlockwise
  10376. * @return {module:zrender/core/PathProxy}
  10377. */
  10378. arc: function (cx, cy, r, startAngle, endAngle, anticlockwise) {
  10379. this.addData(
  10380. CMD.A, cx, cy, r, r, startAngle, endAngle - startAngle, 0, anticlockwise ? 0 : 1
  10381. );
  10382. this._ctx && this._ctx.arc(cx, cy, r, startAngle, endAngle, anticlockwise);
  10383. this._xi = mathCos(endAngle) * r + cx;
  10384. this._yi = mathSin(endAngle) * r + cx;
  10385. return this;
  10386. },
  10387. // TODO
  10388. arcTo: function (x1, y1, x2, y2, radius) {
  10389. if (this._ctx) {
  10390. this._ctx.arcTo(x1, y1, x2, y2, radius);
  10391. }
  10392. return this;
  10393. },
  10394. // TODO
  10395. rect: function (x, y, w, h) {
  10396. this._ctx && this._ctx.rect(x, y, w, h);
  10397. this.addData(CMD.R, x, y, w, h);
  10398. return this;
  10399. },
  10400. /**
  10401. * @return {module:zrender/core/PathProxy}
  10402. */
  10403. closePath: function () {
  10404. this.addData(CMD.Z);
  10405. var ctx = this._ctx;
  10406. var x0 = this._x0;
  10407. var y0 = this._y0;
  10408. if (ctx) {
  10409. this._needsDash() && this._dashedLineTo(x0, y0);
  10410. ctx.closePath();
  10411. }
  10412. this._xi = x0;
  10413. this._yi = y0;
  10414. return this;
  10415. },
  10416. /**
  10417. * Context 从外部传入,因为有可能是 rebuildPath 完之后再 fill。
  10418. * stroke 同样
  10419. * @param {CanvasRenderingContext2D} ctx
  10420. * @return {module:zrender/core/PathProxy}
  10421. */
  10422. fill: function (ctx) {
  10423. ctx && ctx.fill();
  10424. this.toStatic();
  10425. },
  10426. /**
  10427. * @param {CanvasRenderingContext2D} ctx
  10428. * @return {module:zrender/core/PathProxy}
  10429. */
  10430. stroke: function (ctx) {
  10431. ctx && ctx.stroke();
  10432. this.toStatic();
  10433. },
  10434. /**
  10435. * 必须在其它绘制命令前调用
  10436. * Must be invoked before all other path drawing methods
  10437. * @return {module:zrender/core/PathProxy}
  10438. */
  10439. setLineDash: function (lineDash) {
  10440. if (lineDash instanceof Array) {
  10441. this._lineDash = lineDash;
  10442. this._dashIdx = 0;
  10443. var lineDashSum = 0;
  10444. for (var i = 0; i < lineDash.length; i++) {
  10445. lineDashSum += lineDash[i];
  10446. }
  10447. this._dashSum = lineDashSum;
  10448. }
  10449. return this;
  10450. },
  10451. /**
  10452. * 必须在其它绘制命令前调用
  10453. * Must be invoked before all other path drawing methods
  10454. * @return {module:zrender/core/PathProxy}
  10455. */
  10456. setLineDashOffset: function (offset) {
  10457. this._dashOffset = offset;
  10458. return this;
  10459. },
  10460. /**
  10461. *
  10462. * @return {boolean}
  10463. */
  10464. len: function () {
  10465. return this._len;
  10466. },
  10467. /**
  10468. * 直接设置 Path 数据
  10469. */
  10470. setData: function (data) {
  10471. var len = data.length;
  10472. if (! (this.data && this.data.length == len) && hasTypedArray) {
  10473. this.data = new Float32Array(len);
  10474. }
  10475. for (var i = 0; i < len; i++) {
  10476. this.data[i] = data[i];
  10477. }
  10478. this._len = len;
  10479. },
  10480. /**
  10481. * 添加子路径
  10482. * @param {module:zrender/core/PathProxy|Array.<module:zrender/core/PathProxy>} path
  10483. */
  10484. appendPath: function (path) {
  10485. if (!(path instanceof Array)) {
  10486. path = [path];
  10487. }
  10488. var len = path.length;
  10489. var appendSize = 0;
  10490. var offset = this._len;
  10491. for (var i = 0; i < len; i++) {
  10492. appendSize += path[i].len();
  10493. }
  10494. if (hasTypedArray && (this.data instanceof Float32Array)) {
  10495. this.data = new Float32Array(offset + appendSize);
  10496. }
  10497. for (var i = 0; i < len; i++) {
  10498. var appendPathData = path[i].data;
  10499. for (var k = 0; k < appendPathData.length; k++) {
  10500. this.data[offset++] = appendPathData[k];
  10501. }
  10502. }
  10503. this._len = offset;
  10504. },
  10505. /**
  10506. * 填充 Path 数据。
  10507. * 尽量复用而不申明新的数组。大部分图形重绘的指令数据长度都是不变的。
  10508. */
  10509. addData: function (cmd) {
  10510. if (!this._saveData) {
  10511. return;
  10512. }
  10513. var data = this.data;
  10514. if (this._len + arguments.length > data.length) {
  10515. // 因为之前的数组已经转换成静态的 Float32Array
  10516. // 所以不够用时需要扩展一个新的动态数组
  10517. this._expandData();
  10518. data = this.data;
  10519. }
  10520. for (var i = 0; i < arguments.length; i++) {
  10521. data[this._len++] = arguments[i];
  10522. }
  10523. this._prevCmd = cmd;
  10524. },
  10525. _expandData: function () {
  10526. // Only if data is Float32Array
  10527. if (!(this.data instanceof Array)) {
  10528. var newData = [];
  10529. for (var i = 0; i < this._len; i++) {
  10530. newData[i] = this.data[i];
  10531. }
  10532. this.data = newData;
  10533. }
  10534. },
  10535. /**
  10536. * If needs js implemented dashed line
  10537. * @return {boolean}
  10538. * @private
  10539. */
  10540. _needsDash: function () {
  10541. return this._lineDash;
  10542. },
  10543. _dashedLineTo: function (x1, y1) {
  10544. var dashSum = this._dashSum;
  10545. var offset = this._dashOffset;
  10546. var lineDash = this._lineDash;
  10547. var ctx = this._ctx;
  10548. var x0 = this._xi;
  10549. var y0 = this._yi;
  10550. var dx = x1 - x0;
  10551. var dy = y1 - y0;
  10552. var dist = mathSqrt(dx * dx + dy * dy);
  10553. var x = x0;
  10554. var y = y0;
  10555. var dash;
  10556. var nDash = lineDash.length;
  10557. var idx;
  10558. dx /= dist;
  10559. dy /= dist;
  10560. if (offset < 0) {
  10561. // Convert to positive offset
  10562. offset = dashSum + offset;
  10563. }
  10564. offset %= dashSum;
  10565. x -= offset * dx;
  10566. y -= offset * dy;
  10567. while ((dx > 0 && x <= x1) || (dx < 0 && x >= x1)
  10568. || (dx == 0 && ((dy > 0 && y <= y1) || (dy < 0 && y >= y1)))) {
  10569. idx = this._dashIdx;
  10570. dash = lineDash[idx];
  10571. x += dx * dash;
  10572. y += dy * dash;
  10573. this._dashIdx = (idx + 1) % nDash;
  10574. // Skip positive offset
  10575. if ((dx > 0 && x < x0) || (dx < 0 && x > x0) || (dy > 0 && y < y0) || (dy < 0 && y > y0)) {
  10576. continue;
  10577. }
  10578. ctx[idx % 2 ? 'moveTo' : 'lineTo'](
  10579. dx >= 0 ? mathMin(x, x1) : mathMax(x, x1),
  10580. dy >= 0 ? mathMin(y, y1) : mathMax(y, y1)
  10581. );
  10582. }
  10583. // Offset for next lineTo
  10584. dx = x - x1;
  10585. dy = y - y1;
  10586. this._dashOffset = -mathSqrt(dx * dx + dy * dy);
  10587. },
  10588. // Not accurate dashed line to
  10589. _dashedBezierTo: function (x1, y1, x2, y2, x3, y3) {
  10590. var dashSum = this._dashSum;
  10591. var offset = this._dashOffset;
  10592. var lineDash = this._lineDash;
  10593. var ctx = this._ctx;
  10594. var x0 = this._xi;
  10595. var y0 = this._yi;
  10596. var t;
  10597. var dx;
  10598. var dy;
  10599. var cubicAt = curve.cubicAt;
  10600. var bezierLen = 0;
  10601. var idx = this._dashIdx;
  10602. var nDash = lineDash.length;
  10603. var x;
  10604. var y;
  10605. var tmpLen = 0;
  10606. if (offset < 0) {
  10607. // Convert to positive offset
  10608. offset = dashSum + offset;
  10609. }
  10610. offset %= dashSum;
  10611. // Bezier approx length
  10612. for (t = 0; t < 1; t += 0.1) {
  10613. dx = cubicAt(x0, x1, x2, x3, t + 0.1)
  10614. - cubicAt(x0, x1, x2, x3, t);
  10615. dy = cubicAt(y0, y1, y2, y3, t + 0.1)
  10616. - cubicAt(y0, y1, y2, y3, t);
  10617. bezierLen += mathSqrt(dx * dx + dy * dy);
  10618. }
  10619. // Find idx after add offset
  10620. for (; idx < nDash; idx++) {
  10621. tmpLen += lineDash[idx];
  10622. if (tmpLen > offset) {
  10623. break;
  10624. }
  10625. }
  10626. t = (tmpLen - offset) / bezierLen;
  10627. while (t <= 1) {
  10628. x = cubicAt(x0, x1, x2, x3, t);
  10629. y = cubicAt(y0, y1, y2, y3, t);
  10630. // Use line to approximate dashed bezier
  10631. // Bad result if dash is long
  10632. idx % 2 ? ctx.moveTo(x, y)
  10633. : ctx.lineTo(x, y);
  10634. t += lineDash[idx] / bezierLen;
  10635. idx = (idx + 1) % nDash;
  10636. }
  10637. // Finish the last segment and calculate the new offset
  10638. (idx % 2 !== 0) && ctx.lineTo(x3, y3);
  10639. dx = x3 - x;
  10640. dy = y3 - y;
  10641. this._dashOffset = -mathSqrt(dx * dx + dy * dy);
  10642. },
  10643. _dashedQuadraticTo: function (x1, y1, x2, y2) {
  10644. // Convert quadratic to cubic using degree elevation
  10645. var x3 = x2;
  10646. var y3 = y2;
  10647. x2 = (x2 + 2 * x1) / 3;
  10648. y2 = (y2 + 2 * y1) / 3;
  10649. x1 = (this._xi + 2 * x1) / 3;
  10650. y1 = (this._yi + 2 * y1) / 3;
  10651. this._dashedBezierTo(x1, y1, x2, y2, x3, y3);
  10652. },
  10653. /**
  10654. * 转成静态的 Float32Array 减少堆内存占用
  10655. * Convert dynamic array to static Float32Array
  10656. */
  10657. toStatic: function () {
  10658. var data = this.data;
  10659. if (data instanceof Array) {
  10660. data.length = this._len;
  10661. if (hasTypedArray) {
  10662. this.data = new Float32Array(data);
  10663. }
  10664. }
  10665. },
  10666. /**
  10667. * @return {module:zrender/core/BoundingRect}
  10668. */
  10669. getBoundingRect: function () {
  10670. min[0] = min[1] = min2[0] = min2[1] = Number.MAX_VALUE;
  10671. max[0] = max[1] = max2[0] = max2[1] = -Number.MAX_VALUE;
  10672. var data = this.data;
  10673. var xi = 0;
  10674. var yi = 0;
  10675. var x0 = 0;
  10676. var y0 = 0;
  10677. for (var i = 0; i < data.length;) {
  10678. var cmd = data[i++];
  10679. if (i == 1) {
  10680. // 如果第一个命令是 L, C, Q
  10681. // 则 previous point 同绘制命令的第一个 point
  10682. //
  10683. // 第一个命令为 Arc 的情况下会在后面特殊处理
  10684. xi = data[i];
  10685. yi = data[i + 1];
  10686. x0 = xi;
  10687. y0 = yi;
  10688. }
  10689. switch (cmd) {
  10690. case CMD.M:
  10691. // moveTo 命令重新创建一个新的 subpath, 并且更新新的起点
  10692. // 在 closePath 的时候使用
  10693. x0 = data[i++];
  10694. y0 = data[i++];
  10695. xi = x0;
  10696. yi = y0;
  10697. min2[0] = x0;
  10698. min2[1] = y0;
  10699. max2[0] = x0;
  10700. max2[1] = y0;
  10701. break;
  10702. case CMD.L:
  10703. bbox.fromLine(xi, yi, data[i], data[i + 1], min2, max2);
  10704. xi = data[i++];
  10705. yi = data[i++];
  10706. break;
  10707. case CMD.C:
  10708. bbox.fromCubic(
  10709. xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1],
  10710. min2, max2
  10711. );
  10712. xi = data[i++];
  10713. yi = data[i++];
  10714. break;
  10715. case CMD.Q:
  10716. bbox.fromQuadratic(
  10717. xi, yi, data[i++], data[i++], data[i], data[i + 1],
  10718. min2, max2
  10719. );
  10720. xi = data[i++];
  10721. yi = data[i++];
  10722. break;
  10723. case CMD.A:
  10724. // TODO Arc 判断的开销比较大
  10725. var cx = data[i++];
  10726. var cy = data[i++];
  10727. var rx = data[i++];
  10728. var ry = data[i++];
  10729. var startAngle = data[i++];
  10730. var endAngle = data[i++] + startAngle;
  10731. // TODO Arc 旋转
  10732. var psi = data[i++];
  10733. var anticlockwise = 1 - data[i++];
  10734. if (i == 1) {
  10735. // 直接使用 arc 命令
  10736. // 第一个命令起点还未定义
  10737. x0 = mathCos(startAngle) * rx + cx;
  10738. y0 = mathSin(startAngle) * ry + cy;
  10739. }
  10740. bbox.fromArc(
  10741. cx, cy, rx, ry, startAngle, endAngle,
  10742. anticlockwise, min2, max2
  10743. );
  10744. xi = mathCos(endAngle) * rx + cx;
  10745. yi = mathSin(endAngle) * ry + cy;
  10746. break;
  10747. case CMD.R:
  10748. x0 = xi = data[i++];
  10749. y0 = yi = data[i++];
  10750. var width = data[i++];
  10751. var height = data[i++];
  10752. // Use fromLine
  10753. bbox.fromLine(x0, y0, x0 + width, y0 + height, min2, max2);
  10754. break;
  10755. case CMD.Z:
  10756. xi = x0;
  10757. yi = y0;
  10758. break;
  10759. }
  10760. // Union
  10761. vec2.min(min, min, min2);
  10762. vec2.max(max, max, max2);
  10763. }
  10764. // No data
  10765. if (i === 0) {
  10766. min[0] = min[1] = max[0] = max[1] = 0;
  10767. }
  10768. return new BoundingRect(
  10769. min[0], min[1], max[0] - min[0], max[1] - min[1]
  10770. );
  10771. },
  10772. /**
  10773. * Rebuild path from current data
  10774. * Rebuild path will not consider javascript implemented line dash.
  10775. * @param {CanvasRenderingContext} ctx
  10776. */
  10777. rebuildPath: function (ctx) {
  10778. var d = this.data;
  10779. var x0, y0;
  10780. var xi, yi;
  10781. var x, y;
  10782. var ux = this._ux;
  10783. var uy = this._uy;
  10784. var len = this._len;
  10785. for (var i = 0; i < len;) {
  10786. var cmd = d[i++];
  10787. if (i == 1) {
  10788. // 如果第一个命令是 L, C, Q
  10789. // 则 previous point 同绘制命令的第一个 point
  10790. //
  10791. // 第一个命令为 Arc 的情况下会在后面特殊处理
  10792. xi = d[i];
  10793. yi = d[i + 1];
  10794. x0 = xi;
  10795. y0 = yi;
  10796. }
  10797. switch (cmd) {
  10798. case CMD.M:
  10799. x0 = xi = d[i++];
  10800. y0 = yi = d[i++];
  10801. ctx.moveTo(xi, yi);
  10802. break;
  10803. case CMD.L:
  10804. x = d[i++];
  10805. y = d[i++];
  10806. // Not draw too small seg between
  10807. if (mathAbs(x - xi) > ux || mathAbs(y - yi) > uy || i === len - 1) {
  10808. ctx.lineTo(x, y);
  10809. xi = x;
  10810. yi = y;
  10811. }
  10812. break;
  10813. case CMD.C:
  10814. ctx.bezierCurveTo(
  10815. d[i++], d[i++], d[i++], d[i++], d[i++], d[i++]
  10816. );
  10817. xi = d[i - 2];
  10818. yi = d[i - 1];
  10819. break;
  10820. case CMD.Q:
  10821. ctx.quadraticCurveTo(d[i++], d[i++], d[i++], d[i++]);
  10822. xi = d[i - 2];
  10823. yi = d[i - 1];
  10824. break;
  10825. case CMD.A:
  10826. var cx = d[i++];
  10827. var cy = d[i++];
  10828. var rx = d[i++];
  10829. var ry = d[i++];
  10830. var theta = d[i++];
  10831. var dTheta = d[i++];
  10832. var psi = d[i++];
  10833. var fs = d[i++];
  10834. var r = (rx > ry) ? rx : ry;
  10835. var scaleX = (rx > ry) ? 1 : rx / ry;
  10836. var scaleY = (rx > ry) ? ry / rx : 1;
  10837. var isEllipse = Math.abs(rx - ry) > 1e-3;
  10838. var endAngle = theta + dTheta;
  10839. if (isEllipse) {
  10840. ctx.translate(cx, cy);
  10841. ctx.rotate(psi);
  10842. ctx.scale(scaleX, scaleY);
  10843. ctx.arc(0, 0, r, theta, endAngle, 1 - fs);
  10844. ctx.scale(1 / scaleX, 1 / scaleY);
  10845. ctx.rotate(-psi);
  10846. ctx.translate(-cx, -cy);
  10847. }
  10848. else {
  10849. ctx.arc(cx, cy, r, theta, endAngle, 1 - fs);
  10850. }
  10851. if (i == 1) {
  10852. // 直接使用 arc 命令
  10853. // 第一个命令起点还未定义
  10854. x0 = mathCos(theta) * rx + cx;
  10855. y0 = mathSin(theta) * ry + cy;
  10856. }
  10857. xi = mathCos(endAngle) * rx + cx;
  10858. yi = mathSin(endAngle) * ry + cy;
  10859. break;
  10860. case CMD.R:
  10861. x0 = xi = d[i];
  10862. y0 = yi = d[i + 1];
  10863. ctx.rect(d[i++], d[i++], d[i++], d[i++]);
  10864. break;
  10865. case CMD.Z:
  10866. ctx.closePath();
  10867. xi = x0;
  10868. yi = y0;
  10869. }
  10870. }
  10871. }
  10872. };
  10873. PathProxy.CMD = CMD;
  10874. module.exports = PathProxy;
  10875. /***/ },
  10876. /* 37 */
  10877. /***/ function(module, exports, __webpack_require__) {
  10878. 'use strict';
  10879. /**
  10880. * 曲线辅助模块
  10881. * @module zrender/core/curve
  10882. * @author pissang(https://www.github.com/pissang)
  10883. */
  10884. var vec2 = __webpack_require__(10);
  10885. var v2Create = vec2.create;
  10886. var v2DistSquare = vec2.distSquare;
  10887. var mathPow = Math.pow;
  10888. var mathSqrt = Math.sqrt;
  10889. var EPSILON = 1e-8;
  10890. var EPSILON_NUMERIC = 1e-4;
  10891. var THREE_SQRT = mathSqrt(3);
  10892. var ONE_THIRD = 1 / 3;
  10893. // 临时变量
  10894. var _v0 = v2Create();
  10895. var _v1 = v2Create();
  10896. var _v2 = v2Create();
  10897. // var _v3 = vec2.create();
  10898. function isAroundZero(val) {
  10899. return val > -EPSILON && val < EPSILON;
  10900. }
  10901. function isNotAroundZero(val) {
  10902. return val > EPSILON || val < -EPSILON;
  10903. }
  10904. /**
  10905. * 计算三次贝塞尔值
  10906. * @memberOf module:zrender/core/curve
  10907. * @param {number} p0
  10908. * @param {number} p1
  10909. * @param {number} p2
  10910. * @param {number} p3
  10911. * @param {number} t
  10912. * @return {number}
  10913. */
  10914. function cubicAt(p0, p1, p2, p3, t) {
  10915. var onet = 1 - t;
  10916. return onet * onet * (onet * p0 + 3 * t * p1)
  10917. + t * t * (t * p3 + 3 * onet * p2);
  10918. }
  10919. /**
  10920. * 计算三次贝塞尔导数值
  10921. * @memberOf module:zrender/core/curve
  10922. * @param {number} p0
  10923. * @param {number} p1
  10924. * @param {number} p2
  10925. * @param {number} p3
  10926. * @param {number} t
  10927. * @return {number}
  10928. */
  10929. function cubicDerivativeAt(p0, p1, p2, p3, t) {
  10930. var onet = 1 - t;
  10931. return 3 * (
  10932. ((p1 - p0) * onet + 2 * (p2 - p1) * t) * onet
  10933. + (p3 - p2) * t * t
  10934. );
  10935. }
  10936. /**
  10937. * 计算三次贝塞尔方程根,使用盛金公式
  10938. * @memberOf module:zrender/core/curve
  10939. * @param {number} p0
  10940. * @param {number} p1
  10941. * @param {number} p2
  10942. * @param {number} p3
  10943. * @param {number} val
  10944. * @param {Array.<number>} roots
  10945. * @return {number} 有效根数目
  10946. */
  10947. function cubicRootAt(p0, p1, p2, p3, val, roots) {
  10948. // Evaluate roots of cubic functions
  10949. var a = p3 + 3 * (p1 - p2) - p0;
  10950. var b = 3 * (p2 - p1 * 2 + p0);
  10951. var c = 3 * (p1 - p0);
  10952. var d = p0 - val;
  10953. var A = b * b - 3 * a * c;
  10954. var B = b * c - 9 * a * d;
  10955. var C = c * c - 3 * b * d;
  10956. var n = 0;
  10957. if (isAroundZero(A) && isAroundZero(B)) {
  10958. if (isAroundZero(b)) {
  10959. roots[0] = 0;
  10960. }
  10961. else {
  10962. var t1 = -c / b; //t1, t2, t3, b is not zero
  10963. if (t1 >= 0 && t1 <= 1) {
  10964. roots[n++] = t1;
  10965. }
  10966. }
  10967. }
  10968. else {
  10969. var disc = B * B - 4 * A * C;
  10970. if (isAroundZero(disc)) {
  10971. var K = B / A;
  10972. var t1 = -b / a + K; // t1, a is not zero
  10973. var t2 = -K / 2; // t2, t3
  10974. if (t1 >= 0 && t1 <= 1) {
  10975. roots[n++] = t1;
  10976. }
  10977. if (t2 >= 0 && t2 <= 1) {
  10978. roots[n++] = t2;
  10979. }
  10980. }
  10981. else if (disc > 0) {
  10982. var discSqrt = mathSqrt(disc);
  10983. var Y1 = A * b + 1.5 * a * (-B + discSqrt);
  10984. var Y2 = A * b + 1.5 * a * (-B - discSqrt);
  10985. if (Y1 < 0) {
  10986. Y1 = -mathPow(-Y1, ONE_THIRD);
  10987. }
  10988. else {
  10989. Y1 = mathPow(Y1, ONE_THIRD);
  10990. }
  10991. if (Y2 < 0) {
  10992. Y2 = -mathPow(-Y2, ONE_THIRD);
  10993. }
  10994. else {
  10995. Y2 = mathPow(Y2, ONE_THIRD);
  10996. }
  10997. var t1 = (-b - (Y1 + Y2)) / (3 * a);
  10998. if (t1 >= 0 && t1 <= 1) {
  10999. roots[n++] = t1;
  11000. }
  11001. }
  11002. else {
  11003. var T = (2 * A * b - 3 * a * B) / (2 * mathSqrt(A * A * A));
  11004. var theta = Math.acos(T) / 3;
  11005. var ASqrt = mathSqrt(A);
  11006. var tmp = Math.cos(theta);
  11007. var t1 = (-b - 2 * ASqrt * tmp) / (3 * a);
  11008. var t2 = (-b + ASqrt * (tmp + THREE_SQRT * Math.sin(theta))) / (3 * a);
  11009. var t3 = (-b + ASqrt * (tmp - THREE_SQRT * Math.sin(theta))) / (3 * a);
  11010. if (t1 >= 0 && t1 <= 1) {
  11011. roots[n++] = t1;
  11012. }
  11013. if (t2 >= 0 && t2 <= 1) {
  11014. roots[n++] = t2;
  11015. }
  11016. if (t3 >= 0 && t3 <= 1) {
  11017. roots[n++] = t3;
  11018. }
  11019. }
  11020. }
  11021. return n;
  11022. }
  11023. /**
  11024. * 计算三次贝塞尔方程极限值的位置
  11025. * @memberOf module:zrender/core/curve
  11026. * @param {number} p0
  11027. * @param {number} p1
  11028. * @param {number} p2
  11029. * @param {number} p3
  11030. * @param {Array.<number>} extrema
  11031. * @return {number} 有效数目
  11032. */
  11033. function cubicExtrema(p0, p1, p2, p3, extrema) {
  11034. var b = 6 * p2 - 12 * p1 + 6 * p0;
  11035. var a = 9 * p1 + 3 * p3 - 3 * p0 - 9 * p2;
  11036. var c = 3 * p1 - 3 * p0;
  11037. var n = 0;
  11038. if (isAroundZero(a)) {
  11039. if (isNotAroundZero(b)) {
  11040. var t1 = -c / b;
  11041. if (t1 >= 0 && t1 <=1) {
  11042. extrema[n++] = t1;
  11043. }
  11044. }
  11045. }
  11046. else {
  11047. var disc = b * b - 4 * a * c;
  11048. if (isAroundZero(disc)) {
  11049. extrema[0] = -b / (2 * a);
  11050. }
  11051. else if (disc > 0) {
  11052. var discSqrt = mathSqrt(disc);
  11053. var t1 = (-b + discSqrt) / (2 * a);
  11054. var t2 = (-b - discSqrt) / (2 * a);
  11055. if (t1 >= 0 && t1 <= 1) {
  11056. extrema[n++] = t1;
  11057. }
  11058. if (t2 >= 0 && t2 <= 1) {
  11059. extrema[n++] = t2;
  11060. }
  11061. }
  11062. }
  11063. return n;
  11064. }
  11065. /**
  11066. * 细分三次贝塞尔曲线
  11067. * @memberOf module:zrender/core/curve
  11068. * @param {number} p0
  11069. * @param {number} p1
  11070. * @param {number} p2
  11071. * @param {number} p3
  11072. * @param {number} t
  11073. * @param {Array.<number>} out
  11074. */
  11075. function cubicSubdivide(p0, p1, p2, p3, t, out) {
  11076. var p01 = (p1 - p0) * t + p0;
  11077. var p12 = (p2 - p1) * t + p1;
  11078. var p23 = (p3 - p2) * t + p2;
  11079. var p012 = (p12 - p01) * t + p01;
  11080. var p123 = (p23 - p12) * t + p12;
  11081. var p0123 = (p123 - p012) * t + p012;
  11082. // Seg0
  11083. out[0] = p0;
  11084. out[1] = p01;
  11085. out[2] = p012;
  11086. out[3] = p0123;
  11087. // Seg1
  11088. out[4] = p0123;
  11089. out[5] = p123;
  11090. out[6] = p23;
  11091. out[7] = p3;
  11092. }
  11093. /**
  11094. * 投射点到三次贝塞尔曲线上,返回投射距离。
  11095. * 投射点有可能会有一个或者多个,这里只返回其中距离最短的一个。
  11096. * @param {number} x0
  11097. * @param {number} y0
  11098. * @param {number} x1
  11099. * @param {number} y1
  11100. * @param {number} x2
  11101. * @param {number} y2
  11102. * @param {number} x3
  11103. * @param {number} y3
  11104. * @param {number} x
  11105. * @param {number} y
  11106. * @param {Array.<number>} [out] 投射点
  11107. * @return {number}
  11108. */
  11109. function cubicProjectPoint(
  11110. x0, y0, x1, y1, x2, y2, x3, y3,
  11111. x, y, out
  11112. ) {
  11113. // http://pomax.github.io/bezierinfo/#projections
  11114. var t;
  11115. var interval = 0.005;
  11116. var d = Infinity;
  11117. var prev;
  11118. var next;
  11119. var d1;
  11120. var d2;
  11121. _v0[0] = x;
  11122. _v0[1] = y;
  11123. // 先粗略估计一下可能的最小距离的 t 值
  11124. // PENDING
  11125. for (var _t = 0; _t < 1; _t += 0.05) {
  11126. _v1[0] = cubicAt(x0, x1, x2, x3, _t);
  11127. _v1[1] = cubicAt(y0, y1, y2, y3, _t);
  11128. d1 = v2DistSquare(_v0, _v1);
  11129. if (d1 < d) {
  11130. t = _t;
  11131. d = d1;
  11132. }
  11133. }
  11134. d = Infinity;
  11135. // At most 32 iteration
  11136. for (var i = 0; i < 32; i++) {
  11137. if (interval < EPSILON_NUMERIC) {
  11138. break;
  11139. }
  11140. prev = t - interval;
  11141. next = t + interval;
  11142. // t - interval
  11143. _v1[0] = cubicAt(x0, x1, x2, x3, prev);
  11144. _v1[1] = cubicAt(y0, y1, y2, y3, prev);
  11145. d1 = v2DistSquare(_v1, _v0);
  11146. if (prev >= 0 && d1 < d) {
  11147. t = prev;
  11148. d = d1;
  11149. }
  11150. else {
  11151. // t + interval
  11152. _v2[0] = cubicAt(x0, x1, x2, x3, next);
  11153. _v2[1] = cubicAt(y0, y1, y2, y3, next);
  11154. d2 = v2DistSquare(_v2, _v0);
  11155. if (next <= 1 && d2 < d) {
  11156. t = next;
  11157. d = d2;
  11158. }
  11159. else {
  11160. interval *= 0.5;
  11161. }
  11162. }
  11163. }
  11164. // t
  11165. if (out) {
  11166. out[0] = cubicAt(x0, x1, x2, x3, t);
  11167. out[1] = cubicAt(y0, y1, y2, y3, t);
  11168. }
  11169. // console.log(interval, i);
  11170. return mathSqrt(d);
  11171. }
  11172. /**
  11173. * 计算二次方贝塞尔值
  11174. * @param {number} p0
  11175. * @param {number} p1
  11176. * @param {number} p2
  11177. * @param {number} t
  11178. * @return {number}
  11179. */
  11180. function quadraticAt(p0, p1, p2, t) {
  11181. var onet = 1 - t;
  11182. return onet * (onet * p0 + 2 * t * p1) + t * t * p2;
  11183. }
  11184. /**
  11185. * 计算二次方贝塞尔导数值
  11186. * @param {number} p0
  11187. * @param {number} p1
  11188. * @param {number} p2
  11189. * @param {number} t
  11190. * @return {number}
  11191. */
  11192. function quadraticDerivativeAt(p0, p1, p2, t) {
  11193. return 2 * ((1 - t) * (p1 - p0) + t * (p2 - p1));
  11194. }
  11195. /**
  11196. * 计算二次方贝塞尔方程根
  11197. * @param {number} p0
  11198. * @param {number} p1
  11199. * @param {number} p2
  11200. * @param {number} t
  11201. * @param {Array.<number>} roots
  11202. * @return {number} 有效根数目
  11203. */
  11204. function quadraticRootAt(p0, p1, p2, val, roots) {
  11205. var a = p0 - 2 * p1 + p2;
  11206. var b = 2 * (p1 - p0);
  11207. var c = p0 - val;
  11208. var n = 0;
  11209. if (isAroundZero(a)) {
  11210. if (isNotAroundZero(b)) {
  11211. var t1 = -c / b;
  11212. if (t1 >= 0 && t1 <= 1) {
  11213. roots[n++] = t1;
  11214. }
  11215. }
  11216. }
  11217. else {
  11218. var disc = b * b - 4 * a * c;
  11219. if (isAroundZero(disc)) {
  11220. var t1 = -b / (2 * a);
  11221. if (t1 >= 0 && t1 <= 1) {
  11222. roots[n++] = t1;
  11223. }
  11224. }
  11225. else if (disc > 0) {
  11226. var discSqrt = mathSqrt(disc);
  11227. var t1 = (-b + discSqrt) / (2 * a);
  11228. var t2 = (-b - discSqrt) / (2 * a);
  11229. if (t1 >= 0 && t1 <= 1) {
  11230. roots[n++] = t1;
  11231. }
  11232. if (t2 >= 0 && t2 <= 1) {
  11233. roots[n++] = t2;
  11234. }
  11235. }
  11236. }
  11237. return n;
  11238. }
  11239. /**
  11240. * 计算二次贝塞尔方程极限值
  11241. * @memberOf module:zrender/core/curve
  11242. * @param {number} p0
  11243. * @param {number} p1
  11244. * @param {number} p2
  11245. * @return {number}
  11246. */
  11247. function quadraticExtremum(p0, p1, p2) {
  11248. var divider = p0 + p2 - 2 * p1;
  11249. if (divider === 0) {
  11250. // p1 is center of p0 and p2
  11251. return 0.5;
  11252. }
  11253. else {
  11254. return (p0 - p1) / divider;
  11255. }
  11256. }
  11257. /**
  11258. * 细分二次贝塞尔曲线
  11259. * @memberOf module:zrender/core/curve
  11260. * @param {number} p0
  11261. * @param {number} p1
  11262. * @param {number} p2
  11263. * @param {number} t
  11264. * @param {Array.<number>} out
  11265. */
  11266. function quadraticSubdivide(p0, p1, p2, t, out) {
  11267. var p01 = (p1 - p0) * t + p0;
  11268. var p12 = (p2 - p1) * t + p1;
  11269. var p012 = (p12 - p01) * t + p01;
  11270. // Seg0
  11271. out[0] = p0;
  11272. out[1] = p01;
  11273. out[2] = p012;
  11274. // Seg1
  11275. out[3] = p012;
  11276. out[4] = p12;
  11277. out[5] = p2;
  11278. }
  11279. /**
  11280. * 投射点到二次贝塞尔曲线上,返回投射距离。
  11281. * 投射点有可能会有一个或者多个,这里只返回其中距离最短的一个。
  11282. * @param {number} x0
  11283. * @param {number} y0
  11284. * @param {number} x1
  11285. * @param {number} y1
  11286. * @param {number} x2
  11287. * @param {number} y2
  11288. * @param {number} x
  11289. * @param {number} y
  11290. * @param {Array.<number>} out 投射点
  11291. * @return {number}
  11292. */
  11293. function quadraticProjectPoint(
  11294. x0, y0, x1, y1, x2, y2,
  11295. x, y, out
  11296. ) {
  11297. // http://pomax.github.io/bezierinfo/#projections
  11298. var t;
  11299. var interval = 0.005;
  11300. var d = Infinity;
  11301. _v0[0] = x;
  11302. _v0[1] = y;
  11303. // 先粗略估计一下可能的最小距离的 t 值
  11304. // PENDING
  11305. for (var _t = 0; _t < 1; _t += 0.05) {
  11306. _v1[0] = quadraticAt(x0, x1, x2, _t);
  11307. _v1[1] = quadraticAt(y0, y1, y2, _t);
  11308. var d1 = v2DistSquare(_v0, _v1);
  11309. if (d1 < d) {
  11310. t = _t;
  11311. d = d1;
  11312. }
  11313. }
  11314. d = Infinity;
  11315. // At most 32 iteration
  11316. for (var i = 0; i < 32; i++) {
  11317. if (interval < EPSILON_NUMERIC) {
  11318. break;
  11319. }
  11320. var prev = t - interval;
  11321. var next = t + interval;
  11322. // t - interval
  11323. _v1[0] = quadraticAt(x0, x1, x2, prev);
  11324. _v1[1] = quadraticAt(y0, y1, y2, prev);
  11325. var d1 = v2DistSquare(_v1, _v0);
  11326. if (prev >= 0 && d1 < d) {
  11327. t = prev;
  11328. d = d1;
  11329. }
  11330. else {
  11331. // t + interval
  11332. _v2[0] = quadraticAt(x0, x1, x2, next);
  11333. _v2[1] = quadraticAt(y0, y1, y2, next);
  11334. var d2 = v2DistSquare(_v2, _v0);
  11335. if (next <= 1 && d2 < d) {
  11336. t = next;
  11337. d = d2;
  11338. }
  11339. else {
  11340. interval *= 0.5;
  11341. }
  11342. }
  11343. }
  11344. // t
  11345. if (out) {
  11346. out[0] = quadraticAt(x0, x1, x2, t);
  11347. out[1] = quadraticAt(y0, y1, y2, t);
  11348. }
  11349. // console.log(interval, i);
  11350. return mathSqrt(d);
  11351. }
  11352. module.exports = {
  11353. cubicAt: cubicAt,
  11354. cubicDerivativeAt: cubicDerivativeAt,
  11355. cubicRootAt: cubicRootAt,
  11356. cubicExtrema: cubicExtrema,
  11357. cubicSubdivide: cubicSubdivide,
  11358. cubicProjectPoint: cubicProjectPoint,
  11359. quadraticAt: quadraticAt,
  11360. quadraticDerivativeAt: quadraticDerivativeAt,
  11361. quadraticRootAt: quadraticRootAt,
  11362. quadraticExtremum: quadraticExtremum,
  11363. quadraticSubdivide: quadraticSubdivide,
  11364. quadraticProjectPoint: quadraticProjectPoint
  11365. };
  11366. /***/ },
  11367. /* 38 */
  11368. /***/ function(module, exports, __webpack_require__) {
  11369. /**
  11370. * @author Yi Shen(https://github.com/pissang)
  11371. */
  11372. var vec2 = __webpack_require__(10);
  11373. var curve = __webpack_require__(37);
  11374. var bbox = {};
  11375. var mathMin = Math.min;
  11376. var mathMax = Math.max;
  11377. var mathSin = Math.sin;
  11378. var mathCos = Math.cos;
  11379. var start = vec2.create();
  11380. var end = vec2.create();
  11381. var extremity = vec2.create();
  11382. var PI2 = Math.PI * 2;
  11383. /**
  11384. * 从顶点数组中计算出最小包围盒,写入`min`和`max`中
  11385. * @module zrender/core/bbox
  11386. * @param {Array<Object>} points 顶点数组
  11387. * @param {number} min
  11388. * @param {number} max
  11389. */
  11390. bbox.fromPoints = function(points, min, max) {
  11391. if (points.length === 0) {
  11392. return;
  11393. }
  11394. var p = points[0];
  11395. var left = p[0];
  11396. var right = p[0];
  11397. var top = p[1];
  11398. var bottom = p[1];
  11399. var i;
  11400. for (i = 1; i < points.length; i++) {
  11401. p = points[i];
  11402. left = mathMin(left, p[0]);
  11403. right = mathMax(right, p[0]);
  11404. top = mathMin(top, p[1]);
  11405. bottom = mathMax(bottom, p[1]);
  11406. }
  11407. min[0] = left;
  11408. min[1] = top;
  11409. max[0] = right;
  11410. max[1] = bottom;
  11411. };
  11412. /**
  11413. * @memberOf module:zrender/core/bbox
  11414. * @param {number} x0
  11415. * @param {number} y0
  11416. * @param {number} x1
  11417. * @param {number} y1
  11418. * @param {Array.<number>} min
  11419. * @param {Array.<number>} max
  11420. */
  11421. bbox.fromLine = function (x0, y0, x1, y1, min, max) {
  11422. min[0] = mathMin(x0, x1);
  11423. min[1] = mathMin(y0, y1);
  11424. max[0] = mathMax(x0, x1);
  11425. max[1] = mathMax(y0, y1);
  11426. };
  11427. var xDim = [];
  11428. var yDim = [];
  11429. /**
  11430. * 从三阶贝塞尔曲线(p0, p1, p2, p3)中计算出最小包围盒,写入`min`和`max`中
  11431. * @memberOf module:zrender/core/bbox
  11432. * @param {number} x0
  11433. * @param {number} y0
  11434. * @param {number} x1
  11435. * @param {number} y1
  11436. * @param {number} x2
  11437. * @param {number} y2
  11438. * @param {number} x3
  11439. * @param {number} y3
  11440. * @param {Array.<number>} min
  11441. * @param {Array.<number>} max
  11442. */
  11443. bbox.fromCubic = function(
  11444. x0, y0, x1, y1, x2, y2, x3, y3, min, max
  11445. ) {
  11446. var cubicExtrema = curve.cubicExtrema;
  11447. var cubicAt = curve.cubicAt;
  11448. var i;
  11449. var n = cubicExtrema(x0, x1, x2, x3, xDim);
  11450. min[0] = Infinity;
  11451. min[1] = Infinity;
  11452. max[0] = -Infinity;
  11453. max[1] = -Infinity;
  11454. for (i = 0; i < n; i++) {
  11455. var x = cubicAt(x0, x1, x2, x3, xDim[i]);
  11456. min[0] = mathMin(x, min[0]);
  11457. max[0] = mathMax(x, max[0]);
  11458. }
  11459. n = cubicExtrema(y0, y1, y2, y3, yDim);
  11460. for (i = 0; i < n; i++) {
  11461. var y = cubicAt(y0, y1, y2, y3, yDim[i]);
  11462. min[1] = mathMin(y, min[1]);
  11463. max[1] = mathMax(y, max[1]);
  11464. }
  11465. min[0] = mathMin(x0, min[0]);
  11466. max[0] = mathMax(x0, max[0]);
  11467. min[0] = mathMin(x3, min[0]);
  11468. max[0] = mathMax(x3, max[0]);
  11469. min[1] = mathMin(y0, min[1]);
  11470. max[1] = mathMax(y0, max[1]);
  11471. min[1] = mathMin(y3, min[1]);
  11472. max[1] = mathMax(y3, max[1]);
  11473. };
  11474. /**
  11475. * 从二阶贝塞尔曲线(p0, p1, p2)中计算出最小包围盒,写入`min`和`max`中
  11476. * @memberOf module:zrender/core/bbox
  11477. * @param {number} x0
  11478. * @param {number} y0
  11479. * @param {number} x1
  11480. * @param {number} y1
  11481. * @param {number} x2
  11482. * @param {number} y2
  11483. * @param {Array.<number>} min
  11484. * @param {Array.<number>} max
  11485. */
  11486. bbox.fromQuadratic = function(x0, y0, x1, y1, x2, y2, min, max) {
  11487. var quadraticExtremum = curve.quadraticExtremum;
  11488. var quadraticAt = curve.quadraticAt;
  11489. // Find extremities, where derivative in x dim or y dim is zero
  11490. var tx =
  11491. mathMax(
  11492. mathMin(quadraticExtremum(x0, x1, x2), 1), 0
  11493. );
  11494. var ty =
  11495. mathMax(
  11496. mathMin(quadraticExtremum(y0, y1, y2), 1), 0
  11497. );
  11498. var x = quadraticAt(x0, x1, x2, tx);
  11499. var y = quadraticAt(y0, y1, y2, ty);
  11500. min[0] = mathMin(x0, x2, x);
  11501. min[1] = mathMin(y0, y2, y);
  11502. max[0] = mathMax(x0, x2, x);
  11503. max[1] = mathMax(y0, y2, y);
  11504. };
  11505. /**
  11506. * 从圆弧中计算出最小包围盒,写入`min`和`max`中
  11507. * @method
  11508. * @memberOf module:zrender/core/bbox
  11509. * @param {number} x
  11510. * @param {number} y
  11511. * @param {number} rx
  11512. * @param {number} ry
  11513. * @param {number} startAngle
  11514. * @param {number} endAngle
  11515. * @param {number} anticlockwise
  11516. * @param {Array.<number>} min
  11517. * @param {Array.<number>} max
  11518. */
  11519. bbox.fromArc = function (
  11520. x, y, rx, ry, startAngle, endAngle, anticlockwise, min, max
  11521. ) {
  11522. var vec2Min = vec2.min;
  11523. var vec2Max = vec2.max;
  11524. var diff = Math.abs(startAngle - endAngle);
  11525. if (diff % PI2 < 1e-4 && diff > 1e-4) {
  11526. // Is a circle
  11527. min[0] = x - rx;
  11528. min[1] = y - ry;
  11529. max[0] = x + rx;
  11530. max[1] = y + ry;
  11531. return;
  11532. }
  11533. start[0] = mathCos(startAngle) * rx + x;
  11534. start[1] = mathSin(startAngle) * ry + y;
  11535. end[0] = mathCos(endAngle) * rx + x;
  11536. end[1] = mathSin(endAngle) * ry + y;
  11537. vec2Min(min, start, end);
  11538. vec2Max(max, start, end);
  11539. // Thresh to [0, Math.PI * 2]
  11540. startAngle = startAngle % (PI2);
  11541. if (startAngle < 0) {
  11542. startAngle = startAngle + PI2;
  11543. }
  11544. endAngle = endAngle % (PI2);
  11545. if (endAngle < 0) {
  11546. endAngle = endAngle + PI2;
  11547. }
  11548. if (startAngle > endAngle && !anticlockwise) {
  11549. endAngle += PI2;
  11550. }
  11551. else if (startAngle < endAngle && anticlockwise) {
  11552. startAngle += PI2;
  11553. }
  11554. if (anticlockwise) {
  11555. var tmp = endAngle;
  11556. endAngle = startAngle;
  11557. startAngle = tmp;
  11558. }
  11559. // var number = 0;
  11560. // var step = (anticlockwise ? -Math.PI : Math.PI) / 2;
  11561. for (var angle = 0; angle < endAngle; angle += Math.PI / 2) {
  11562. if (angle > startAngle) {
  11563. extremity[0] = mathCos(angle) * rx + x;
  11564. extremity[1] = mathSin(angle) * ry + y;
  11565. vec2Min(min, extremity, min);
  11566. vec2Max(max, extremity, max);
  11567. }
  11568. }
  11569. };
  11570. module.exports = bbox;
  11571. /***/ },
  11572. /* 39 */
  11573. /***/ function(module, exports, __webpack_require__) {
  11574. 'use strict';
  11575. var CMD = __webpack_require__(36).CMD;
  11576. var line = __webpack_require__(40);
  11577. var cubic = __webpack_require__(41);
  11578. var quadratic = __webpack_require__(42);
  11579. var arc = __webpack_require__(43);
  11580. var normalizeRadian = __webpack_require__(44).normalizeRadian;
  11581. var curve = __webpack_require__(37);
  11582. var windingLine = __webpack_require__(45);
  11583. var containStroke = line.containStroke;
  11584. var PI2 = Math.PI * 2;
  11585. var EPSILON = 1e-4;
  11586. function isAroundEqual(a, b) {
  11587. return Math.abs(a - b) < EPSILON;
  11588. }
  11589. // 临时数组
  11590. var roots = [-1, -1, -1];
  11591. var extrema = [-1, -1];
  11592. function swapExtrema() {
  11593. var tmp = extrema[0];
  11594. extrema[0] = extrema[1];
  11595. extrema[1] = tmp;
  11596. }
  11597. function windingCubic(x0, y0, x1, y1, x2, y2, x3, y3, x, y) {
  11598. // Quick reject
  11599. if (
  11600. (y > y0 && y > y1 && y > y2 && y > y3)
  11601. || (y < y0 && y < y1 && y < y2 && y < y3)
  11602. ) {
  11603. return 0;
  11604. }
  11605. var nRoots = curve.cubicRootAt(y0, y1, y2, y3, y, roots);
  11606. if (nRoots === 0) {
  11607. return 0;
  11608. }
  11609. else {
  11610. var w = 0;
  11611. var nExtrema = -1;
  11612. var y0_, y1_;
  11613. for (var i = 0; i < nRoots; i++) {
  11614. var t = roots[i];
  11615. // Avoid winding error when intersection point is the connect point of two line of polygon
  11616. var unit = (t === 0 || t === 1) ? 0.5 : 1;
  11617. var x_ = curve.cubicAt(x0, x1, x2, x3, t);
  11618. if (x_ < x) { // Quick reject
  11619. continue;
  11620. }
  11621. if (nExtrema < 0) {
  11622. nExtrema = curve.cubicExtrema(y0, y1, y2, y3, extrema);
  11623. if (extrema[1] < extrema[0] && nExtrema > 1) {
  11624. swapExtrema();
  11625. }
  11626. y0_ = curve.cubicAt(y0, y1, y2, y3, extrema[0]);
  11627. if (nExtrema > 1) {
  11628. y1_ = curve.cubicAt(y0, y1, y2, y3, extrema[1]);
  11629. }
  11630. }
  11631. if (nExtrema == 2) {
  11632. // 分成三段单调函数
  11633. if (t < extrema[0]) {
  11634. w += y0_ < y0 ? unit : -unit;
  11635. }
  11636. else if (t < extrema[1]) {
  11637. w += y1_ < y0_ ? unit : -unit;
  11638. }
  11639. else {
  11640. w += y3 < y1_ ? unit : -unit;
  11641. }
  11642. }
  11643. else {
  11644. // 分成两段单调函数
  11645. if (t < extrema[0]) {
  11646. w += y0_ < y0 ? unit : -unit;
  11647. }
  11648. else {
  11649. w += y3 < y0_ ? unit : -unit;
  11650. }
  11651. }
  11652. }
  11653. return w;
  11654. }
  11655. }
  11656. function windingQuadratic(x0, y0, x1, y1, x2, y2, x, y) {
  11657. // Quick reject
  11658. if (
  11659. (y > y0 && y > y1 && y > y2)
  11660. || (y < y0 && y < y1 && y < y2)
  11661. ) {
  11662. return 0;
  11663. }
  11664. var nRoots = curve.quadraticRootAt(y0, y1, y2, y, roots);
  11665. if (nRoots === 0) {
  11666. return 0;
  11667. }
  11668. else {
  11669. var t = curve.quadraticExtremum(y0, y1, y2);
  11670. if (t >= 0 && t <= 1) {
  11671. var w = 0;
  11672. var y_ = curve.quadraticAt(y0, y1, y2, t);
  11673. for (var i = 0; i < nRoots; i++) {
  11674. // Remove one endpoint.
  11675. var unit = (roots[i] === 0 || roots[i] === 1) ? 0.5 : 1;
  11676. var x_ = curve.quadraticAt(x0, x1, x2, roots[i]);
  11677. if (x_ < x) { // Quick reject
  11678. continue;
  11679. }
  11680. if (roots[i] < t) {
  11681. w += y_ < y0 ? unit : -unit;
  11682. }
  11683. else {
  11684. w += y2 < y_ ? unit : -unit;
  11685. }
  11686. }
  11687. return w;
  11688. }
  11689. else {
  11690. // Remove one endpoint.
  11691. var unit = (roots[0] === 0 || roots[0] === 1) ? 0.5 : 1;
  11692. var x_ = curve.quadraticAt(x0, x1, x2, roots[0]);
  11693. if (x_ < x) { // Quick reject
  11694. return 0;
  11695. }
  11696. return y2 < y0 ? unit : -unit;
  11697. }
  11698. }
  11699. }
  11700. // TODO
  11701. // Arc 旋转
  11702. function windingArc(
  11703. cx, cy, r, startAngle, endAngle, anticlockwise, x, y
  11704. ) {
  11705. y -= cy;
  11706. if (y > r || y < -r) {
  11707. return 0;
  11708. }
  11709. var tmp = Math.sqrt(r * r - y * y);
  11710. roots[0] = -tmp;
  11711. roots[1] = tmp;
  11712. var diff = Math.abs(startAngle - endAngle);
  11713. if (diff < 1e-4) {
  11714. return 0;
  11715. }
  11716. if (diff % PI2 < 1e-4) {
  11717. // Is a circle
  11718. startAngle = 0;
  11719. endAngle = PI2;
  11720. var dir = anticlockwise ? 1 : -1;
  11721. if (x >= roots[0] + cx && x <= roots[1] + cx) {
  11722. return dir;
  11723. } else {
  11724. return 0;
  11725. }
  11726. }
  11727. if (anticlockwise) {
  11728. var tmp = startAngle;
  11729. startAngle = normalizeRadian(endAngle);
  11730. endAngle = normalizeRadian(tmp);
  11731. }
  11732. else {
  11733. startAngle = normalizeRadian(startAngle);
  11734. endAngle = normalizeRadian(endAngle);
  11735. }
  11736. if (startAngle > endAngle) {
  11737. endAngle += PI2;
  11738. }
  11739. var w = 0;
  11740. for (var i = 0; i < 2; i++) {
  11741. var x_ = roots[i];
  11742. if (x_ + cx > x) {
  11743. var angle = Math.atan2(y, x_);
  11744. var dir = anticlockwise ? 1 : -1;
  11745. if (angle < 0) {
  11746. angle = PI2 + angle;
  11747. }
  11748. if (
  11749. (angle >= startAngle && angle <= endAngle)
  11750. || (angle + PI2 >= startAngle && angle + PI2 <= endAngle)
  11751. ) {
  11752. if (angle > Math.PI / 2 && angle < Math.PI * 1.5) {
  11753. dir = -dir;
  11754. }
  11755. w += dir;
  11756. }
  11757. }
  11758. }
  11759. return w;
  11760. }
  11761. function containPath(data, lineWidth, isStroke, x, y) {
  11762. var w = 0;
  11763. var xi = 0;
  11764. var yi = 0;
  11765. var x0 = 0;
  11766. var y0 = 0;
  11767. for (var i = 0; i < data.length;) {
  11768. var cmd = data[i++];
  11769. // Begin a new subpath
  11770. if (cmd === CMD.M && i > 1) {
  11771. // Close previous subpath
  11772. if (!isStroke) {
  11773. w += windingLine(xi, yi, x0, y0, x, y);
  11774. }
  11775. // 如果被任何一个 subpath 包含
  11776. // if (w !== 0) {
  11777. // return true;
  11778. // }
  11779. }
  11780. if (i == 1) {
  11781. // 如果第一个命令是 L, C, Q
  11782. // 则 previous point 同绘制命令的第一个 point
  11783. //
  11784. // 第一个命令为 Arc 的情况下会在后面特殊处理
  11785. xi = data[i];
  11786. yi = data[i + 1];
  11787. x0 = xi;
  11788. y0 = yi;
  11789. }
  11790. switch (cmd) {
  11791. case CMD.M:
  11792. // moveTo 命令重新创建一个新的 subpath, 并且更新新的起点
  11793. // 在 closePath 的时候使用
  11794. x0 = data[i++];
  11795. y0 = data[i++];
  11796. xi = x0;
  11797. yi = y0;
  11798. break;
  11799. case CMD.L:
  11800. if (isStroke) {
  11801. if (containStroke(xi, yi, data[i], data[i + 1], lineWidth, x, y)) {
  11802. return true;
  11803. }
  11804. }
  11805. else {
  11806. // NOTE 在第一个命令为 L, C, Q 的时候会计算出 NaN
  11807. w += windingLine(xi, yi, data[i], data[i + 1], x, y) || 0;
  11808. }
  11809. xi = data[i++];
  11810. yi = data[i++];
  11811. break;
  11812. case CMD.C:
  11813. if (isStroke) {
  11814. if (cubic.containStroke(xi, yi,
  11815. data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1],
  11816. lineWidth, x, y
  11817. )) {
  11818. return true;
  11819. }
  11820. }
  11821. else {
  11822. w += windingCubic(
  11823. xi, yi,
  11824. data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1],
  11825. x, y
  11826. ) || 0;
  11827. }
  11828. xi = data[i++];
  11829. yi = data[i++];
  11830. break;
  11831. case CMD.Q:
  11832. if (isStroke) {
  11833. if (quadratic.containStroke(xi, yi,
  11834. data[i++], data[i++], data[i], data[i + 1],
  11835. lineWidth, x, y
  11836. )) {
  11837. return true;
  11838. }
  11839. }
  11840. else {
  11841. w += windingQuadratic(
  11842. xi, yi,
  11843. data[i++], data[i++], data[i], data[i + 1],
  11844. x, y
  11845. ) || 0;
  11846. }
  11847. xi = data[i++];
  11848. yi = data[i++];
  11849. break;
  11850. case CMD.A:
  11851. // TODO Arc 判断的开销比较大
  11852. var cx = data[i++];
  11853. var cy = data[i++];
  11854. var rx = data[i++];
  11855. var ry = data[i++];
  11856. var theta = data[i++];
  11857. var dTheta = data[i++];
  11858. // TODO Arc 旋转
  11859. var psi = data[i++];
  11860. var anticlockwise = 1 - data[i++];
  11861. var x1 = Math.cos(theta) * rx + cx;
  11862. var y1 = Math.sin(theta) * ry + cy;
  11863. // 不是直接使用 arc 命令
  11864. if (i > 1) {
  11865. w += windingLine(xi, yi, x1, y1, x, y);
  11866. }
  11867. else {
  11868. // 第一个命令起点还未定义
  11869. x0 = x1;
  11870. y0 = y1;
  11871. }
  11872. // zr 使用scale来模拟椭圆, 这里也对x做一定的缩放
  11873. var _x = (x - cx) * ry / rx + cx;
  11874. if (isStroke) {
  11875. if (arc.containStroke(
  11876. cx, cy, ry, theta, theta + dTheta, anticlockwise,
  11877. lineWidth, _x, y
  11878. )) {
  11879. return true;
  11880. }
  11881. }
  11882. else {
  11883. w += windingArc(
  11884. cx, cy, ry, theta, theta + dTheta, anticlockwise,
  11885. _x, y
  11886. );
  11887. }
  11888. xi = Math.cos(theta + dTheta) * rx + cx;
  11889. yi = Math.sin(theta + dTheta) * ry + cy;
  11890. break;
  11891. case CMD.R:
  11892. x0 = xi = data[i++];
  11893. y0 = yi = data[i++];
  11894. var width = data[i++];
  11895. var height = data[i++];
  11896. var x1 = x0 + width;
  11897. var y1 = y0 + height;
  11898. if (isStroke) {
  11899. if (containStroke(x0, y0, x1, y0, lineWidth, x, y)
  11900. || containStroke(x1, y0, x1, y1, lineWidth, x, y)
  11901. || containStroke(x1, y1, x0, y1, lineWidth, x, y)
  11902. || containStroke(x0, y1, x0, y0, lineWidth, x, y)
  11903. ) {
  11904. return true;
  11905. }
  11906. }
  11907. else {
  11908. // FIXME Clockwise ?
  11909. w += windingLine(x1, y0, x1, y1, x, y);
  11910. w += windingLine(x0, y1, x0, y0, x, y);
  11911. }
  11912. break;
  11913. case CMD.Z:
  11914. if (isStroke) {
  11915. if (containStroke(
  11916. xi, yi, x0, y0, lineWidth, x, y
  11917. )) {
  11918. return true;
  11919. }
  11920. }
  11921. else {
  11922. // Close a subpath
  11923. w += windingLine(xi, yi, x0, y0, x, y);
  11924. // 如果被任何一个 subpath 包含
  11925. // FIXME subpaths may overlap
  11926. // if (w !== 0) {
  11927. // return true;
  11928. // }
  11929. }
  11930. xi = x0;
  11931. yi = y0;
  11932. break;
  11933. }
  11934. }
  11935. if (!isStroke && !isAroundEqual(yi, y0)) {
  11936. w += windingLine(xi, yi, x0, y0, x, y) || 0;
  11937. }
  11938. return w !== 0;
  11939. }
  11940. module.exports = {
  11941. contain: function (pathData, x, y) {
  11942. return containPath(pathData, 0, false, x, y);
  11943. },
  11944. containStroke: function (pathData, lineWidth, x, y) {
  11945. return containPath(pathData, lineWidth, true, x, y);
  11946. }
  11947. };
  11948. /***/ },
  11949. /* 40 */
  11950. /***/ function(module, exports) {
  11951. module.exports = {
  11952. /**
  11953. * 线段包含判断
  11954. * @param {number} x0
  11955. * @param {number} y0
  11956. * @param {number} x1
  11957. * @param {number} y1
  11958. * @param {number} lineWidth
  11959. * @param {number} x
  11960. * @param {number} y
  11961. * @return {boolean}
  11962. */
  11963. containStroke: function (x0, y0, x1, y1, lineWidth, x, y) {
  11964. if (lineWidth === 0) {
  11965. return false;
  11966. }
  11967. var _l = lineWidth;
  11968. var _a = 0;
  11969. var _b = x0;
  11970. // Quick reject
  11971. if (
  11972. (y > y0 + _l && y > y1 + _l)
  11973. || (y < y0 - _l && y < y1 - _l)
  11974. || (x > x0 + _l && x > x1 + _l)
  11975. || (x < x0 - _l && x < x1 - _l)
  11976. ) {
  11977. return false;
  11978. }
  11979. if (x0 !== x1) {
  11980. _a = (y0 - y1) / (x0 - x1);
  11981. _b = (x0 * y1 - x1 * y0) / (x0 - x1) ;
  11982. }
  11983. else {
  11984. return Math.abs(x - x0) <= _l / 2;
  11985. }
  11986. var tmp = _a * x - y + _b;
  11987. var _s = tmp * tmp / (_a * _a + 1);
  11988. return _s <= _l / 2 * _l / 2;
  11989. }
  11990. };
  11991. /***/ },
  11992. /* 41 */
  11993. /***/ function(module, exports, __webpack_require__) {
  11994. var curve = __webpack_require__(37);
  11995. module.exports = {
  11996. /**
  11997. * 三次贝塞尔曲线描边包含判断
  11998. * @param {number} x0
  11999. * @param {number} y0
  12000. * @param {number} x1
  12001. * @param {number} y1
  12002. * @param {number} x2
  12003. * @param {number} y2
  12004. * @param {number} x3
  12005. * @param {number} y3
  12006. * @param {number} lineWidth
  12007. * @param {number} x
  12008. * @param {number} y
  12009. * @return {boolean}
  12010. */
  12011. containStroke: function(x0, y0, x1, y1, x2, y2, x3, y3, lineWidth, x, y) {
  12012. if (lineWidth === 0) {
  12013. return false;
  12014. }
  12015. var _l = lineWidth;
  12016. // Quick reject
  12017. if (
  12018. (y > y0 + _l && y > y1 + _l && y > y2 + _l && y > y3 + _l)
  12019. || (y < y0 - _l && y < y1 - _l && y < y2 - _l && y < y3 - _l)
  12020. || (x > x0 + _l && x > x1 + _l && x > x2 + _l && x > x3 + _l)
  12021. || (x < x0 - _l && x < x1 - _l && x < x2 - _l && x < x3 - _l)
  12022. ) {
  12023. return false;
  12024. }
  12025. var d = curve.cubicProjectPoint(
  12026. x0, y0, x1, y1, x2, y2, x3, y3,
  12027. x, y, null
  12028. );
  12029. return d <= _l / 2;
  12030. }
  12031. };
  12032. /***/ },
  12033. /* 42 */
  12034. /***/ function(module, exports, __webpack_require__) {
  12035. var curve = __webpack_require__(37);
  12036. module.exports = {
  12037. /**
  12038. * 二次贝塞尔曲线描边包含判断
  12039. * @param {number} x0
  12040. * @param {number} y0
  12041. * @param {number} x1
  12042. * @param {number} y1
  12043. * @param {number} x2
  12044. * @param {number} y2
  12045. * @param {number} lineWidth
  12046. * @param {number} x
  12047. * @param {number} y
  12048. * @return {boolean}
  12049. */
  12050. containStroke: function (x0, y0, x1, y1, x2, y2, lineWidth, x, y) {
  12051. if (lineWidth === 0) {
  12052. return false;
  12053. }
  12054. var _l = lineWidth;
  12055. // Quick reject
  12056. if (
  12057. (y > y0 + _l && y > y1 + _l && y > y2 + _l)
  12058. || (y < y0 - _l && y < y1 - _l && y < y2 - _l)
  12059. || (x > x0 + _l && x > x1 + _l && x > x2 + _l)
  12060. || (x < x0 - _l && x < x1 - _l && x < x2 - _l)
  12061. ) {
  12062. return false;
  12063. }
  12064. var d = curve.quadraticProjectPoint(
  12065. x0, y0, x1, y1, x2, y2,
  12066. x, y, null
  12067. );
  12068. return d <= _l / 2;
  12069. }
  12070. };
  12071. /***/ },
  12072. /* 43 */
  12073. /***/ function(module, exports, __webpack_require__) {
  12074. var normalizeRadian = __webpack_require__(44).normalizeRadian;
  12075. var PI2 = Math.PI * 2;
  12076. module.exports = {
  12077. /**
  12078. * 圆弧描边包含判断
  12079. * @param {number} cx
  12080. * @param {number} cy
  12081. * @param {number} r
  12082. * @param {number} startAngle
  12083. * @param {number} endAngle
  12084. * @param {boolean} anticlockwise
  12085. * @param {number} lineWidth
  12086. * @param {number} x
  12087. * @param {number} y
  12088. * @return {Boolean}
  12089. */
  12090. containStroke: function (
  12091. cx, cy, r, startAngle, endAngle, anticlockwise,
  12092. lineWidth, x, y
  12093. ) {
  12094. if (lineWidth === 0) {
  12095. return false;
  12096. }
  12097. var _l = lineWidth;
  12098. x -= cx;
  12099. y -= cy;
  12100. var d = Math.sqrt(x * x + y * y);
  12101. if ((d - _l > r) || (d + _l < r)) {
  12102. return false;
  12103. }
  12104. if (Math.abs(startAngle - endAngle) % PI2 < 1e-4) {
  12105. // Is a circle
  12106. return true;
  12107. }
  12108. if (anticlockwise) {
  12109. var tmp = startAngle;
  12110. startAngle = normalizeRadian(endAngle);
  12111. endAngle = normalizeRadian(tmp);
  12112. } else {
  12113. startAngle = normalizeRadian(startAngle);
  12114. endAngle = normalizeRadian(endAngle);
  12115. }
  12116. if (startAngle > endAngle) {
  12117. endAngle += PI2;
  12118. }
  12119. var angle = Math.atan2(y, x);
  12120. if (angle < 0) {
  12121. angle += PI2;
  12122. }
  12123. return (angle >= startAngle && angle <= endAngle)
  12124. || (angle + PI2 >= startAngle && angle + PI2 <= endAngle);
  12125. }
  12126. };
  12127. /***/ },
  12128. /* 44 */
  12129. /***/ function(module, exports) {
  12130. var PI2 = Math.PI * 2;
  12131. module.exports = {
  12132. normalizeRadian: function(angle) {
  12133. angle %= PI2;
  12134. if (angle < 0) {
  12135. angle += PI2;
  12136. }
  12137. return angle;
  12138. }
  12139. };
  12140. /***/ },
  12141. /* 45 */
  12142. /***/ function(module, exports) {
  12143. module.exports = function windingLine(x0, y0, x1, y1, x, y) {
  12144. if ((y > y0 && y > y1) || (y < y0 && y < y1)) {
  12145. return 0;
  12146. }
  12147. // Ignore horizontal line
  12148. if (y1 === y0) {
  12149. return 0;
  12150. }
  12151. var dir = y1 < y0 ? 1 : -1;
  12152. var t = (y - y0) / (y1 - y0);
  12153. // Avoid winding error when intersection point is the connect point of two line of polygon
  12154. if (t === 1 || t === 0) {
  12155. dir = y1 < y0 ? 0.5 : -0.5;
  12156. }
  12157. var x_ = t * (x1 - x0) + x0;
  12158. return x_ > x ? dir : 0;
  12159. };
  12160. /***/ },
  12161. /* 46 */
  12162. /***/ function(module, exports) {
  12163. var Pattern = function (image, repeat) {
  12164. // Should do nothing more in this constructor. Because gradient can be
  12165. // declard by `color: {image: ...}`, where this constructor will not be called.
  12166. this.image = image;
  12167. this.repeat = repeat;
  12168. // Can be cloned
  12169. this.type = 'pattern';
  12170. };
  12171. Pattern.prototype.getCanvasPattern = function (ctx) {
  12172. return ctx.createPattern(this.image, this.repeat || 'repeat');
  12173. };
  12174. module.exports = Pattern;
  12175. /***/ },
  12176. /* 47 */
  12177. /***/ function(module, exports, __webpack_require__) {
  12178. var CMD = __webpack_require__(36).CMD;
  12179. var vec2 = __webpack_require__(10);
  12180. var v2ApplyTransform = vec2.applyTransform;
  12181. var points = [[], [], []];
  12182. var mathSqrt = Math.sqrt;
  12183. var mathAtan2 = Math.atan2;
  12184. function transformPath(path, m) {
  12185. var data = path.data;
  12186. var cmd;
  12187. var nPoint;
  12188. var i;
  12189. var j;
  12190. var k;
  12191. var p;
  12192. var M = CMD.M;
  12193. var C = CMD.C;
  12194. var L = CMD.L;
  12195. var R = CMD.R;
  12196. var A = CMD.A;
  12197. var Q = CMD.Q;
  12198. for (i = 0, j = 0; i < data.length;) {
  12199. cmd = data[i++];
  12200. j = i;
  12201. nPoint = 0;
  12202. switch (cmd) {
  12203. case M:
  12204. nPoint = 1;
  12205. break;
  12206. case L:
  12207. nPoint = 1;
  12208. break;
  12209. case C:
  12210. nPoint = 3;
  12211. break;
  12212. case Q:
  12213. nPoint = 2;
  12214. break;
  12215. case A:
  12216. var x = m[4];
  12217. var y = m[5];
  12218. var sx = mathSqrt(m[0] * m[0] + m[1] * m[1]);
  12219. var sy = mathSqrt(m[2] * m[2] + m[3] * m[3]);
  12220. var angle = mathAtan2(-m[1] / sy, m[0] / sx);
  12221. // cx
  12222. data[i] *= sx;
  12223. data[i++] += x;
  12224. // cy
  12225. data[i] *= sy;
  12226. data[i++] += y;
  12227. // Scale rx and ry
  12228. // FIXME Assume psi is 0 here
  12229. data[i++] *= sx;
  12230. data[i++] *= sy;
  12231. // Start angle
  12232. data[i++] += angle;
  12233. // end angle
  12234. data[i++] += angle;
  12235. // FIXME psi
  12236. i += 2;
  12237. j = i;
  12238. break;
  12239. case R:
  12240. // x0, y0
  12241. p[0] = data[i++];
  12242. p[1] = data[i++];
  12243. v2ApplyTransform(p, p, m);
  12244. data[j++] = p[0];
  12245. data[j++] = p[1];
  12246. // x1, y1
  12247. p[0] += data[i++];
  12248. p[1] += data[i++];
  12249. v2ApplyTransform(p, p, m);
  12250. data[j++] = p[0];
  12251. data[j++] = p[1];
  12252. }
  12253. for (k = 0; k < nPoint; k++) {
  12254. var p = points[k];
  12255. p[0] = data[i++];
  12256. p[1] = data[i++];
  12257. v2ApplyTransform(p, p, m);
  12258. // Write back
  12259. data[j++] = p[0];
  12260. data[j++] = p[1];
  12261. }
  12262. }
  12263. }
  12264. module.exports = transformPath;
  12265. /***/ },
  12266. /* 48 */
  12267. /***/ function(module, exports, __webpack_require__) {
  12268. /**
  12269. * Group是一个容器,可以插入子节点,Group的变换也会被应用到子节点上
  12270. * @module zrender/graphic/Group
  12271. * @example
  12272. * var Group = require('zrender/lib/container/Group');
  12273. * var Circle = require('zrender/lib/graphic/shape/Circle');
  12274. * var g = new Group();
  12275. * g.position[0] = 100;
  12276. * g.position[1] = 100;
  12277. * g.add(new Circle({
  12278. * style: {
  12279. * x: 100,
  12280. * y: 100,
  12281. * r: 20,
  12282. * }
  12283. * }));
  12284. * zr.add(g);
  12285. */
  12286. var zrUtil = __webpack_require__(4);
  12287. var Element = __webpack_require__(23);
  12288. var BoundingRect = __webpack_require__(9);
  12289. /**
  12290. * @alias module:zrender/graphic/Group
  12291. * @constructor
  12292. * @extends module:zrender/mixin/Transformable
  12293. * @extends module:zrender/mixin/Eventful
  12294. */
  12295. var Group = function (opts) {
  12296. opts = opts || {};
  12297. Element.call(this, opts);
  12298. for (var key in opts) {
  12299. if (opts.hasOwnProperty(key)) {
  12300. this[key] = opts[key];
  12301. }
  12302. }
  12303. this._children = [];
  12304. this.__storage = null;
  12305. this.__dirty = true;
  12306. };
  12307. Group.prototype = {
  12308. constructor: Group,
  12309. isGroup: true,
  12310. /**
  12311. * @type {string}
  12312. */
  12313. type: 'group',
  12314. /**
  12315. * 所有子孙元素是否响应鼠标事件
  12316. * @name module:/zrender/container/Group#silent
  12317. * @type {boolean}
  12318. * @default false
  12319. */
  12320. silent: false,
  12321. /**
  12322. * @return {Array.<module:zrender/Element>}
  12323. */
  12324. children: function () {
  12325. return this._children.slice();
  12326. },
  12327. /**
  12328. * 获取指定 index 的儿子节点
  12329. * @param {number} idx
  12330. * @return {module:zrender/Element}
  12331. */
  12332. childAt: function (idx) {
  12333. return this._children[idx];
  12334. },
  12335. /**
  12336. * 获取指定名字的儿子节点
  12337. * @param {string} name
  12338. * @return {module:zrender/Element}
  12339. */
  12340. childOfName: function (name) {
  12341. var children = this._children;
  12342. for (var i = 0; i < children.length; i++) {
  12343. if (children[i].name === name) {
  12344. return children[i];
  12345. }
  12346. }
  12347. },
  12348. /**
  12349. * @return {number}
  12350. */
  12351. childCount: function () {
  12352. return this._children.length;
  12353. },
  12354. /**
  12355. * 添加子节点到最后
  12356. * @param {module:zrender/Element} child
  12357. */
  12358. add: function (child) {
  12359. if (child && child !== this && child.parent !== this) {
  12360. this._children.push(child);
  12361. this._doAdd(child);
  12362. }
  12363. return this;
  12364. },
  12365. /**
  12366. * 添加子节点在 nextSibling 之前
  12367. * @param {module:zrender/Element} child
  12368. * @param {module:zrender/Element} nextSibling
  12369. */
  12370. addBefore: function (child, nextSibling) {
  12371. if (child && child !== this && child.parent !== this
  12372. && nextSibling && nextSibling.parent === this) {
  12373. var children = this._children;
  12374. var idx = children.indexOf(nextSibling);
  12375. if (idx >= 0) {
  12376. children.splice(idx, 0, child);
  12377. this._doAdd(child);
  12378. }
  12379. }
  12380. return this;
  12381. },
  12382. _doAdd: function (child) {
  12383. if (child.parent) {
  12384. child.parent.remove(child);
  12385. }
  12386. child.parent = this;
  12387. var storage = this.__storage;
  12388. var zr = this.__zr;
  12389. if (storage && storage !== child.__storage) {
  12390. storage.addToStorage(child);
  12391. if (child instanceof Group) {
  12392. child.addChildrenToStorage(storage);
  12393. }
  12394. }
  12395. zr && zr.refresh();
  12396. },
  12397. /**
  12398. * 移除子节点
  12399. * @param {module:zrender/Element} child
  12400. */
  12401. remove: function (child) {
  12402. var zr = this.__zr;
  12403. var storage = this.__storage;
  12404. var children = this._children;
  12405. var idx = zrUtil.indexOf(children, child);
  12406. if (idx < 0) {
  12407. return this;
  12408. }
  12409. children.splice(idx, 1);
  12410. child.parent = null;
  12411. if (storage) {
  12412. storage.delFromStorage(child);
  12413. if (child instanceof Group) {
  12414. child.delChildrenFromStorage(storage);
  12415. }
  12416. }
  12417. zr && zr.refresh();
  12418. return this;
  12419. },
  12420. /**
  12421. * 移除所有子节点
  12422. */
  12423. removeAll: function () {
  12424. var children = this._children;
  12425. var storage = this.__storage;
  12426. var child;
  12427. var i;
  12428. for (i = 0; i < children.length; i++) {
  12429. child = children[i];
  12430. if (storage) {
  12431. storage.delFromStorage(child);
  12432. if (child instanceof Group) {
  12433. child.delChildrenFromStorage(storage);
  12434. }
  12435. }
  12436. child.parent = null;
  12437. }
  12438. children.length = 0;
  12439. return this;
  12440. },
  12441. /**
  12442. * 遍历所有子节点
  12443. * @param {Function} cb
  12444. * @param {} context
  12445. */
  12446. eachChild: function (cb, context) {
  12447. var children = this._children;
  12448. for (var i = 0; i < children.length; i++) {
  12449. var child = children[i];
  12450. cb.call(context, child, i);
  12451. }
  12452. return this;
  12453. },
  12454. /**
  12455. * 深度优先遍历所有子孙节点
  12456. * @param {Function} cb
  12457. * @param {} context
  12458. */
  12459. traverse: function (cb, context) {
  12460. for (var i = 0; i < this._children.length; i++) {
  12461. var child = this._children[i];
  12462. cb.call(context, child);
  12463. if (child.type === 'group') {
  12464. child.traverse(cb, context);
  12465. }
  12466. }
  12467. return this;
  12468. },
  12469. addChildrenToStorage: function (storage) {
  12470. for (var i = 0; i < this._children.length; i++) {
  12471. var child = this._children[i];
  12472. storage.addToStorage(child);
  12473. if (child instanceof Group) {
  12474. child.addChildrenToStorage(storage);
  12475. }
  12476. }
  12477. },
  12478. delChildrenFromStorage: function (storage) {
  12479. for (var i = 0; i < this._children.length; i++) {
  12480. var child = this._children[i];
  12481. storage.delFromStorage(child);
  12482. if (child instanceof Group) {
  12483. child.delChildrenFromStorage(storage);
  12484. }
  12485. }
  12486. },
  12487. dirty: function () {
  12488. this.__dirty = true;
  12489. this.__zr && this.__zr.refresh();
  12490. return this;
  12491. },
  12492. /**
  12493. * @return {module:zrender/core/BoundingRect}
  12494. */
  12495. getBoundingRect: function (includeChildren) {
  12496. // TODO Caching
  12497. var rect = null;
  12498. var tmpRect = new BoundingRect(0, 0, 0, 0);
  12499. var children = includeChildren || this._children;
  12500. var tmpMat = [];
  12501. for (var i = 0; i < children.length; i++) {
  12502. var child = children[i];
  12503. if (child.ignore || child.invisible) {
  12504. continue;
  12505. }
  12506. var childRect = child.getBoundingRect();
  12507. var transform = child.getLocalTransform(tmpMat);
  12508. // TODO
  12509. // The boundingRect cacluated by transforming original
  12510. // rect may be bigger than the actual bundingRect when rotation
  12511. // is used. (Consider a circle rotated aginst its center, where
  12512. // the actual boundingRect should be the same as that not be
  12513. // rotated.) But we can not find better approach to calculate
  12514. // actual boundingRect yet, considering performance.
  12515. if (transform) {
  12516. tmpRect.copy(childRect);
  12517. tmpRect.applyTransform(transform);
  12518. rect = rect || tmpRect.clone();
  12519. rect.union(tmpRect);
  12520. }
  12521. else {
  12522. rect = rect || childRect.clone();
  12523. rect.union(childRect);
  12524. }
  12525. }
  12526. return rect || tmpRect;
  12527. }
  12528. };
  12529. zrUtil.inherits(Group, Element);
  12530. module.exports = Group;
  12531. /***/ },
  12532. /* 49 */
  12533. /***/ function(module, exports, __webpack_require__) {
  12534. /**
  12535. * Image element
  12536. * @module zrender/graphic/Image
  12537. */
  12538. var Displayable = __webpack_require__(21);
  12539. var BoundingRect = __webpack_require__(9);
  12540. var zrUtil = __webpack_require__(4);
  12541. var LRU = __webpack_require__(32);
  12542. var globalImageCache = new LRU(50);
  12543. /**
  12544. * @alias zrender/graphic/Image
  12545. * @extends module:zrender/graphic/Displayable
  12546. * @constructor
  12547. * @param {Object} opts
  12548. */
  12549. function ZImage(opts) {
  12550. Displayable.call(this, opts);
  12551. }
  12552. ZImage.prototype = {
  12553. constructor: ZImage,
  12554. type: 'image',
  12555. brush: function (ctx, prevEl) {
  12556. var style = this.style;
  12557. var src = style.image;
  12558. var image;
  12559. // Must bind each time
  12560. style.bind(ctx, this, prevEl);
  12561. // style.image is a url string
  12562. if (typeof src === 'string') {
  12563. image = this._image;
  12564. }
  12565. // style.image is an HTMLImageElement or HTMLCanvasElement or Canvas
  12566. else {
  12567. image = src;
  12568. }
  12569. // FIXME Case create many images with src
  12570. if (!image && src) {
  12571. // Try get from global image cache
  12572. var cachedImgObj = globalImageCache.get(src);
  12573. if (!cachedImgObj) {
  12574. // Create a new image
  12575. image = new Image();
  12576. image.onload = function () {
  12577. image.onload = null;
  12578. for (var i = 0; i < cachedImgObj.pending.length; i++) {
  12579. cachedImgObj.pending[i].dirty();
  12580. }
  12581. };
  12582. cachedImgObj = {
  12583. image: image,
  12584. pending: [this]
  12585. };
  12586. image.src = src;
  12587. globalImageCache.put(src, cachedImgObj);
  12588. this._image = image;
  12589. return;
  12590. }
  12591. else {
  12592. image = cachedImgObj.image;
  12593. this._image = image;
  12594. // Image is not complete finish, add to pending list
  12595. if (!image.width || !image.height) {
  12596. cachedImgObj.pending.push(this);
  12597. return;
  12598. }
  12599. }
  12600. }
  12601. if (image) {
  12602. // 图片已经加载完成
  12603. // if (image.nodeName.toUpperCase() == 'IMG') {
  12604. // if (!image.complete) {
  12605. // return;
  12606. // }
  12607. // }
  12608. // Else is canvas
  12609. var x = style.x || 0;
  12610. var y = style.y || 0;
  12611. // 图片加载失败
  12612. if (!image.width || !image.height) {
  12613. return;
  12614. }
  12615. var width = style.width;
  12616. var height = style.height;
  12617. var aspect = image.width / image.height;
  12618. if (width == null && height != null) {
  12619. // Keep image/height ratio
  12620. width = height * aspect;
  12621. }
  12622. else if (height == null && width != null) {
  12623. height = width / aspect;
  12624. }
  12625. else if (width == null && height == null) {
  12626. width = image.width;
  12627. height = image.height;
  12628. }
  12629. // 设置transform
  12630. this.setTransform(ctx);
  12631. if (style.sWidth && style.sHeight) {
  12632. var sx = style.sx || 0;
  12633. var sy = style.sy || 0;
  12634. ctx.drawImage(
  12635. image,
  12636. sx, sy, style.sWidth, style.sHeight,
  12637. x, y, width, height
  12638. );
  12639. }
  12640. else if (style.sx && style.sy) {
  12641. var sx = style.sx;
  12642. var sy = style.sy;
  12643. var sWidth = width - sx;
  12644. var sHeight = height - sy;
  12645. ctx.drawImage(
  12646. image,
  12647. sx, sy, sWidth, sHeight,
  12648. x, y, width, height
  12649. );
  12650. }
  12651. else {
  12652. ctx.drawImage(image, x, y, width, height);
  12653. }
  12654. this.restoreTransform(ctx);
  12655. // Draw rect text
  12656. if (style.text != null) {
  12657. this.drawRectText(ctx, this.getBoundingRect());
  12658. }
  12659. }
  12660. },
  12661. getBoundingRect: function () {
  12662. var style = this.style;
  12663. if (! this._rect) {
  12664. this._rect = new BoundingRect(
  12665. style.x || 0, style.y || 0, style.width || 0, style.height || 0
  12666. );
  12667. }
  12668. return this._rect;
  12669. }
  12670. };
  12671. zrUtil.inherits(ZImage, Displayable);
  12672. module.exports = ZImage;
  12673. /***/ },
  12674. /* 50 */
  12675. /***/ function(module, exports, __webpack_require__) {
  12676. /**
  12677. * Text element
  12678. * @module zrender/graphic/Text
  12679. *
  12680. * TODO Wrapping
  12681. *
  12682. * Text not support gradient
  12683. */
  12684. var Displayable = __webpack_require__(21);
  12685. var zrUtil = __webpack_require__(4);
  12686. var textContain = __webpack_require__(8);
  12687. /**
  12688. * @alias zrender/graphic/Text
  12689. * @extends module:zrender/graphic/Displayable
  12690. * @constructor
  12691. * @param {Object} opts
  12692. */
  12693. var Text = function (opts) {
  12694. Displayable.call(this, opts);
  12695. };
  12696. Text.prototype = {
  12697. constructor: Text,
  12698. type: 'text',
  12699. brush: function (ctx, prevEl) {
  12700. var style = this.style;
  12701. var x = style.x || 0;
  12702. var y = style.y || 0;
  12703. // Convert to string
  12704. var text = style.text;
  12705. // Convert to string
  12706. text != null && (text += '');
  12707. // Always bind style
  12708. style.bind(ctx, this, prevEl);
  12709. if (text) {
  12710. this.setTransform(ctx);
  12711. var textBaseline;
  12712. var textAlign = style.textAlign;
  12713. var font = style.textFont || style.font;
  12714. if (style.textVerticalAlign) {
  12715. var rect = textContain.getBoundingRect(
  12716. text, font, style.textAlign, 'top'
  12717. );
  12718. // Ignore textBaseline
  12719. textBaseline = 'middle';
  12720. switch (style.textVerticalAlign) {
  12721. case 'middle':
  12722. y -= rect.height / 2 - rect.lineHeight / 2;
  12723. break;
  12724. case 'bottom':
  12725. y -= rect.height - rect.lineHeight / 2;
  12726. break;
  12727. default:
  12728. y += rect.lineHeight / 2;
  12729. }
  12730. }
  12731. else {
  12732. textBaseline = style.textBaseline;
  12733. }
  12734. // TODO Invalid font
  12735. ctx.font = font || '12px sans-serif';
  12736. ctx.textAlign = textAlign || 'left';
  12737. // Use canvas default left textAlign. Giving invalid value will cause state not change
  12738. if (ctx.textAlign !== textAlign) {
  12739. ctx.textAlign = 'left';
  12740. }
  12741. // FIXME in text contain default is top
  12742. ctx.textBaseline = textBaseline || 'alphabetic';
  12743. // Use canvas default alphabetic baseline
  12744. if (ctx.textBaseline !== textBaseline) {
  12745. ctx.textBaseline = 'alphabetic';
  12746. }
  12747. var lineHeight = textContain.measureText('国', ctx.font).width;
  12748. var textLines = text.split('\n');
  12749. for (var i = 0; i < textLines.length; i++) {
  12750. // Fill after stroke so the outline will not cover the main part.
  12751. style.hasStroke() && ctx.strokeText(textLines[i], x, y);
  12752. style.hasFill() && ctx.fillText(textLines[i], x, y);
  12753. y += lineHeight;
  12754. }
  12755. this.restoreTransform(ctx);
  12756. }
  12757. },
  12758. getBoundingRect: function () {
  12759. var style = this.style;
  12760. if (!this._rect) {
  12761. var textVerticalAlign = style.textVerticalAlign;
  12762. var rect = textContain.getBoundingRect(
  12763. style.text + '', style.textFont || style.font, style.textAlign,
  12764. textVerticalAlign ? 'top' : style.textBaseline
  12765. );
  12766. switch (textVerticalAlign) {
  12767. case 'middle':
  12768. rect.y -= rect.height / 2;
  12769. break;
  12770. case 'bottom':
  12771. rect.y -= rect.height;
  12772. break;
  12773. }
  12774. rect.x += style.x || 0;
  12775. rect.y += style.y || 0;
  12776. if (style.hasStroke()) {
  12777. var w = style.lineWidth;
  12778. rect.x -= w / 2;
  12779. rect.y -= w / 2;
  12780. rect.width += w;
  12781. rect.height += w;
  12782. }
  12783. this._rect = rect;
  12784. }
  12785. return this._rect;
  12786. }
  12787. };
  12788. zrUtil.inherits(Text, Displayable);
  12789. module.exports = Text;
  12790. /***/ },
  12791. /* 51 */
  12792. /***/ function(module, exports, __webpack_require__) {
  12793. 'use strict';
  12794. /**
  12795. * 圆形
  12796. * @module zrender/shape/Circle
  12797. */
  12798. module.exports = __webpack_require__(20).extend({
  12799. type: 'circle',
  12800. shape: {
  12801. cx: 0,
  12802. cy: 0,
  12803. r: 0
  12804. },
  12805. buildPath : function (ctx, shape, inBundle) {
  12806. // Better stroking in ShapeBundle
  12807. // Always do it may have performence issue ( fill may be 2x more cost)
  12808. if (inBundle) {
  12809. ctx.moveTo(shape.cx + shape.r, shape.cy);
  12810. }
  12811. // else {
  12812. // if (ctx.allocate && !ctx.data.length) {
  12813. // ctx.allocate(ctx.CMD_MEM_SIZE.A);
  12814. // }
  12815. // }
  12816. // Better stroking in ShapeBundle
  12817. // ctx.moveTo(shape.cx + shape.r, shape.cy);
  12818. ctx.arc(shape.cx, shape.cy, shape.r, 0, Math.PI * 2, true);
  12819. }
  12820. });
  12821. /***/ },
  12822. /* 52 */
  12823. /***/ function(module, exports, __webpack_require__) {
  12824. /**
  12825. * 扇形
  12826. * @module zrender/graphic/shape/Sector
  12827. */
  12828. var env = __webpack_require__(2);
  12829. var Path = __webpack_require__(20);
  12830. var shadowTemp = [
  12831. ['shadowBlur', 0],
  12832. ['shadowColor', '#000'],
  12833. ['shadowOffsetX', 0],
  12834. ['shadowOffsetY', 0]
  12835. ];
  12836. module.exports = Path.extend({
  12837. type: 'sector',
  12838. shape: {
  12839. cx: 0,
  12840. cy: 0,
  12841. r0: 0,
  12842. r: 0,
  12843. startAngle: 0,
  12844. endAngle: Math.PI * 2,
  12845. clockwise: true
  12846. },
  12847. brush: (env.browser.ie && env.browser.version >= 11) // version: '11.0'
  12848. // Fix weird bug in some version of IE11 (like 11.0.9600.17801),
  12849. // where exception "unexpected call to method or property access"
  12850. // might be thrown when calling ctx.fill after a path whose area size
  12851. // is zero is drawn and ctx.clip() is called and shadowBlur is set.
  12852. // (e.g.,
  12853. // ctx.moveTo(10, 10);
  12854. // ctx.lineTo(20, 10);
  12855. // ctx.closePath();
  12856. // ctx.clip();
  12857. // ctx.shadowBlur = 10;
  12858. // ...
  12859. // ctx.fill();
  12860. // )
  12861. ? function () {
  12862. var clipPaths = this.__clipPaths;
  12863. var style = this.style;
  12864. var modified;
  12865. if (clipPaths) {
  12866. for (var i = 0; i < clipPaths.length; i++) {
  12867. var shape = clipPaths[i] && clipPaths[i].shape;
  12868. if (shape && shape.startAngle === shape.endAngle) {
  12869. for (var j = 0; j < shadowTemp.length; j++) {
  12870. shadowTemp[j][2] = style[shadowTemp[j][0]];
  12871. style[shadowTemp[j][0]] = shadowTemp[j][1];
  12872. }
  12873. modified = true;
  12874. break;
  12875. }
  12876. }
  12877. }
  12878. Path.prototype.brush.apply(this, arguments);
  12879. if (modified) {
  12880. for (var j = 0; j < shadowTemp.length; j++) {
  12881. style[shadowTemp[j][0]] = shadowTemp[j][2];
  12882. }
  12883. }
  12884. }
  12885. : Path.prototype.brush,
  12886. buildPath: function (ctx, shape) {
  12887. var x = shape.cx;
  12888. var y = shape.cy;
  12889. var r0 = Math.max(shape.r0 || 0, 0);
  12890. var r = Math.max(shape.r, 0);
  12891. var startAngle = shape.startAngle;
  12892. var endAngle = shape.endAngle;
  12893. var clockwise = shape.clockwise;
  12894. var unitX = Math.cos(startAngle);
  12895. var unitY = Math.sin(startAngle);
  12896. ctx.moveTo(unitX * r0 + x, unitY * r0 + y);
  12897. ctx.lineTo(unitX * r + x, unitY * r + y);
  12898. ctx.arc(x, y, r, startAngle, endAngle, !clockwise);
  12899. ctx.lineTo(
  12900. Math.cos(endAngle) * r0 + x,
  12901. Math.sin(endAngle) * r0 + y
  12902. );
  12903. if (r0 !== 0) {
  12904. ctx.arc(x, y, r0, endAngle, startAngle, clockwise);
  12905. }
  12906. ctx.closePath();
  12907. }
  12908. });
  12909. /***/ },
  12910. /* 53 */
  12911. /***/ function(module, exports, __webpack_require__) {
  12912. /**
  12913. * 圆环
  12914. * @module zrender/graphic/shape/Ring
  12915. */
  12916. module.exports = __webpack_require__(20).extend({
  12917. type: 'ring',
  12918. shape: {
  12919. cx: 0,
  12920. cy: 0,
  12921. r: 0,
  12922. r0: 0
  12923. },
  12924. buildPath: function (ctx, shape) {
  12925. var x = shape.cx;
  12926. var y = shape.cy;
  12927. var PI2 = Math.PI * 2;
  12928. ctx.moveTo(x + shape.r, y);
  12929. ctx.arc(x, y, shape.r, 0, PI2, false);
  12930. ctx.moveTo(x + shape.r0, y);
  12931. ctx.arc(x, y, shape.r0, 0, PI2, true);
  12932. }
  12933. });
  12934. /***/ },
  12935. /* 54 */
  12936. /***/ function(module, exports, __webpack_require__) {
  12937. /**
  12938. * 多边形
  12939. * @module zrender/shape/Polygon
  12940. */
  12941. var polyHelper = __webpack_require__(55);
  12942. module.exports = __webpack_require__(20).extend({
  12943. type: 'polygon',
  12944. shape: {
  12945. points: null,
  12946. smooth: false,
  12947. smoothConstraint: null
  12948. },
  12949. buildPath: function (ctx, shape) {
  12950. polyHelper.buildPath(ctx, shape, true);
  12951. }
  12952. });
  12953. /***/ },
  12954. /* 55 */
  12955. /***/ function(module, exports, __webpack_require__) {
  12956. var smoothSpline = __webpack_require__(56);
  12957. var smoothBezier = __webpack_require__(57);
  12958. module.exports = {
  12959. buildPath: function (ctx, shape, closePath) {
  12960. var points = shape.points;
  12961. var smooth = shape.smooth;
  12962. if (points && points.length >= 2) {
  12963. if (smooth && smooth !== 'spline') {
  12964. var controlPoints = smoothBezier(
  12965. points, smooth, closePath, shape.smoothConstraint
  12966. );
  12967. ctx.moveTo(points[0][0], points[0][1]);
  12968. var len = points.length;
  12969. for (var i = 0; i < (closePath ? len : len - 1); i++) {
  12970. var cp1 = controlPoints[i * 2];
  12971. var cp2 = controlPoints[i * 2 + 1];
  12972. var p = points[(i + 1) % len];
  12973. ctx.bezierCurveTo(
  12974. cp1[0], cp1[1], cp2[0], cp2[1], p[0], p[1]
  12975. );
  12976. }
  12977. }
  12978. else {
  12979. if (smooth === 'spline') {
  12980. points = smoothSpline(points, closePath);
  12981. }
  12982. ctx.moveTo(points[0][0], points[0][1]);
  12983. for (var i = 1, l = points.length; i < l; i++) {
  12984. ctx.lineTo(points[i][0], points[i][1]);
  12985. }
  12986. }
  12987. closePath && ctx.closePath();
  12988. }
  12989. }
  12990. };
  12991. /***/ },
  12992. /* 56 */
  12993. /***/ function(module, exports, __webpack_require__) {
  12994. /**
  12995. * Catmull-Rom spline 插值折线
  12996. * @module zrender/shape/util/smoothSpline
  12997. * @author pissang (https://www.github.com/pissang)
  12998. * Kener (@Kener-林峰, kener.linfeng@gmail.com)
  12999. * errorrik (errorrik@gmail.com)
  13000. */
  13001. var vec2 = __webpack_require__(10);
  13002. /**
  13003. * @inner
  13004. */
  13005. function interpolate(p0, p1, p2, p3, t, t2, t3) {
  13006. var v0 = (p2 - p0) * 0.5;
  13007. var v1 = (p3 - p1) * 0.5;
  13008. return (2 * (p1 - p2) + v0 + v1) * t3
  13009. + (-3 * (p1 - p2) - 2 * v0 - v1) * t2
  13010. + v0 * t + p1;
  13011. }
  13012. /**
  13013. * @alias module:zrender/shape/util/smoothSpline
  13014. * @param {Array} points 线段顶点数组
  13015. * @param {boolean} isLoop
  13016. * @return {Array}
  13017. */
  13018. module.exports = function (points, isLoop) {
  13019. var len = points.length;
  13020. var ret = [];
  13021. var distance = 0;
  13022. for (var i = 1; i < len; i++) {
  13023. distance += vec2.distance(points[i - 1], points[i]);
  13024. }
  13025. var segs = distance / 2;
  13026. segs = segs < len ? len : segs;
  13027. for (var i = 0; i < segs; i++) {
  13028. var pos = i / (segs - 1) * (isLoop ? len : len - 1);
  13029. var idx = Math.floor(pos);
  13030. var w = pos - idx;
  13031. var p0;
  13032. var p1 = points[idx % len];
  13033. var p2;
  13034. var p3;
  13035. if (!isLoop) {
  13036. p0 = points[idx === 0 ? idx : idx - 1];
  13037. p2 = points[idx > len - 2 ? len - 1 : idx + 1];
  13038. p3 = points[idx > len - 3 ? len - 1 : idx + 2];
  13039. }
  13040. else {
  13041. p0 = points[(idx - 1 + len) % len];
  13042. p2 = points[(idx + 1) % len];
  13043. p3 = points[(idx + 2) % len];
  13044. }
  13045. var w2 = w * w;
  13046. var w3 = w * w2;
  13047. ret.push([
  13048. interpolate(p0[0], p1[0], p2[0], p3[0], w, w2, w3),
  13049. interpolate(p0[1], p1[1], p2[1], p3[1], w, w2, w3)
  13050. ]);
  13051. }
  13052. return ret;
  13053. };
  13054. /***/ },
  13055. /* 57 */
  13056. /***/ function(module, exports, __webpack_require__) {
  13057. /**
  13058. * 贝塞尔平滑曲线
  13059. * @module zrender/shape/util/smoothBezier
  13060. * @author pissang (https://www.github.com/pissang)
  13061. * Kener (@Kener-林峰, kener.linfeng@gmail.com)
  13062. * errorrik (errorrik@gmail.com)
  13063. */
  13064. var vec2 = __webpack_require__(10);
  13065. var v2Min = vec2.min;
  13066. var v2Max = vec2.max;
  13067. var v2Scale = vec2.scale;
  13068. var v2Distance = vec2.distance;
  13069. var v2Add = vec2.add;
  13070. /**
  13071. * 贝塞尔平滑曲线
  13072. * @alias module:zrender/shape/util/smoothBezier
  13073. * @param {Array} points 线段顶点数组
  13074. * @param {number} smooth 平滑等级, 0-1
  13075. * @param {boolean} isLoop
  13076. * @param {Array} constraint 将计算出来的控制点约束在一个包围盒内
  13077. * 比如 [[0, 0], [100, 100]], 这个包围盒会与
  13078. * 整个折线的包围盒做一个并集用来约束控制点。
  13079. * @param {Array} 计算出来的控制点数组
  13080. */
  13081. module.exports = function (points, smooth, isLoop, constraint) {
  13082. var cps = [];
  13083. var v = [];
  13084. var v1 = [];
  13085. var v2 = [];
  13086. var prevPoint;
  13087. var nextPoint;
  13088. var min, max;
  13089. if (constraint) {
  13090. min = [Infinity, Infinity];
  13091. max = [-Infinity, -Infinity];
  13092. for (var i = 0, len = points.length; i < len; i++) {
  13093. v2Min(min, min, points[i]);
  13094. v2Max(max, max, points[i]);
  13095. }
  13096. // 与指定的包围盒做并集
  13097. v2Min(min, min, constraint[0]);
  13098. v2Max(max, max, constraint[1]);
  13099. }
  13100. for (var i = 0, len = points.length; i < len; i++) {
  13101. var point = points[i];
  13102. if (isLoop) {
  13103. prevPoint = points[i ? i - 1 : len - 1];
  13104. nextPoint = points[(i + 1) % len];
  13105. }
  13106. else {
  13107. if (i === 0 || i === len - 1) {
  13108. cps.push(vec2.clone(points[i]));
  13109. continue;
  13110. }
  13111. else {
  13112. prevPoint = points[i - 1];
  13113. nextPoint = points[i + 1];
  13114. }
  13115. }
  13116. vec2.sub(v, nextPoint, prevPoint);
  13117. // use degree to scale the handle length
  13118. v2Scale(v, v, smooth);
  13119. var d0 = v2Distance(point, prevPoint);
  13120. var d1 = v2Distance(point, nextPoint);
  13121. var sum = d0 + d1;
  13122. if (sum !== 0) {
  13123. d0 /= sum;
  13124. d1 /= sum;
  13125. }
  13126. v2Scale(v1, v, -d0);
  13127. v2Scale(v2, v, d1);
  13128. var cp0 = v2Add([], point, v1);
  13129. var cp1 = v2Add([], point, v2);
  13130. if (constraint) {
  13131. v2Max(cp0, cp0, min);
  13132. v2Min(cp0, cp0, max);
  13133. v2Max(cp1, cp1, min);
  13134. v2Min(cp1, cp1, max);
  13135. }
  13136. cps.push(cp0);
  13137. cps.push(cp1);
  13138. }
  13139. if (isLoop) {
  13140. cps.push(cps.shift());
  13141. }
  13142. return cps;
  13143. };
  13144. /***/ },
  13145. /* 58 */
  13146. /***/ function(module, exports, __webpack_require__) {
  13147. /**
  13148. * @module zrender/graphic/shape/Polyline
  13149. */
  13150. var polyHelper = __webpack_require__(55);
  13151. module.exports = __webpack_require__(20).extend({
  13152. type: 'polyline',
  13153. shape: {
  13154. points: null,
  13155. smooth: false,
  13156. smoothConstraint: null
  13157. },
  13158. style: {
  13159. stroke: '#000',
  13160. fill: null
  13161. },
  13162. buildPath: function (ctx, shape) {
  13163. polyHelper.buildPath(ctx, shape, false);
  13164. }
  13165. });
  13166. /***/ },
  13167. /* 59 */
  13168. /***/ function(module, exports, __webpack_require__) {
  13169. /**
  13170. * 矩形
  13171. * @module zrender/graphic/shape/Rect
  13172. */
  13173. var roundRectHelper = __webpack_require__(60);
  13174. module.exports = __webpack_require__(20).extend({
  13175. type: 'rect',
  13176. shape: {
  13177. // 左上、右上、右下、左下角的半径依次为r1、r2、r3、r4
  13178. // r缩写为1 相当于 [1, 1, 1, 1]
  13179. // r缩写为[1] 相当于 [1, 1, 1, 1]
  13180. // r缩写为[1, 2] 相当于 [1, 2, 1, 2]
  13181. // r缩写为[1, 2, 3] 相当于 [1, 2, 3, 2]
  13182. r: 0,
  13183. x: 0,
  13184. y: 0,
  13185. width: 0,
  13186. height: 0
  13187. },
  13188. buildPath: function (ctx, shape) {
  13189. var x = shape.x;
  13190. var y = shape.y;
  13191. var width = shape.width;
  13192. var height = shape.height;
  13193. if (!shape.r) {
  13194. ctx.rect(x, y, width, height);
  13195. }
  13196. else {
  13197. roundRectHelper.buildPath(ctx, shape);
  13198. }
  13199. ctx.closePath();
  13200. return;
  13201. }
  13202. });
  13203. /***/ },
  13204. /* 60 */
  13205. /***/ function(module, exports) {
  13206. module.exports = {
  13207. buildPath: function (ctx, shape) {
  13208. var x = shape.x;
  13209. var y = shape.y;
  13210. var width = shape.width;
  13211. var height = shape.height;
  13212. var r = shape.r;
  13213. var r1;
  13214. var r2;
  13215. var r3;
  13216. var r4;
  13217. // Convert width and height to positive for better borderRadius
  13218. if (width < 0) {
  13219. x = x + width;
  13220. width = -width;
  13221. }
  13222. if (height < 0) {
  13223. y = y + height;
  13224. height = -height;
  13225. }
  13226. if (typeof r === 'number') {
  13227. r1 = r2 = r3 = r4 = r;
  13228. }
  13229. else if (r instanceof Array) {
  13230. if (r.length === 1) {
  13231. r1 = r2 = r3 = r4 = r[0];
  13232. }
  13233. else if (r.length === 2) {
  13234. r1 = r3 = r[0];
  13235. r2 = r4 = r[1];
  13236. }
  13237. else if (r.length === 3) {
  13238. r1 = r[0];
  13239. r2 = r4 = r[1];
  13240. r3 = r[2];
  13241. }
  13242. else {
  13243. r1 = r[0];
  13244. r2 = r[1];
  13245. r3 = r[2];
  13246. r4 = r[3];
  13247. }
  13248. }
  13249. else {
  13250. r1 = r2 = r3 = r4 = 0;
  13251. }
  13252. var total;
  13253. if (r1 + r2 > width) {
  13254. total = r1 + r2;
  13255. r1 *= width / total;
  13256. r2 *= width / total;
  13257. }
  13258. if (r3 + r4 > width) {
  13259. total = r3 + r4;
  13260. r3 *= width / total;
  13261. r4 *= width / total;
  13262. }
  13263. if (r2 + r3 > height) {
  13264. total = r2 + r3;
  13265. r2 *= height / total;
  13266. r3 *= height / total;
  13267. }
  13268. if (r1 + r4 > height) {
  13269. total = r1 + r4;
  13270. r1 *= height / total;
  13271. r4 *= height / total;
  13272. }
  13273. ctx.moveTo(x + r1, y);
  13274. ctx.lineTo(x + width - r2, y);
  13275. r2 !== 0 && ctx.quadraticCurveTo(
  13276. x + width, y, x + width, y + r2
  13277. );
  13278. ctx.lineTo(x + width, y + height - r3);
  13279. r3 !== 0 && ctx.quadraticCurveTo(
  13280. x + width, y + height, x + width - r3, y + height
  13281. );
  13282. ctx.lineTo(x + r4, y + height);
  13283. r4 !== 0 && ctx.quadraticCurveTo(
  13284. x, y + height, x, y + height - r4
  13285. );
  13286. ctx.lineTo(x, y + r1);
  13287. r1 !== 0 && ctx.quadraticCurveTo(x, y, x + r1, y);
  13288. }
  13289. };
  13290. /***/ },
  13291. /* 61 */
  13292. /***/ function(module, exports, __webpack_require__) {
  13293. /**
  13294. * 直线
  13295. * @module zrender/graphic/shape/Line
  13296. */
  13297. module.exports = __webpack_require__(20).extend({
  13298. type: 'line',
  13299. shape: {
  13300. // Start point
  13301. x1: 0,
  13302. y1: 0,
  13303. // End point
  13304. x2: 0,
  13305. y2: 0,
  13306. percent: 1
  13307. },
  13308. style: {
  13309. stroke: '#000',
  13310. fill: null
  13311. },
  13312. buildPath: function (ctx, shape) {
  13313. var x1 = shape.x1;
  13314. var y1 = shape.y1;
  13315. var x2 = shape.x2;
  13316. var y2 = shape.y2;
  13317. var percent = shape.percent;
  13318. if (percent === 0) {
  13319. return;
  13320. }
  13321. ctx.moveTo(x1, y1);
  13322. if (percent < 1) {
  13323. x2 = x1 * (1 - percent) + x2 * percent;
  13324. y2 = y1 * (1 - percent) + y2 * percent;
  13325. }
  13326. ctx.lineTo(x2, y2);
  13327. },
  13328. /**
  13329. * Get point at percent
  13330. * @param {number} percent
  13331. * @return {Array.<number>}
  13332. */
  13333. pointAt: function (p) {
  13334. var shape = this.shape;
  13335. return [
  13336. shape.x1 * (1 - p) + shape.x2 * p,
  13337. shape.y1 * (1 - p) + shape.y2 * p
  13338. ];
  13339. }
  13340. });
  13341. /***/ },
  13342. /* 62 */
  13343. /***/ function(module, exports, __webpack_require__) {
  13344. 'use strict';
  13345. /**
  13346. * 贝塞尔曲线
  13347. * @module zrender/shape/BezierCurve
  13348. */
  13349. var curveTool = __webpack_require__(37);
  13350. var vec2 = __webpack_require__(10);
  13351. var quadraticSubdivide = curveTool.quadraticSubdivide;
  13352. var cubicSubdivide = curveTool.cubicSubdivide;
  13353. var quadraticAt = curveTool.quadraticAt;
  13354. var cubicAt = curveTool.cubicAt;
  13355. var quadraticDerivativeAt = curveTool.quadraticDerivativeAt;
  13356. var cubicDerivativeAt = curveTool.cubicDerivativeAt;
  13357. var out = [];
  13358. function someVectorAt(shape, t, isTangent) {
  13359. var cpx2 = shape.cpx2;
  13360. var cpy2 = shape.cpy2;
  13361. if (cpx2 === null || cpy2 === null) {
  13362. return [
  13363. (isTangent ? cubicDerivativeAt : cubicAt)(shape.x1, shape.cpx1, shape.cpx2, shape.x2, t),
  13364. (isTangent ? cubicDerivativeAt : cubicAt)(shape.y1, shape.cpy1, shape.cpy2, shape.y2, t)
  13365. ];
  13366. }
  13367. else {
  13368. return [
  13369. (isTangent ? quadraticDerivativeAt : quadraticAt)(shape.x1, shape.cpx1, shape.x2, t),
  13370. (isTangent ? quadraticDerivativeAt : quadraticAt)(shape.y1, shape.cpy1, shape.y2, t)
  13371. ];
  13372. }
  13373. }
  13374. module.exports = __webpack_require__(20).extend({
  13375. type: 'bezier-curve',
  13376. shape: {
  13377. x1: 0,
  13378. y1: 0,
  13379. x2: 0,
  13380. y2: 0,
  13381. cpx1: 0,
  13382. cpy1: 0,
  13383. // cpx2: 0,
  13384. // cpy2: 0
  13385. // Curve show percent, for animating
  13386. percent: 1
  13387. },
  13388. style: {
  13389. stroke: '#000',
  13390. fill: null
  13391. },
  13392. buildPath: function (ctx, shape) {
  13393. var x1 = shape.x1;
  13394. var y1 = shape.y1;
  13395. var x2 = shape.x2;
  13396. var y2 = shape.y2;
  13397. var cpx1 = shape.cpx1;
  13398. var cpy1 = shape.cpy1;
  13399. var cpx2 = shape.cpx2;
  13400. var cpy2 = shape.cpy2;
  13401. var percent = shape.percent;
  13402. if (percent === 0) {
  13403. return;
  13404. }
  13405. ctx.moveTo(x1, y1);
  13406. if (cpx2 == null || cpy2 == null) {
  13407. if (percent < 1) {
  13408. quadraticSubdivide(
  13409. x1, cpx1, x2, percent, out
  13410. );
  13411. cpx1 = out[1];
  13412. x2 = out[2];
  13413. quadraticSubdivide(
  13414. y1, cpy1, y2, percent, out
  13415. );
  13416. cpy1 = out[1];
  13417. y2 = out[2];
  13418. }
  13419. ctx.quadraticCurveTo(
  13420. cpx1, cpy1,
  13421. x2, y2
  13422. );
  13423. }
  13424. else {
  13425. if (percent < 1) {
  13426. cubicSubdivide(
  13427. x1, cpx1, cpx2, x2, percent, out
  13428. );
  13429. cpx1 = out[1];
  13430. cpx2 = out[2];
  13431. x2 = out[3];
  13432. cubicSubdivide(
  13433. y1, cpy1, cpy2, y2, percent, out
  13434. );
  13435. cpy1 = out[1];
  13436. cpy2 = out[2];
  13437. y2 = out[3];
  13438. }
  13439. ctx.bezierCurveTo(
  13440. cpx1, cpy1,
  13441. cpx2, cpy2,
  13442. x2, y2
  13443. );
  13444. }
  13445. },
  13446. /**
  13447. * Get point at percent
  13448. * @param {number} t
  13449. * @return {Array.<number>}
  13450. */
  13451. pointAt: function (t) {
  13452. return someVectorAt(this.shape, t, false);
  13453. },
  13454. /**
  13455. * Get tangent at percent
  13456. * @param {number} t
  13457. * @return {Array.<number>}
  13458. */
  13459. tangentAt: function (t) {
  13460. var p = someVectorAt(this.shape, t, true);
  13461. return vec2.normalize(p, p);
  13462. }
  13463. });
  13464. /***/ },
  13465. /* 63 */
  13466. /***/ function(module, exports, __webpack_require__) {
  13467. /**
  13468. * 圆弧
  13469. * @module zrender/graphic/shape/Arc
  13470. */
  13471. module.exports = __webpack_require__(20).extend({
  13472. type: 'arc',
  13473. shape: {
  13474. cx: 0,
  13475. cy: 0,
  13476. r: 0,
  13477. startAngle: 0,
  13478. endAngle: Math.PI * 2,
  13479. clockwise: true
  13480. },
  13481. style: {
  13482. stroke: '#000',
  13483. fill: null
  13484. },
  13485. buildPath: function (ctx, shape) {
  13486. var x = shape.cx;
  13487. var y = shape.cy;
  13488. var r = Math.max(shape.r, 0);
  13489. var startAngle = shape.startAngle;
  13490. var endAngle = shape.endAngle;
  13491. var clockwise = shape.clockwise;
  13492. var unitX = Math.cos(startAngle);
  13493. var unitY = Math.sin(startAngle);
  13494. ctx.moveTo(unitX * r + x, unitY * r + y);
  13495. ctx.arc(x, y, r, startAngle, endAngle, !clockwise);
  13496. }
  13497. });
  13498. /***/ },
  13499. /* 64 */
  13500. /***/ function(module, exports, __webpack_require__) {
  13501. // CompoundPath to improve performance
  13502. var Path = __webpack_require__(20);
  13503. module.exports = Path.extend({
  13504. type: 'compound',
  13505. shape: {
  13506. paths: null
  13507. },
  13508. _updatePathDirty: function () {
  13509. var dirtyPath = this.__dirtyPath;
  13510. var paths = this.shape.paths;
  13511. for (var i = 0; i < paths.length; i++) {
  13512. // Mark as dirty if any subpath is dirty
  13513. dirtyPath = dirtyPath || paths[i].__dirtyPath;
  13514. }
  13515. this.__dirtyPath = dirtyPath;
  13516. this.__dirty = this.__dirty || dirtyPath;
  13517. },
  13518. beforeBrush: function () {
  13519. this._updatePathDirty();
  13520. var paths = this.shape.paths || [];
  13521. var scale = this.getGlobalScale();
  13522. // Update path scale
  13523. for (var i = 0; i < paths.length; i++) {
  13524. if (!paths[i].path) {
  13525. paths[i].createPathProxy();
  13526. }
  13527. paths[i].path.setScale(scale[0], scale[1]);
  13528. }
  13529. },
  13530. buildPath: function (ctx, shape) {
  13531. var paths = shape.paths || [];
  13532. for (var i = 0; i < paths.length; i++) {
  13533. paths[i].buildPath(ctx, paths[i].shape, true);
  13534. }
  13535. },
  13536. afterBrush: function () {
  13537. var paths = this.shape.paths;
  13538. for (var i = 0; i < paths.length; i++) {
  13539. paths[i].__dirtyPath = false;
  13540. }
  13541. },
  13542. getBoundingRect: function () {
  13543. this._updatePathDirty();
  13544. return Path.prototype.getBoundingRect.call(this);
  13545. }
  13546. });
  13547. /***/ },
  13548. /* 65 */
  13549. /***/ function(module, exports, __webpack_require__) {
  13550. 'use strict';
  13551. var zrUtil = __webpack_require__(4);
  13552. var Gradient = __webpack_require__(66);
  13553. /**
  13554. * x, y, x2, y2 are all percent from 0 to 1
  13555. * @param {number} [x=0]
  13556. * @param {number} [y=0]
  13557. * @param {number} [x2=1]
  13558. * @param {number} [y2=0]
  13559. * @param {Array.<Object>} colorStops
  13560. * @param {boolean} [globalCoord=false]
  13561. */
  13562. var LinearGradient = function (x, y, x2, y2, colorStops, globalCoord) {
  13563. // Should do nothing more in this constructor. Because gradient can be
  13564. // declard by `color: {type: 'linear', colorStops: ...}`, where
  13565. // this constructor will not be called.
  13566. this.x = x == null ? 0 : x;
  13567. this.y = y == null ? 0 : y;
  13568. this.x2 = x2 == null ? 1 : x2;
  13569. this.y2 = y2 == null ? 0 : y2;
  13570. // Can be cloned
  13571. this.type = 'linear';
  13572. // If use global coord
  13573. this.global = globalCoord || false;
  13574. Gradient.call(this, colorStops);
  13575. };
  13576. LinearGradient.prototype = {
  13577. constructor: LinearGradient
  13578. };
  13579. zrUtil.inherits(LinearGradient, Gradient);
  13580. module.exports = LinearGradient;
  13581. /***/ },
  13582. /* 66 */
  13583. /***/ function(module, exports) {
  13584. /**
  13585. * @param {Array.<Object>} colorStops
  13586. */
  13587. var Gradient = function (colorStops) {
  13588. this.colorStops = colorStops || [];
  13589. };
  13590. Gradient.prototype = {
  13591. constructor: Gradient,
  13592. addColorStop: function (offset, color) {
  13593. this.colorStops.push({
  13594. offset: offset,
  13595. color: color
  13596. });
  13597. }
  13598. };
  13599. module.exports = Gradient;
  13600. /***/ },
  13601. /* 67 */
  13602. /***/ function(module, exports, __webpack_require__) {
  13603. 'use strict';
  13604. var zrUtil = __webpack_require__(4);
  13605. var Gradient = __webpack_require__(66);
  13606. /**
  13607. * x, y, r are all percent from 0 to 1
  13608. * @param {number} [x=0.5]
  13609. * @param {number} [y=0.5]
  13610. * @param {number} [r=0.5]
  13611. * @param {Array.<Object>} [colorStops]
  13612. * @param {boolean} [globalCoord=false]
  13613. */
  13614. var RadialGradient = function (x, y, r, colorStops, globalCoord) {
  13615. // Should do nothing more in this constructor. Because gradient can be
  13616. // declard by `color: {type: 'radial', colorStops: ...}`, where
  13617. // this constructor will not be called.
  13618. this.x = x == null ? 0.5 : x;
  13619. this.y = y == null ? 0.5 : y;
  13620. this.r = r == null ? 0.5 : r;
  13621. // Can be cloned
  13622. this.type = 'radial';
  13623. // If use global coord
  13624. this.global = globalCoord || false;
  13625. Gradient.call(this, colorStops);
  13626. };
  13627. RadialGradient.prototype = {
  13628. constructor: RadialGradient
  13629. };
  13630. zrUtil.inherits(RadialGradient, Gradient);
  13631. module.exports = RadialGradient;
  13632. /***/ },
  13633. /* 68 */
  13634. /***/ function(module, exports, __webpack_require__) {
  13635. var getItemStyle = __webpack_require__(15)(
  13636. [
  13637. ['fill', 'color'],
  13638. ['stroke', 'borderColor'],
  13639. ['lineWidth', 'borderWidth'],
  13640. ['opacity'],
  13641. ['shadowBlur'],
  13642. ['shadowOffsetX'],
  13643. ['shadowOffsetY'],
  13644. ['shadowColor'],
  13645. ['textPosition'],
  13646. ['textAlign']
  13647. ]
  13648. );
  13649. module.exports = {
  13650. getItemStyle: function (excludes, includes) {
  13651. var style = getItemStyle.call(this, excludes, includes);
  13652. var lineDash = this.getBorderLineDash();
  13653. lineDash && (style.lineDash = lineDash);
  13654. return style;
  13655. },
  13656. getBorderLineDash: function () {
  13657. var lineType = this.get('borderType');
  13658. return (lineType === 'solid' || lineType == null) ? null
  13659. : (lineType === 'dashed' ? [5, 5] : [1, 1]);
  13660. }
  13661. };
  13662. /***/ },
  13663. /* 69 */
  13664. /***/ function(module, exports, __webpack_require__) {
  13665. /**
  13666. * Component model
  13667. *
  13668. * @module echarts/model/Component
  13669. */
  13670. var Model = __webpack_require__(12);
  13671. var zrUtil = __webpack_require__(4);
  13672. var arrayPush = Array.prototype.push;
  13673. var componentUtil = __webpack_require__(70);
  13674. var clazzUtil = __webpack_require__(13);
  13675. var layout = __webpack_require__(71);
  13676. /**
  13677. * @alias module:echarts/model/Component
  13678. * @constructor
  13679. * @param {Object} option
  13680. * @param {module:echarts/model/Model} parentModel
  13681. * @param {module:echarts/model/Model} ecModel
  13682. */
  13683. var ComponentModel = Model.extend({
  13684. type: 'component',
  13685. /**
  13686. * @readOnly
  13687. * @type {string}
  13688. */
  13689. id: '',
  13690. /**
  13691. * @readOnly
  13692. */
  13693. name: '',
  13694. /**
  13695. * @readOnly
  13696. * @type {string}
  13697. */
  13698. mainType: '',
  13699. /**
  13700. * @readOnly
  13701. * @type {string}
  13702. */
  13703. subType: '',
  13704. /**
  13705. * @readOnly
  13706. * @type {number}
  13707. */
  13708. componentIndex: 0,
  13709. /**
  13710. * @type {Object}
  13711. * @protected
  13712. */
  13713. defaultOption: null,
  13714. /**
  13715. * @type {module:echarts/model/Global}
  13716. * @readOnly
  13717. */
  13718. ecModel: null,
  13719. /**
  13720. * key: componentType
  13721. * value: Component model list, can not be null.
  13722. * @type {Object.<string, Array.<module:echarts/model/Model>>}
  13723. * @readOnly
  13724. */
  13725. dependentModels: [],
  13726. /**
  13727. * @type {string}
  13728. * @readOnly
  13729. */
  13730. uid: null,
  13731. /**
  13732. * Support merge layout params.
  13733. * Only support 'box' now (left/right/top/bottom/width/height).
  13734. * @type {string|Object} Object can be {ignoreSize: true}
  13735. * @readOnly
  13736. */
  13737. layoutMode: null,
  13738. $constructor: function (option, parentModel, ecModel, extraOpt) {
  13739. Model.call(this, option, parentModel, ecModel, extraOpt);
  13740. this.uid = componentUtil.getUID('componentModel');
  13741. },
  13742. init: function (option, parentModel, ecModel, extraOpt) {
  13743. this.mergeDefaultAndTheme(option, ecModel);
  13744. },
  13745. mergeDefaultAndTheme: function (option, ecModel) {
  13746. var layoutMode = this.layoutMode;
  13747. var inputPositionParams = layoutMode
  13748. ? layout.getLayoutParams(option) : {};
  13749. var themeModel = ecModel.getTheme();
  13750. zrUtil.merge(option, themeModel.get(this.mainType));
  13751. zrUtil.merge(option, this.getDefaultOption());
  13752. if (layoutMode) {
  13753. layout.mergeLayoutParam(option, inputPositionParams, layoutMode);
  13754. }
  13755. },
  13756. mergeOption: function (option, extraOpt) {
  13757. zrUtil.merge(this.option, option, true);
  13758. var layoutMode = this.layoutMode;
  13759. if (layoutMode) {
  13760. layout.mergeLayoutParam(this.option, option, layoutMode);
  13761. }
  13762. },
  13763. // Hooker after init or mergeOption
  13764. optionUpdated: function (newCptOption, isInit) {},
  13765. getDefaultOption: function () {
  13766. if (!clazzUtil.hasOwn(this, '__defaultOption')) {
  13767. var optList = [];
  13768. var Class = this.constructor;
  13769. while (Class) {
  13770. var opt = Class.prototype.defaultOption;
  13771. opt && optList.push(opt);
  13772. Class = Class.superClass;
  13773. }
  13774. var defaultOption = {};
  13775. for (var i = optList.length - 1; i >= 0; i--) {
  13776. defaultOption = zrUtil.merge(defaultOption, optList[i], true);
  13777. }
  13778. clazzUtil.set(this, '__defaultOption', defaultOption);
  13779. }
  13780. return clazzUtil.get(this, '__defaultOption');
  13781. },
  13782. getReferringComponents: function (mainType) {
  13783. return this.ecModel.queryComponents({
  13784. mainType: mainType,
  13785. index: this.get(mainType + 'Index', true),
  13786. id: this.get(mainType + 'Id', true)
  13787. });
  13788. }
  13789. });
  13790. // Reset ComponentModel.extend, add preConstruct.
  13791. // clazzUtil.enableClassExtend(
  13792. // ComponentModel,
  13793. // function (option, parentModel, ecModel, extraOpt) {
  13794. // // Set dependentModels, componentIndex, name, id, mainType, subType.
  13795. // zrUtil.extend(this, extraOpt);
  13796. // this.uid = componentUtil.getUID('componentModel');
  13797. // // this.setReadOnly([
  13798. // // 'type', 'id', 'uid', 'name', 'mainType', 'subType',
  13799. // // 'dependentModels', 'componentIndex'
  13800. // // ]);
  13801. // }
  13802. // );
  13803. // Add capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on.
  13804. clazzUtil.enableClassManagement(
  13805. ComponentModel, {registerWhenExtend: true}
  13806. );
  13807. componentUtil.enableSubTypeDefaulter(ComponentModel);
  13808. // Add capability of ComponentModel.topologicalTravel.
  13809. componentUtil.enableTopologicalTravel(ComponentModel, getDependencies);
  13810. function getDependencies(componentType) {
  13811. var deps = [];
  13812. zrUtil.each(ComponentModel.getClassesByMainType(componentType), function (Clazz) {
  13813. arrayPush.apply(deps, Clazz.prototype.dependencies || []);
  13814. });
  13815. // Ensure main type
  13816. return zrUtil.map(deps, function (type) {
  13817. return clazzUtil.parseClassType(type).main;
  13818. });
  13819. }
  13820. zrUtil.mixin(ComponentModel, __webpack_require__(72));
  13821. module.exports = ComponentModel;
  13822. /***/ },
  13823. /* 70 */
  13824. /***/ function(module, exports, __webpack_require__) {
  13825. var zrUtil = __webpack_require__(4);
  13826. var clazz = __webpack_require__(13);
  13827. var parseClassType = clazz.parseClassType;
  13828. var base = 0;
  13829. var componentUtil = {};
  13830. var DELIMITER = '_';
  13831. /**
  13832. * @public
  13833. * @param {string} type
  13834. * @return {string}
  13835. */
  13836. componentUtil.getUID = function (type) {
  13837. // Considering the case of crossing js context,
  13838. // use Math.random to make id as unique as possible.
  13839. return [(type || ''), base++, Math.random()].join(DELIMITER);
  13840. };
  13841. /**
  13842. * @inner
  13843. */
  13844. componentUtil.enableSubTypeDefaulter = function (entity) {
  13845. var subTypeDefaulters = {};
  13846. entity.registerSubTypeDefaulter = function (componentType, defaulter) {
  13847. componentType = parseClassType(componentType);
  13848. subTypeDefaulters[componentType.main] = defaulter;
  13849. };
  13850. entity.determineSubType = function (componentType, option) {
  13851. var type = option.type;
  13852. if (!type) {
  13853. var componentTypeMain = parseClassType(componentType).main;
  13854. if (entity.hasSubTypes(componentType) && subTypeDefaulters[componentTypeMain]) {
  13855. type = subTypeDefaulters[componentTypeMain](option);
  13856. }
  13857. }
  13858. return type;
  13859. };
  13860. return entity;
  13861. };
  13862. /**
  13863. * Topological travel on Activity Network (Activity On Vertices).
  13864. * Dependencies is defined in Model.prototype.dependencies, like ['xAxis', 'yAxis'].
  13865. *
  13866. * If 'xAxis' or 'yAxis' is absent in componentTypeList, just ignore it in topology.
  13867. *
  13868. * If there is circle dependencey, Error will be thrown.
  13869. *
  13870. */
  13871. componentUtil.enableTopologicalTravel = function (entity, dependencyGetter) {
  13872. /**
  13873. * @public
  13874. * @param {Array.<string>} targetNameList Target Component type list.
  13875. * Can be ['aa', 'bb', 'aa.xx']
  13876. * @param {Array.<string>} fullNameList By which we can build dependency graph.
  13877. * @param {Function} callback Params: componentType, dependencies.
  13878. * @param {Object} context Scope of callback.
  13879. */
  13880. entity.topologicalTravel = function (targetNameList, fullNameList, callback, context) {
  13881. if (!targetNameList.length) {
  13882. return;
  13883. }
  13884. var result = makeDepndencyGraph(fullNameList);
  13885. var graph = result.graph;
  13886. var stack = result.noEntryList;
  13887. var targetNameSet = {};
  13888. zrUtil.each(targetNameList, function (name) {
  13889. targetNameSet[name] = true;
  13890. });
  13891. while (stack.length) {
  13892. var currComponentType = stack.pop();
  13893. var currVertex = graph[currComponentType];
  13894. var isInTargetNameSet = !!targetNameSet[currComponentType];
  13895. if (isInTargetNameSet) {
  13896. callback.call(context, currComponentType, currVertex.originalDeps.slice());
  13897. delete targetNameSet[currComponentType];
  13898. }
  13899. zrUtil.each(
  13900. currVertex.successor,
  13901. isInTargetNameSet ? removeEdgeAndAdd : removeEdge
  13902. );
  13903. }
  13904. zrUtil.each(targetNameSet, function () {
  13905. throw new Error('Circle dependency may exists');
  13906. });
  13907. function removeEdge(succComponentType) {
  13908. graph[succComponentType].entryCount--;
  13909. if (graph[succComponentType].entryCount === 0) {
  13910. stack.push(succComponentType);
  13911. }
  13912. }
  13913. // Consider this case: legend depends on series, and we call
  13914. // chart.setOption({series: [...]}), where only series is in option.
  13915. // If we do not have 'removeEdgeAndAdd', legendModel.mergeOption will
  13916. // not be called, but only sereis.mergeOption is called. Thus legend
  13917. // have no chance to update its local record about series (like which
  13918. // name of series is available in legend).
  13919. function removeEdgeAndAdd(succComponentType) {
  13920. targetNameSet[succComponentType] = true;
  13921. removeEdge(succComponentType);
  13922. }
  13923. };
  13924. /**
  13925. * DepndencyGraph: {Object}
  13926. * key: conponentType,
  13927. * value: {
  13928. * successor: [conponentTypes...],
  13929. * originalDeps: [conponentTypes...],
  13930. * entryCount: {number}
  13931. * }
  13932. */
  13933. function makeDepndencyGraph(fullNameList) {
  13934. var graph = {};
  13935. var noEntryList = [];
  13936. zrUtil.each(fullNameList, function (name) {
  13937. var thisItem = createDependencyGraphItem(graph, name);
  13938. var originalDeps = thisItem.originalDeps = dependencyGetter(name);
  13939. var availableDeps = getAvailableDependencies(originalDeps, fullNameList);
  13940. thisItem.entryCount = availableDeps.length;
  13941. if (thisItem.entryCount === 0) {
  13942. noEntryList.push(name);
  13943. }
  13944. zrUtil.each(availableDeps, function (dependentName) {
  13945. if (zrUtil.indexOf(thisItem.predecessor, dependentName) < 0) {
  13946. thisItem.predecessor.push(dependentName);
  13947. }
  13948. var thatItem = createDependencyGraphItem(graph, dependentName);
  13949. if (zrUtil.indexOf(thatItem.successor, dependentName) < 0) {
  13950. thatItem.successor.push(name);
  13951. }
  13952. });
  13953. });
  13954. return {graph: graph, noEntryList: noEntryList};
  13955. }
  13956. function createDependencyGraphItem(graph, name) {
  13957. if (!graph[name]) {
  13958. graph[name] = {predecessor: [], successor: []};
  13959. }
  13960. return graph[name];
  13961. }
  13962. function getAvailableDependencies(originalDeps, fullNameList) {
  13963. var availableDeps = [];
  13964. zrUtil.each(originalDeps, function (dep) {
  13965. zrUtil.indexOf(fullNameList, dep) >= 0 && availableDeps.push(dep);
  13966. });
  13967. return availableDeps;
  13968. }
  13969. };
  13970. module.exports = componentUtil;
  13971. /***/ },
  13972. /* 71 */
  13973. /***/ function(module, exports, __webpack_require__) {
  13974. 'use strict';
  13975. // Layout helpers for each component positioning
  13976. var zrUtil = __webpack_require__(4);
  13977. var BoundingRect = __webpack_require__(9);
  13978. var numberUtil = __webpack_require__(7);
  13979. var formatUtil = __webpack_require__(6);
  13980. var parsePercent = numberUtil.parsePercent;
  13981. var each = zrUtil.each;
  13982. var layout = {};
  13983. /**
  13984. * @public
  13985. */
  13986. var LOCATION_PARAMS = layout.LOCATION_PARAMS = [
  13987. 'left', 'right', 'top', 'bottom', 'width', 'height'
  13988. ];
  13989. /**
  13990. * @public
  13991. */
  13992. var HV_NAMES = layout.HV_NAMES = [
  13993. ['width', 'left', 'right'],
  13994. ['height', 'top', 'bottom']
  13995. ];
  13996. function boxLayout(orient, group, gap, maxWidth, maxHeight) {
  13997. var x = 0;
  13998. var y = 0;
  13999. if (maxWidth == null) {
  14000. maxWidth = Infinity;
  14001. }
  14002. if (maxHeight == null) {
  14003. maxHeight = Infinity;
  14004. }
  14005. var currentLineMaxSize = 0;
  14006. group.eachChild(function (child, idx) {
  14007. var position = child.position;
  14008. var rect = child.getBoundingRect();
  14009. var nextChild = group.childAt(idx + 1);
  14010. var nextChildRect = nextChild && nextChild.getBoundingRect();
  14011. var nextX;
  14012. var nextY;
  14013. if (orient === 'horizontal') {
  14014. var moveX = rect.width + (nextChildRect ? (-nextChildRect.x + rect.x) : 0);
  14015. nextX = x + moveX;
  14016. // Wrap when width exceeds maxWidth or meet a `newline` group
  14017. if (nextX > maxWidth || child.newline) {
  14018. x = 0;
  14019. nextX = moveX;
  14020. y += currentLineMaxSize + gap;
  14021. currentLineMaxSize = rect.height;
  14022. }
  14023. else {
  14024. currentLineMaxSize = Math.max(currentLineMaxSize, rect.height);
  14025. }
  14026. }
  14027. else {
  14028. var moveY = rect.height + (nextChildRect ? (-nextChildRect.y + rect.y) : 0);
  14029. nextY = y + moveY;
  14030. // Wrap when width exceeds maxHeight or meet a `newline` group
  14031. if (nextY > maxHeight || child.newline) {
  14032. x += currentLineMaxSize + gap;
  14033. y = 0;
  14034. nextY = moveY;
  14035. currentLineMaxSize = rect.width;
  14036. }
  14037. else {
  14038. currentLineMaxSize = Math.max(currentLineMaxSize, rect.width);
  14039. }
  14040. }
  14041. if (child.newline) {
  14042. return;
  14043. }
  14044. position[0] = x;
  14045. position[1] = y;
  14046. orient === 'horizontal'
  14047. ? (x = nextX + gap)
  14048. : (y = nextY + gap);
  14049. });
  14050. }
  14051. /**
  14052. * VBox or HBox layouting
  14053. * @param {string} orient
  14054. * @param {module:zrender/container/Group} group
  14055. * @param {number} gap
  14056. * @param {number} [width=Infinity]
  14057. * @param {number} [height=Infinity]
  14058. */
  14059. layout.box = boxLayout;
  14060. /**
  14061. * VBox layouting
  14062. * @param {module:zrender/container/Group} group
  14063. * @param {number} gap
  14064. * @param {number} [width=Infinity]
  14065. * @param {number} [height=Infinity]
  14066. */
  14067. layout.vbox = zrUtil.curry(boxLayout, 'vertical');
  14068. /**
  14069. * HBox layouting
  14070. * @param {module:zrender/container/Group} group
  14071. * @param {number} gap
  14072. * @param {number} [width=Infinity]
  14073. * @param {number} [height=Infinity]
  14074. */
  14075. layout.hbox = zrUtil.curry(boxLayout, 'horizontal');
  14076. /**
  14077. * If x or x2 is not specified or 'center' 'left' 'right',
  14078. * the width would be as long as possible.
  14079. * If y or y2 is not specified or 'middle' 'top' 'bottom',
  14080. * the height would be as long as possible.
  14081. *
  14082. * @param {Object} positionInfo
  14083. * @param {number|string} [positionInfo.x]
  14084. * @param {number|string} [positionInfo.y]
  14085. * @param {number|string} [positionInfo.x2]
  14086. * @param {number|string} [positionInfo.y2]
  14087. * @param {Object} containerRect
  14088. * @param {string|number} margin
  14089. * @return {Object} {width, height}
  14090. */
  14091. layout.getAvailableSize = function (positionInfo, containerRect, margin) {
  14092. var containerWidth = containerRect.width;
  14093. var containerHeight = containerRect.height;
  14094. var x = parsePercent(positionInfo.x, containerWidth);
  14095. var y = parsePercent(positionInfo.y, containerHeight);
  14096. var x2 = parsePercent(positionInfo.x2, containerWidth);
  14097. var y2 = parsePercent(positionInfo.y2, containerHeight);
  14098. (isNaN(x) || isNaN(parseFloat(positionInfo.x))) && (x = 0);
  14099. (isNaN(x2) || isNaN(parseFloat(positionInfo.x2))) && (x2 = containerWidth);
  14100. (isNaN(y) || isNaN(parseFloat(positionInfo.y))) && (y = 0);
  14101. (isNaN(y2) || isNaN(parseFloat(positionInfo.y2))) && (y2 = containerHeight);
  14102. margin = formatUtil.normalizeCssArray(margin || 0);
  14103. return {
  14104. width: Math.max(x2 - x - margin[1] - margin[3], 0),
  14105. height: Math.max(y2 - y - margin[0] - margin[2], 0)
  14106. };
  14107. };
  14108. /**
  14109. * Parse position info.
  14110. *
  14111. * @param {Object} positionInfo
  14112. * @param {number|string} [positionInfo.left]
  14113. * @param {number|string} [positionInfo.top]
  14114. * @param {number|string} [positionInfo.right]
  14115. * @param {number|string} [positionInfo.bottom]
  14116. * @param {number|string} [positionInfo.width]
  14117. * @param {number|string} [positionInfo.height]
  14118. * @param {number|string} [positionInfo.aspect] Aspect is width / height
  14119. * @param {Object} containerRect
  14120. * @param {string|number} [margin]
  14121. *
  14122. * @return {module:zrender/core/BoundingRect}
  14123. */
  14124. layout.getLayoutRect = function (
  14125. positionInfo, containerRect, margin
  14126. ) {
  14127. margin = formatUtil.normalizeCssArray(margin || 0);
  14128. var containerWidth = containerRect.width;
  14129. var containerHeight = containerRect.height;
  14130. var left = parsePercent(positionInfo.left, containerWidth);
  14131. var top = parsePercent(positionInfo.top, containerHeight);
  14132. var right = parsePercent(positionInfo.right, containerWidth);
  14133. var bottom = parsePercent(positionInfo.bottom, containerHeight);
  14134. var width = parsePercent(positionInfo.width, containerWidth);
  14135. var height = parsePercent(positionInfo.height, containerHeight);
  14136. var verticalMargin = margin[2] + margin[0];
  14137. var horizontalMargin = margin[1] + margin[3];
  14138. var aspect = positionInfo.aspect;
  14139. // If width is not specified, calculate width from left and right
  14140. if (isNaN(width)) {
  14141. width = containerWidth - right - horizontalMargin - left;
  14142. }
  14143. if (isNaN(height)) {
  14144. height = containerHeight - bottom - verticalMargin - top;
  14145. }
  14146. // If width and height are not given
  14147. // 1. Graph should not exceeds the container
  14148. // 2. Aspect must be keeped
  14149. // 3. Graph should take the space as more as possible
  14150. if (isNaN(width) && isNaN(height)) {
  14151. if (aspect > containerWidth / containerHeight) {
  14152. width = containerWidth * 0.8;
  14153. }
  14154. else {
  14155. height = containerHeight * 0.8;
  14156. }
  14157. }
  14158. if (aspect != null) {
  14159. // Calculate width or height with given aspect
  14160. if (isNaN(width)) {
  14161. width = aspect * height;
  14162. }
  14163. if (isNaN(height)) {
  14164. height = width / aspect;
  14165. }
  14166. }
  14167. // If left is not specified, calculate left from right and width
  14168. if (isNaN(left)) {
  14169. left = containerWidth - right - width - horizontalMargin;
  14170. }
  14171. if (isNaN(top)) {
  14172. top = containerHeight - bottom - height - verticalMargin;
  14173. }
  14174. // Align left and top
  14175. switch (positionInfo.left || positionInfo.right) {
  14176. case 'center':
  14177. left = containerWidth / 2 - width / 2 - margin[3];
  14178. break;
  14179. case 'right':
  14180. left = containerWidth - width - horizontalMargin;
  14181. break;
  14182. }
  14183. switch (positionInfo.top || positionInfo.bottom) {
  14184. case 'middle':
  14185. case 'center':
  14186. top = containerHeight / 2 - height / 2 - margin[0];
  14187. break;
  14188. case 'bottom':
  14189. top = containerHeight - height - verticalMargin;
  14190. break;
  14191. }
  14192. // If something is wrong and left, top, width, height are calculated as NaN
  14193. left = left || 0;
  14194. top = top || 0;
  14195. if (isNaN(width)) {
  14196. // Width may be NaN if only one value is given except width
  14197. width = containerWidth - left - (right || 0);
  14198. }
  14199. if (isNaN(height)) {
  14200. // Height may be NaN if only one value is given except height
  14201. height = containerHeight - top - (bottom || 0);
  14202. }
  14203. var rect = new BoundingRect(left + margin[3], top + margin[0], width, height);
  14204. rect.margin = margin;
  14205. return rect;
  14206. };
  14207. /**
  14208. * Position a zr element in viewport
  14209. * Group position is specified by either
  14210. * {left, top}, {right, bottom}
  14211. * If all properties exists, right and bottom will be igonred.
  14212. *
  14213. * Logic:
  14214. * 1. Scale (against origin point in parent coord)
  14215. * 2. Rotate (against origin point in parent coord)
  14216. * 3. Traslate (with el.position by this method)
  14217. * So this method only fixes the last step 'Traslate', which does not affect
  14218. * scaling and rotating.
  14219. *
  14220. * If be called repeatly with the same input el, the same result will be gotten.
  14221. *
  14222. * @param {module:zrender/Element} el Should have `getBoundingRect` method.
  14223. * @param {Object} positionInfo
  14224. * @param {number|string} [positionInfo.left]
  14225. * @param {number|string} [positionInfo.top]
  14226. * @param {number|string} [positionInfo.right]
  14227. * @param {number|string} [positionInfo.bottom]
  14228. * @param {Object} containerRect
  14229. * @param {string|number} margin
  14230. * @param {Object} [opt]
  14231. * @param {Array.<number>} [opt.hv=[1,1]] Only horizontal or only vertical.
  14232. * @param {Array.<number>} [opt.boundingMode='all']
  14233. * Specify how to calculate boundingRect when locating.
  14234. * 'all': Position the boundingRect that is transformed and uioned
  14235. * both itself and its descendants.
  14236. * This mode simplies confine the elements in the bounding
  14237. * of their container (e.g., using 'right: 0').
  14238. * 'raw': Position the boundingRect that is not transformed and only itself.
  14239. * This mode is useful when you want a element can overflow its
  14240. * container. (Consider a rotated circle needs to be located in a corner.)
  14241. * In this mode positionInfo.width/height can only be number.
  14242. */
  14243. layout.positionElement = function (el, positionInfo, containerRect, margin, opt) {
  14244. var h = !opt || !opt.hv || opt.hv[0];
  14245. var v = !opt || !opt.hv || opt.hv[1];
  14246. var boundingMode = opt && opt.boundingMode || 'all';
  14247. if (!h && !v) {
  14248. return;
  14249. }
  14250. var rect;
  14251. if (boundingMode === 'raw') {
  14252. rect = el.type === 'group'
  14253. ? new BoundingRect(0, 0, +positionInfo.width || 0, +positionInfo.height || 0)
  14254. : el.getBoundingRect();
  14255. }
  14256. else {
  14257. rect = el.getBoundingRect();
  14258. if (el.needLocalTransform()) {
  14259. var transform = el.getLocalTransform();
  14260. // Notice: raw rect may be inner object of el,
  14261. // which should not be modified.
  14262. rect = rect.clone();
  14263. rect.applyTransform(transform);
  14264. }
  14265. }
  14266. positionInfo = layout.getLayoutRect(
  14267. zrUtil.defaults(
  14268. {width: rect.width, height: rect.height},
  14269. positionInfo
  14270. ),
  14271. containerRect,
  14272. margin
  14273. );
  14274. // Because 'tranlate' is the last step in transform
  14275. // (see zrender/core/Transformable#getLocalTransfrom),
  14276. // we can just only modify el.position to get final result.
  14277. var elPos = el.position;
  14278. var dx = h ? positionInfo.x - rect.x : 0;
  14279. var dy = v ? positionInfo.y - rect.y : 0;
  14280. el.attr('position', boundingMode === 'raw' ? [dx, dy] : [elPos[0] + dx, elPos[1] + dy]);
  14281. };
  14282. /**
  14283. * @param {Object} option Contains some of the properties in HV_NAMES.
  14284. * @param {number} hvIdx 0: horizontal; 1: vertical.
  14285. */
  14286. layout.sizeCalculable = function (option, hvIdx) {
  14287. return option[HV_NAMES[hvIdx][0]] != null
  14288. || (option[HV_NAMES[hvIdx][1]] != null && option[HV_NAMES[hvIdx][2]] != null);
  14289. };
  14290. /**
  14291. * Consider Case:
  14292. * When defulat option has {left: 0, width: 100}, and we set {right: 0}
  14293. * through setOption or media query, using normal zrUtil.merge will cause
  14294. * {right: 0} does not take effect.
  14295. *
  14296. * @example
  14297. * ComponentModel.extend({
  14298. * init: function () {
  14299. * ...
  14300. * var inputPositionParams = layout.getLayoutParams(option);
  14301. * this.mergeOption(inputPositionParams);
  14302. * },
  14303. * mergeOption: function (newOption) {
  14304. * newOption && zrUtil.merge(thisOption, newOption, true);
  14305. * layout.mergeLayoutParam(thisOption, newOption);
  14306. * }
  14307. * });
  14308. *
  14309. * @param {Object} targetOption
  14310. * @param {Object} newOption
  14311. * @param {Object|string} [opt]
  14312. * @param {boolean|Array.<boolean>} [opt.ignoreSize=false] Some component must has width and height.
  14313. */
  14314. layout.mergeLayoutParam = function (targetOption, newOption, opt) {
  14315. !zrUtil.isObject(opt) && (opt = {});
  14316. var ignoreSize = opt.ignoreSize;
  14317. !zrUtil.isArray(ignoreSize) && (ignoreSize = [ignoreSize, ignoreSize]);
  14318. var hResult = merge(HV_NAMES[0], 0);
  14319. var vResult = merge(HV_NAMES[1], 1);
  14320. copy(HV_NAMES[0], targetOption, hResult);
  14321. copy(HV_NAMES[1], targetOption, vResult);
  14322. function merge(names, hvIdx) {
  14323. var newParams = {};
  14324. var newValueCount = 0;
  14325. var merged = {};
  14326. var mergedValueCount = 0;
  14327. var enoughParamNumber = 2;
  14328. each(names, function (name) {
  14329. merged[name] = targetOption[name];
  14330. });
  14331. each(names, function (name) {
  14332. // Consider case: newOption.width is null, which is
  14333. // set by user for removing width setting.
  14334. hasProp(newOption, name) && (newParams[name] = merged[name] = newOption[name]);
  14335. hasValue(newParams, name) && newValueCount++;
  14336. hasValue(merged, name) && mergedValueCount++;
  14337. });
  14338. if (ignoreSize[hvIdx]) {
  14339. // Only one of left/right is premitted to exist.
  14340. if (hasValue(newOption, names[1])) {
  14341. merged[names[2]] = null;
  14342. }
  14343. else if (hasValue(newOption, names[2])) {
  14344. merged[names[1]] = null;
  14345. }
  14346. return merged;
  14347. }
  14348. // Case: newOption: {width: ..., right: ...},
  14349. // or targetOption: {right: ...} and newOption: {width: ...},
  14350. // There is no conflict when merged only has params count
  14351. // little than enoughParamNumber.
  14352. if (mergedValueCount === enoughParamNumber || !newValueCount) {
  14353. return merged;
  14354. }
  14355. // Case: newOption: {width: ..., right: ...},
  14356. // Than we can make sure user only want those two, and ignore
  14357. // all origin params in targetOption.
  14358. else if (newValueCount >= enoughParamNumber) {
  14359. return newParams;
  14360. }
  14361. else {
  14362. // Chose another param from targetOption by priority.
  14363. for (var i = 0; i < names.length; i++) {
  14364. var name = names[i];
  14365. if (!hasProp(newParams, name) && hasProp(targetOption, name)) {
  14366. newParams[name] = targetOption[name];
  14367. break;
  14368. }
  14369. }
  14370. return newParams;
  14371. }
  14372. }
  14373. function hasProp(obj, name) {
  14374. return obj.hasOwnProperty(name);
  14375. }
  14376. function hasValue(obj, name) {
  14377. return obj[name] != null && obj[name] !== 'auto';
  14378. }
  14379. function copy(names, target, source) {
  14380. each(names, function (name) {
  14381. target[name] = source[name];
  14382. });
  14383. }
  14384. };
  14385. /**
  14386. * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object.
  14387. * @param {Object} source
  14388. * @return {Object} Result contains those props.
  14389. */
  14390. layout.getLayoutParams = function (source) {
  14391. return layout.copyLayoutParams({}, source);
  14392. };
  14393. /**
  14394. * Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object.
  14395. * @param {Object} source
  14396. * @return {Object} Result contains those props.
  14397. */
  14398. layout.copyLayoutParams = function (target, source) {
  14399. source && target && each(LOCATION_PARAMS, function (name) {
  14400. source.hasOwnProperty(name) && (target[name] = source[name]);
  14401. });
  14402. return target;
  14403. };
  14404. module.exports = layout;
  14405. /***/ },
  14406. /* 72 */
  14407. /***/ function(module, exports) {
  14408. module.exports = {
  14409. getBoxLayoutParams: function () {
  14410. return {
  14411. left: this.get('left'),
  14412. top: this.get('top'),
  14413. right: this.get('right'),
  14414. bottom: this.get('bottom'),
  14415. width: this.get('width'),
  14416. height: this.get('height')
  14417. };
  14418. }
  14419. };
  14420. /***/ },
  14421. /* 73 */
  14422. /***/ function(module, exports) {
  14423. var platform = '';
  14424. // Navigator not exists in node
  14425. if (typeof navigator !== 'undefined') {
  14426. platform = navigator.platform || '';
  14427. }
  14428. module.exports = {
  14429. // 全图默认背景
  14430. // backgroundColor: 'rgba(0,0,0,0)',
  14431. // https://dribbble.com/shots/1065960-Infographic-Pie-chart-visualization
  14432. // color: ['#5793f3', '#d14a61', '#fd9c35', '#675bba', '#fec42c', '#dd4444', '#d4df5a', '#cd4870'],
  14433. // 浅色
  14434. // color: ['#bcd3bb', '#e88f70', '#edc1a5', '#9dc5c8', '#e1e8c8', '#7b7c68', '#e5b5b5', '#f0b489', '#928ea8', '#bda29a'],
  14435. // color: ['#cc5664', '#9bd6ec', '#ea946e', '#8acaaa', '#f1ec64', '#ee8686', '#a48dc1', '#5da6bc', '#b9dcae'],
  14436. // 深色
  14437. color: ['#c23531','#2f4554', '#61a0a8', '#d48265', '#91c7ae','#749f83', '#ca8622', '#bda29a','#6e7074', '#546570', '#c4ccd3'],
  14438. // 默认需要 Grid 配置项
  14439. // grid: {},
  14440. // 主题,主题
  14441. textStyle: {
  14442. // color: '#000',
  14443. // decoration: 'none',
  14444. // PENDING
  14445. fontFamily: platform.match(/^Win/) ? 'Microsoft YaHei' : 'sans-serif',
  14446. // fontFamily: 'Arial, Verdana, sans-serif',
  14447. fontSize: 12,
  14448. fontStyle: 'normal',
  14449. fontWeight: 'normal'
  14450. },
  14451. // http://blogs.adobe.com/webplatform/2014/02/24/using-blend-modes-in-html-canvas/
  14452. // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
  14453. // Default is source-over
  14454. blendMode: null,
  14455. animation: 'auto',
  14456. animationDuration: 1000,
  14457. animationDurationUpdate: 300,
  14458. animationEasing: 'exponentialOut',
  14459. animationEasingUpdate: 'cubicOut',
  14460. animationThreshold: 2000,
  14461. // Configuration for progressive/incremental rendering
  14462. progressiveThreshold: 3000,
  14463. progressive: 400,
  14464. // Threshold of if use single hover layer to optimize.
  14465. // It is recommended that `hoverLayerThreshold` is equivalent to or less than
  14466. // `progressiveThreshold`, otherwise hover will cause restart of progressive,
  14467. // which is unexpected.
  14468. // see example <echarts/test/heatmap-large.html>.
  14469. hoverLayerThreshold: 3000,
  14470. // See: module:echarts/scale/Time
  14471. useUTC: false
  14472. };
  14473. /***/ },
  14474. /* 74 */
  14475. /***/ function(module, exports, __webpack_require__) {
  14476. var classUtil = __webpack_require__(13);
  14477. var set = classUtil.set;
  14478. var get = classUtil.get;
  14479. module.exports = {
  14480. clearColorPalette: function () {
  14481. set(this, 'colorIdx', 0);
  14482. set(this, 'colorNameMap', {});
  14483. },
  14484. getColorFromPalette: function (name, scope) {
  14485. scope = scope || this;
  14486. var colorIdx = get(scope, 'colorIdx') || 0;
  14487. var colorNameMap = get(scope, 'colorNameMap') || set(scope, 'colorNameMap', {});
  14488. // Use `hasOwnProperty` to avoid conflict with Object.prototype.
  14489. if (colorNameMap.hasOwnProperty(name)) {
  14490. return colorNameMap[name];
  14491. }
  14492. var colorPalette = this.get('color', true) || [];
  14493. if (!colorPalette.length) {
  14494. return;
  14495. }
  14496. var color = colorPalette[colorIdx];
  14497. if (name) {
  14498. colorNameMap[name] = color;
  14499. }
  14500. set(scope, 'colorIdx', (colorIdx + 1) % colorPalette.length);
  14501. return color;
  14502. }
  14503. };
  14504. /***/ },
  14505. /* 75 */
  14506. /***/ function(module, exports, __webpack_require__) {
  14507. 'use strict';
  14508. var zrUtil = __webpack_require__(4);
  14509. var echartsAPIList = [
  14510. 'getDom', 'getZr', 'getWidth', 'getHeight', 'getDevicePixelRatio', 'dispatchAction', 'isDisposed',
  14511. 'on', 'off', 'getDataURL', 'getConnectedDataURL', 'getModel', 'getOption',
  14512. 'getViewOfComponentModel', 'getViewOfSeriesModel'
  14513. ];
  14514. // And `getCoordinateSystems` and `getComponentByElement` will be injected in echarts.js
  14515. function ExtensionAPI(chartInstance) {
  14516. zrUtil.each(echartsAPIList, function (name) {
  14517. this[name] = zrUtil.bind(chartInstance[name], chartInstance);
  14518. }, this);
  14519. }
  14520. module.exports = ExtensionAPI;
  14521. /***/ },
  14522. /* 76 */
  14523. /***/ function(module, exports, __webpack_require__) {
  14524. 'use strict';
  14525. var zrUtil = __webpack_require__(4);
  14526. var coordinateSystemCreators = {};
  14527. function CoordinateSystemManager() {
  14528. this._coordinateSystems = [];
  14529. }
  14530. CoordinateSystemManager.prototype = {
  14531. constructor: CoordinateSystemManager,
  14532. create: function (ecModel, api) {
  14533. var coordinateSystems = [];
  14534. zrUtil.each(coordinateSystemCreators, function (creater, type) {
  14535. var list = creater.create(ecModel, api);
  14536. coordinateSystems = coordinateSystems.concat(list || []);
  14537. });
  14538. this._coordinateSystems = coordinateSystems;
  14539. },
  14540. update: function (ecModel, api) {
  14541. zrUtil.each(this._coordinateSystems, function (coordSys) {
  14542. // FIXME MUST have
  14543. coordSys.update && coordSys.update(ecModel, api);
  14544. });
  14545. },
  14546. getCoordinateSystems: function () {
  14547. return this._coordinateSystems.slice();
  14548. }
  14549. };
  14550. CoordinateSystemManager.register = function (type, coordinateSystemCreator) {
  14551. coordinateSystemCreators[type] = coordinateSystemCreator;
  14552. };
  14553. CoordinateSystemManager.get = function (type) {
  14554. return coordinateSystemCreators[type];
  14555. };
  14556. module.exports = CoordinateSystemManager;
  14557. /***/ },
  14558. /* 77 */
  14559. /***/ function(module, exports, __webpack_require__) {
  14560. /**
  14561. * ECharts option manager
  14562. *
  14563. * @module {echarts/model/OptionManager}
  14564. */
  14565. var zrUtil = __webpack_require__(4);
  14566. var modelUtil = __webpack_require__(5);
  14567. var ComponentModel = __webpack_require__(69);
  14568. var each = zrUtil.each;
  14569. var clone = zrUtil.clone;
  14570. var map = zrUtil.map;
  14571. var merge = zrUtil.merge;
  14572. var QUERY_REG = /^(min|max)?(.+)$/;
  14573. /**
  14574. * TERM EXPLANATIONS:
  14575. *
  14576. * [option]:
  14577. *
  14578. * An object that contains definitions of components. For example:
  14579. * var option = {
  14580. * title: {...},
  14581. * legend: {...},
  14582. * visualMap: {...},
  14583. * series: [
  14584. * {data: [...]},
  14585. * {data: [...]},
  14586. * ...
  14587. * ]
  14588. * };
  14589. *
  14590. * [rawOption]:
  14591. *
  14592. * An object input to echarts.setOption. 'rawOption' may be an
  14593. * 'option', or may be an object contains multi-options. For example:
  14594. * var option = {
  14595. * baseOption: {
  14596. * title: {...},
  14597. * legend: {...},
  14598. * series: [
  14599. * {data: [...]},
  14600. * {data: [...]},
  14601. * ...
  14602. * ]
  14603. * },
  14604. * timeline: {...},
  14605. * options: [
  14606. * {title: {...}, series: {data: [...]}},
  14607. * {title: {...}, series: {data: [...]}},
  14608. * ...
  14609. * ],
  14610. * media: [
  14611. * {
  14612. * query: {maxWidth: 320},
  14613. * option: {series: {x: 20}, visualMap: {show: false}}
  14614. * },
  14615. * {
  14616. * query: {minWidth: 320, maxWidth: 720},
  14617. * option: {series: {x: 500}, visualMap: {show: true}}
  14618. * },
  14619. * {
  14620. * option: {series: {x: 1200}, visualMap: {show: true}}
  14621. * }
  14622. * ]
  14623. * };
  14624. *
  14625. * @alias module:echarts/model/OptionManager
  14626. * @param {module:echarts/ExtensionAPI} api
  14627. */
  14628. function OptionManager(api) {
  14629. /**
  14630. * @private
  14631. * @type {module:echarts/ExtensionAPI}
  14632. */
  14633. this._api = api;
  14634. /**
  14635. * @private
  14636. * @type {Array.<number>}
  14637. */
  14638. this._timelineOptions = [];
  14639. /**
  14640. * @private
  14641. * @type {Array.<Object>}
  14642. */
  14643. this._mediaList = [];
  14644. /**
  14645. * @private
  14646. * @type {Object}
  14647. */
  14648. this._mediaDefault;
  14649. /**
  14650. * -1, means default.
  14651. * empty means no media.
  14652. * @private
  14653. * @type {Array.<number>}
  14654. */
  14655. this._currentMediaIndices = [];
  14656. /**
  14657. * @private
  14658. * @type {Object}
  14659. */
  14660. this._optionBackup;
  14661. /**
  14662. * @private
  14663. * @type {Object}
  14664. */
  14665. this._newBaseOption;
  14666. }
  14667. // timeline.notMerge is not supported in ec3. Firstly there is rearly
  14668. // case that notMerge is needed. Secondly supporting 'notMerge' requires
  14669. // rawOption cloned and backuped when timeline changed, which does no
  14670. // good to performance. What's more, that both timeline and setOption
  14671. // method supply 'notMerge' brings complex and some problems.
  14672. // Consider this case:
  14673. // (step1) chart.setOption({timeline: {notMerge: false}, ...}, false);
  14674. // (step2) chart.setOption({timeline: {notMerge: true}, ...}, false);
  14675. OptionManager.prototype = {
  14676. constructor: OptionManager,
  14677. /**
  14678. * @public
  14679. * @param {Object} rawOption Raw option.
  14680. * @param {module:echarts/model/Global} ecModel
  14681. * @param {Array.<Function>} optionPreprocessorFuncs
  14682. * @return {Object} Init option
  14683. */
  14684. setOption: function (rawOption, optionPreprocessorFuncs) {
  14685. rawOption = clone(rawOption, true);
  14686. // FIXME
  14687. // 如果 timeline options 或者 media 中设置了某个属性,而baseOption中没有设置,则进行警告。
  14688. var oldOptionBackup = this._optionBackup;
  14689. var newParsedOption = parseRawOption.call(
  14690. this, rawOption, optionPreprocessorFuncs, !oldOptionBackup
  14691. );
  14692. this._newBaseOption = newParsedOption.baseOption;
  14693. // For setOption at second time (using merge mode);
  14694. if (oldOptionBackup) {
  14695. // Only baseOption can be merged.
  14696. mergeOption(oldOptionBackup.baseOption, newParsedOption.baseOption);
  14697. // For simplicity, timeline options and media options do not support merge,
  14698. // that is, if you `setOption` twice and both has timeline options, the latter
  14699. // timeline opitons will not be merged to the formers, but just substitude them.
  14700. if (newParsedOption.timelineOptions.length) {
  14701. oldOptionBackup.timelineOptions = newParsedOption.timelineOptions;
  14702. }
  14703. if (newParsedOption.mediaList.length) {
  14704. oldOptionBackup.mediaList = newParsedOption.mediaList;
  14705. }
  14706. if (newParsedOption.mediaDefault) {
  14707. oldOptionBackup.mediaDefault = newParsedOption.mediaDefault;
  14708. }
  14709. }
  14710. else {
  14711. this._optionBackup = newParsedOption;
  14712. }
  14713. },
  14714. /**
  14715. * @param {boolean} isRecreate
  14716. * @return {Object}
  14717. */
  14718. mountOption: function (isRecreate) {
  14719. var optionBackup = this._optionBackup;
  14720. // TODO
  14721. // 如果没有reset功能则不clone。
  14722. this._timelineOptions = map(optionBackup.timelineOptions, clone);
  14723. this._mediaList = map(optionBackup.mediaList, clone);
  14724. this._mediaDefault = clone(optionBackup.mediaDefault);
  14725. this._currentMediaIndices = [];
  14726. return clone(isRecreate
  14727. // this._optionBackup.baseOption, which is created at the first `setOption`
  14728. // called, and is merged into every new option by inner method `mergeOption`
  14729. // each time `setOption` called, can be only used in `isRecreate`, because
  14730. // its reliability is under suspicion. In other cases option merge is
  14731. // performed by `model.mergeOption`.
  14732. ? optionBackup.baseOption : this._newBaseOption
  14733. );
  14734. },
  14735. /**
  14736. * @param {module:echarts/model/Global} ecModel
  14737. * @return {Object}
  14738. */
  14739. getTimelineOption: function (ecModel) {
  14740. var option;
  14741. var timelineOptions = this._timelineOptions;
  14742. if (timelineOptions.length) {
  14743. // getTimelineOption can only be called after ecModel inited,
  14744. // so we can get currentIndex from timelineModel.
  14745. var timelineModel = ecModel.getComponent('timeline');
  14746. if (timelineModel) {
  14747. option = clone(
  14748. timelineOptions[timelineModel.getCurrentIndex()],
  14749. true
  14750. );
  14751. }
  14752. }
  14753. return option;
  14754. },
  14755. /**
  14756. * @param {module:echarts/model/Global} ecModel
  14757. * @return {Array.<Object>}
  14758. */
  14759. getMediaOption: function (ecModel) {
  14760. var ecWidth = this._api.getWidth();
  14761. var ecHeight = this._api.getHeight();
  14762. var mediaList = this._mediaList;
  14763. var mediaDefault = this._mediaDefault;
  14764. var indices = [];
  14765. var result = [];
  14766. // No media defined.
  14767. if (!mediaList.length && !mediaDefault) {
  14768. return result;
  14769. }
  14770. // Multi media may be applied, the latter defined media has higher priority.
  14771. for (var i = 0, len = mediaList.length; i < len; i++) {
  14772. if (applyMediaQuery(mediaList[i].query, ecWidth, ecHeight)) {
  14773. indices.push(i);
  14774. }
  14775. }
  14776. // FIXME
  14777. // 是否mediaDefault应该强制用户设置,否则可能修改不能回归。
  14778. if (!indices.length && mediaDefault) {
  14779. indices = [-1];
  14780. }
  14781. if (indices.length && !indicesEquals(indices, this._currentMediaIndices)) {
  14782. result = map(indices, function (index) {
  14783. return clone(
  14784. index === -1 ? mediaDefault.option : mediaList[index].option
  14785. );
  14786. });
  14787. }
  14788. // Otherwise return nothing.
  14789. this._currentMediaIndices = indices;
  14790. return result;
  14791. }
  14792. };
  14793. function parseRawOption(rawOption, optionPreprocessorFuncs, isNew) {
  14794. var timelineOptions = [];
  14795. var mediaList = [];
  14796. var mediaDefault;
  14797. var baseOption;
  14798. // Compatible with ec2.
  14799. var timelineOpt = rawOption.timeline;
  14800. if (rawOption.baseOption) {
  14801. baseOption = rawOption.baseOption;
  14802. }
  14803. // For timeline
  14804. if (timelineOpt || rawOption.options) {
  14805. baseOption = baseOption || {};
  14806. timelineOptions = (rawOption.options || []).slice();
  14807. }
  14808. // For media query
  14809. if (rawOption.media) {
  14810. baseOption = baseOption || {};
  14811. var media = rawOption.media;
  14812. each(media, function (singleMedia) {
  14813. if (singleMedia && singleMedia.option) {
  14814. if (singleMedia.query) {
  14815. mediaList.push(singleMedia);
  14816. }
  14817. else if (!mediaDefault) {
  14818. // Use the first media default.
  14819. mediaDefault = singleMedia;
  14820. }
  14821. }
  14822. });
  14823. }
  14824. // For normal option
  14825. if (!baseOption) {
  14826. baseOption = rawOption;
  14827. }
  14828. // Set timelineOpt to baseOption in ec3,
  14829. // which is convenient for merge option.
  14830. if (!baseOption.timeline) {
  14831. baseOption.timeline = timelineOpt;
  14832. }
  14833. // Preprocess.
  14834. each([baseOption].concat(timelineOptions)
  14835. .concat(zrUtil.map(mediaList, function (media) {
  14836. return media.option;
  14837. })),
  14838. function (option) {
  14839. each(optionPreprocessorFuncs, function (preProcess) {
  14840. preProcess(option, isNew);
  14841. });
  14842. }
  14843. );
  14844. return {
  14845. baseOption: baseOption,
  14846. timelineOptions: timelineOptions,
  14847. mediaDefault: mediaDefault,
  14848. mediaList: mediaList
  14849. };
  14850. }
  14851. /**
  14852. * @see <http://www.w3.org/TR/css3-mediaqueries/#media1>
  14853. * Support: width, height, aspectRatio
  14854. * Can use max or min as prefix.
  14855. */
  14856. function applyMediaQuery(query, ecWidth, ecHeight) {
  14857. var realMap = {
  14858. width: ecWidth,
  14859. height: ecHeight,
  14860. aspectratio: ecWidth / ecHeight // lowser case for convenientce.
  14861. };
  14862. var applicatable = true;
  14863. zrUtil.each(query, function (value, attr) {
  14864. var matched = attr.match(QUERY_REG);
  14865. if (!matched || !matched[1] || !matched[2]) {
  14866. return;
  14867. }
  14868. var operator = matched[1];
  14869. var realAttr = matched[2].toLowerCase();
  14870. if (!compare(realMap[realAttr], value, operator)) {
  14871. applicatable = false;
  14872. }
  14873. });
  14874. return applicatable;
  14875. }
  14876. function compare(real, expect, operator) {
  14877. if (operator === 'min') {
  14878. return real >= expect;
  14879. }
  14880. else if (operator === 'max') {
  14881. return real <= expect;
  14882. }
  14883. else { // Equals
  14884. return real === expect;
  14885. }
  14886. }
  14887. function indicesEquals(indices1, indices2) {
  14888. // indices is always order by asc and has only finite number.
  14889. return indices1.join(',') === indices2.join(',');
  14890. }
  14891. /**
  14892. * Consider case:
  14893. * `chart.setOption(opt1);`
  14894. * Then user do some interaction like dataZoom, dataView changing.
  14895. * `chart.setOption(opt2);`
  14896. * Then user press 'reset button' in toolbox.
  14897. *
  14898. * After doing that all of the interaction effects should be reset, the
  14899. * chart should be the same as the result of invoke
  14900. * `chart.setOption(opt1); chart.setOption(opt2);`.
  14901. *
  14902. * Although it is not able ensure that
  14903. * `chart.setOption(opt1); chart.setOption(opt2);` is equivalents to
  14904. * `chart.setOption(merge(opt1, opt2));` exactly,
  14905. * this might be the only simple way to implement that feature.
  14906. *
  14907. * MEMO: We've considered some other approaches:
  14908. * 1. Each model handle its self restoration but not uniform treatment.
  14909. * (Too complex in logic and error-prone)
  14910. * 2. Use a shadow ecModel. (Performace expensive)
  14911. */
  14912. function mergeOption(oldOption, newOption) {
  14913. newOption = newOption || {};
  14914. each(newOption, function (newCptOpt, mainType) {
  14915. if (newCptOpt == null) {
  14916. return;
  14917. }
  14918. var oldCptOpt = oldOption[mainType];
  14919. if (!ComponentModel.hasClass(mainType)) {
  14920. oldOption[mainType] = merge(oldCptOpt, newCptOpt, true);
  14921. }
  14922. else {
  14923. newCptOpt = modelUtil.normalizeToArray(newCptOpt);
  14924. oldCptOpt = modelUtil.normalizeToArray(oldCptOpt);
  14925. var mapResult = modelUtil.mappingToExists(oldCptOpt, newCptOpt);
  14926. oldOption[mainType] = map(mapResult, function (item) {
  14927. return (item.option && item.exist)
  14928. ? merge(item.exist, item.option, true)
  14929. : (item.exist || item.option);
  14930. });
  14931. }
  14932. });
  14933. }
  14934. module.exports = OptionManager;
  14935. /***/ },
  14936. /* 78 */
  14937. /***/ function(module, exports, __webpack_require__) {
  14938. 'use strict';
  14939. var zrUtil = __webpack_require__(4);
  14940. var formatUtil = __webpack_require__(6);
  14941. var classUtil = __webpack_require__(13);
  14942. var modelUtil = __webpack_require__(5);
  14943. var ComponentModel = __webpack_require__(69);
  14944. var colorPaletteMixin = __webpack_require__(74);
  14945. var env = __webpack_require__(2);
  14946. var layout = __webpack_require__(71);
  14947. var set = classUtil.set;
  14948. var get = classUtil.get;
  14949. var encodeHTML = formatUtil.encodeHTML;
  14950. var addCommas = formatUtil.addCommas;
  14951. var SeriesModel = ComponentModel.extend({
  14952. type: 'series.__base__',
  14953. /**
  14954. * @readOnly
  14955. */
  14956. seriesIndex: 0,
  14957. // coodinateSystem will be injected in the echarts/CoordinateSystem
  14958. coordinateSystem: null,
  14959. /**
  14960. * @type {Object}
  14961. * @protected
  14962. */
  14963. defaultOption: null,
  14964. /**
  14965. * Data provided for legend
  14966. * @type {Function}
  14967. */
  14968. // PENDING
  14969. legendDataProvider: null,
  14970. /**
  14971. * Access path of color for visual
  14972. */
  14973. visualColorAccessPath: 'itemStyle.normal.color',
  14974. /**
  14975. * Support merge layout params.
  14976. * Only support 'box' now (left/right/top/bottom/width/height).
  14977. * @type {string|Object} Object can be {ignoreSize: true}
  14978. * @readOnly
  14979. */
  14980. layoutMode: null,
  14981. init: function (option, parentModel, ecModel, extraOpt) {
  14982. /**
  14983. * @type {number}
  14984. * @readOnly
  14985. */
  14986. this.seriesIndex = this.componentIndex;
  14987. this.mergeDefaultAndTheme(option, ecModel);
  14988. var data = this.getInitialData(option, ecModel);
  14989. if (true) {
  14990. zrUtil.assert(data, 'getInitialData returned invalid data.');
  14991. }
  14992. /**
  14993. * @type {module:echarts/data/List|module:echarts/data/Tree|module:echarts/data/Graph}
  14994. * @private
  14995. */
  14996. set(this, 'dataBeforeProcessed', data);
  14997. // If we reverse the order (make data firstly, and then make
  14998. // dataBeforeProcessed by cloneShallow), cloneShallow will
  14999. // cause data.graph.data !== data when using
  15000. // module:echarts/data/Graph or module:echarts/data/Tree.
  15001. // See module:echarts/data/helper/linkList
  15002. this.restoreData();
  15003. },
  15004. /**
  15005. * Util for merge default and theme to option
  15006. * @param {Object} option
  15007. * @param {module:echarts/model/Global} ecModel
  15008. */
  15009. mergeDefaultAndTheme: function (option, ecModel) {
  15010. var layoutMode = this.layoutMode;
  15011. var inputPositionParams = layoutMode
  15012. ? layout.getLayoutParams(option) : {};
  15013. zrUtil.merge(
  15014. option,
  15015. ecModel.getTheme().get(this.subType)
  15016. );
  15017. zrUtil.merge(option, this.getDefaultOption());
  15018. // Default label emphasis `position` and `show`
  15019. // FIXME Set label in mergeOption
  15020. modelUtil.defaultEmphasis(option.label, modelUtil.LABEL_OPTIONS);
  15021. this.fillDataTextStyle(option.data);
  15022. if (layoutMode) {
  15023. layout.mergeLayoutParam(option, inputPositionParams, layoutMode);
  15024. }
  15025. },
  15026. mergeOption: function (newSeriesOption, ecModel) {
  15027. newSeriesOption = zrUtil.merge(this.option, newSeriesOption, true);
  15028. this.fillDataTextStyle(newSeriesOption.data);
  15029. var layoutMode = this.layoutMode;
  15030. if (layoutMode) {
  15031. layout.mergeLayoutParam(this.option, newSeriesOption, layoutMode);
  15032. }
  15033. var data = this.getInitialData(newSeriesOption, ecModel);
  15034. // TODO Merge data?
  15035. if (data) {
  15036. set(this, 'data', data);
  15037. set(this, 'dataBeforeProcessed', data.cloneShallow());
  15038. }
  15039. },
  15040. fillDataTextStyle: function (data) {
  15041. // Default data label emphasis `position` and `show`
  15042. // FIXME Tree structure data ?
  15043. // FIXME Performance ?
  15044. if (data) {
  15045. for (var i = 0; i < data.length; i++) {
  15046. if (data[i] && data[i].label) {
  15047. modelUtil.defaultEmphasis(data[i].label, modelUtil.LABEL_OPTIONS);
  15048. }
  15049. }
  15050. }
  15051. },
  15052. /**
  15053. * Init a data structure from data related option in series
  15054. * Must be overwritten
  15055. */
  15056. getInitialData: function () {},
  15057. /**
  15058. * @param {string} [dataType]
  15059. * @return {module:echarts/data/List}
  15060. */
  15061. getData: function (dataType) {
  15062. var data = get(this, 'data');
  15063. return dataType == null ? data : data.getLinkedData(dataType);
  15064. },
  15065. /**
  15066. * @param {module:echarts/data/List} data
  15067. */
  15068. setData: function (data) {
  15069. set(this, 'data', data);
  15070. },
  15071. /**
  15072. * Get data before processed
  15073. * @return {module:echarts/data/List}
  15074. */
  15075. getRawData: function () {
  15076. return get(this, 'dataBeforeProcessed');
  15077. },
  15078. /**
  15079. * Coord dimension to data dimension.
  15080. *
  15081. * By default the result is the same as dimensions of series data.
  15082. * But in some series data dimensions are different from coord dimensions (i.e.
  15083. * candlestick and boxplot). Override this method to handle those cases.
  15084. *
  15085. * Coord dimension to data dimension can be one-to-many
  15086. *
  15087. * @param {string} coordDim
  15088. * @return {Array.<string>} dimensions on the axis.
  15089. */
  15090. coordDimToDataDim: function (coordDim) {
  15091. return modelUtil.coordDimToDataDim(this.getData(), coordDim);
  15092. },
  15093. /**
  15094. * Convert data dimension to coord dimension.
  15095. *
  15096. * @param {string|number} dataDim
  15097. * @return {string}
  15098. */
  15099. dataDimToCoordDim: function (dataDim) {
  15100. return modelUtil.dataDimToCoordDim(this.getData(), dataDim);
  15101. },
  15102. /**
  15103. * Get base axis if has coordinate system and has axis.
  15104. * By default use coordSys.getBaseAxis();
  15105. * Can be overrided for some chart.
  15106. * @return {type} description
  15107. */
  15108. getBaseAxis: function () {
  15109. var coordSys = this.coordinateSystem;
  15110. return coordSys && coordSys.getBaseAxis && coordSys.getBaseAxis();
  15111. },
  15112. // FIXME
  15113. /**
  15114. * Default tooltip formatter
  15115. *
  15116. * @param {number} dataIndex
  15117. * @param {boolean} [multipleSeries=false]
  15118. * @param {number} [dataType]
  15119. */
  15120. formatTooltip: function (dataIndex, multipleSeries, dataType) {
  15121. function formatArrayValue(value) {
  15122. var vertially = zrUtil.reduce(value, function (vertially, val, idx) {
  15123. var dimItem = data.getDimensionInfo(idx);
  15124. return vertially |= dimItem.tooltip !== false && dimItem.tooltipName != null;
  15125. }, 0);
  15126. var result = [];
  15127. var tooltipDims = modelUtil.otherDimToDataDim(data, 'tooltip');
  15128. tooltipDims.length
  15129. ? zrUtil.each(tooltipDims, function (dimIdx) {
  15130. setEachItem(data.get(dimIdx, dataIndex), dimIdx);
  15131. })
  15132. // By default, all dims is used on tooltip.
  15133. : zrUtil.each(value, setEachItem);
  15134. function setEachItem(val, dimIdx) {
  15135. var dimInfo = data.getDimensionInfo(dimIdx);
  15136. // If `dimInfo.tooltip` is not set, show tooltip.
  15137. if (!dimInfo || dimInfo.otherDims.tooltip === false) {
  15138. return;
  15139. }
  15140. var dimType = dimInfo.type;
  15141. var valStr = (vertially ? '- ' + (dimInfo.tooltipName || dimInfo.name) + ': ' : '')
  15142. + (dimType === 'ordinal'
  15143. ? val + ''
  15144. : dimType === 'time'
  15145. ? (multipleSeries ? '' : formatUtil.formatTime('yyyy/MM/dd hh:mm:ss', val))
  15146. : addCommas(val)
  15147. );
  15148. valStr && result.push(encodeHTML(valStr));
  15149. }
  15150. return (vertially ? '<br/>' : '') + result.join(vertially ? '<br/>' : ', ');
  15151. }
  15152. var data = get(this, 'data');
  15153. var value = this.getRawValue(dataIndex);
  15154. var formattedValue = zrUtil.isArray(value)
  15155. ? formatArrayValue(value) : encodeHTML(addCommas(value));
  15156. var name = data.getName(dataIndex);
  15157. var color = data.getItemVisual(dataIndex, 'color');
  15158. if (zrUtil.isObject(color) && color.colorStops) {
  15159. color = (color.colorStops[0] || {}).color;
  15160. }
  15161. color = color || 'transparent';
  15162. var colorEl = formatUtil.getTooltipMarker(color);
  15163. var seriesName = this.name;
  15164. // FIXME
  15165. if (seriesName === '\0-') {
  15166. // Not show '-'
  15167. seriesName = '';
  15168. }
  15169. seriesName = seriesName
  15170. ? encodeHTML(seriesName) + (!multipleSeries ? '<br/>' : ': ')
  15171. : '';
  15172. return !multipleSeries
  15173. ? seriesName + colorEl
  15174. + (name
  15175. ? encodeHTML(name) + ': ' + formattedValue
  15176. : formattedValue
  15177. )
  15178. : colorEl + seriesName + formattedValue;
  15179. },
  15180. /**
  15181. * @return {boolean}
  15182. */
  15183. isAnimationEnabled: function () {
  15184. if (env.node) {
  15185. return false;
  15186. }
  15187. var animationEnabled = this.getShallow('animation');
  15188. if (animationEnabled) {
  15189. if (this.getData().count() > this.getShallow('animationThreshold')) {
  15190. animationEnabled = false;
  15191. }
  15192. }
  15193. return animationEnabled;
  15194. },
  15195. restoreData: function () {
  15196. set(this, 'data', get(this, 'dataBeforeProcessed').cloneShallow());
  15197. },
  15198. getColorFromPalette: function (name, scope) {
  15199. var ecModel = this.ecModel;
  15200. // PENDING
  15201. var color = colorPaletteMixin.getColorFromPalette.call(this, name, scope);
  15202. if (!color) {
  15203. color = ecModel.getColorFromPalette(name, scope);
  15204. }
  15205. return color;
  15206. },
  15207. /**
  15208. * Get data indices for show tooltip content. See tooltip.
  15209. * @abstract
  15210. * @param {Array.<string>|string} dim
  15211. * @param {Array.<number>} value
  15212. * @param {module:echarts/coord/single/SingleAxis} baseAxis
  15213. * @return {Object} {dataIndices, nestestValue}.
  15214. */
  15215. getAxisTooltipData: null,
  15216. /**
  15217. * See tooltip.
  15218. * @abstract
  15219. * @param {number} dataIndex
  15220. * @return {Array.<number>} Point of tooltip. null/undefined can be returned.
  15221. */
  15222. getTooltipPosition: null
  15223. });
  15224. zrUtil.mixin(SeriesModel, modelUtil.dataFormatMixin);
  15225. zrUtil.mixin(SeriesModel, colorPaletteMixin);
  15226. module.exports = SeriesModel;
  15227. /***/ },
  15228. /* 79 */
  15229. /***/ function(module, exports, __webpack_require__) {
  15230. var Group = __webpack_require__(48);
  15231. var componentUtil = __webpack_require__(70);
  15232. var clazzUtil = __webpack_require__(13);
  15233. var Component = function () {
  15234. /**
  15235. * @type {module:zrender/container/Group}
  15236. * @readOnly
  15237. */
  15238. this.group = new Group();
  15239. /**
  15240. * @type {string}
  15241. * @readOnly
  15242. */
  15243. this.uid = componentUtil.getUID('viewComponent');
  15244. };
  15245. Component.prototype = {
  15246. constructor: Component,
  15247. init: function (ecModel, api) {},
  15248. render: function (componentModel, ecModel, api, payload) {},
  15249. dispose: function () {}
  15250. };
  15251. var componentProto = Component.prototype;
  15252. componentProto.updateView
  15253. = componentProto.updateLayout
  15254. = componentProto.updateVisual
  15255. = function (seriesModel, ecModel, api, payload) {
  15256. // Do nothing;
  15257. };
  15258. // Enable Component.extend.
  15259. clazzUtil.enableClassExtend(Component);
  15260. // Enable capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on.
  15261. clazzUtil.enableClassManagement(Component, {registerWhenExtend: true});
  15262. module.exports = Component;
  15263. /***/ },
  15264. /* 80 */
  15265. /***/ function(module, exports, __webpack_require__) {
  15266. var Group = __webpack_require__(48);
  15267. var componentUtil = __webpack_require__(70);
  15268. var clazzUtil = __webpack_require__(13);
  15269. var modelUtil = __webpack_require__(5);
  15270. var zrUtil = __webpack_require__(4);
  15271. function Chart() {
  15272. /**
  15273. * @type {module:zrender/container/Group}
  15274. * @readOnly
  15275. */
  15276. this.group = new Group();
  15277. /**
  15278. * @type {string}
  15279. * @readOnly
  15280. */
  15281. this.uid = componentUtil.getUID('viewChart');
  15282. }
  15283. Chart.prototype = {
  15284. type: 'chart',
  15285. /**
  15286. * Init the chart
  15287. * @param {module:echarts/model/Global} ecModel
  15288. * @param {module:echarts/ExtensionAPI} api
  15289. */
  15290. init: function (ecModel, api) {},
  15291. /**
  15292. * Render the chart
  15293. * @param {module:echarts/model/Series} seriesModel
  15294. * @param {module:echarts/model/Global} ecModel
  15295. * @param {module:echarts/ExtensionAPI} api
  15296. * @param {Object} payload
  15297. */
  15298. render: function (seriesModel, ecModel, api, payload) {},
  15299. /**
  15300. * Highlight series or specified data item
  15301. * @param {module:echarts/model/Series} seriesModel
  15302. * @param {module:echarts/model/Global} ecModel
  15303. * @param {module:echarts/ExtensionAPI} api
  15304. * @param {Object} payload
  15305. */
  15306. highlight: function (seriesModel, ecModel, api, payload) {
  15307. toggleHighlight(seriesModel.getData(), payload, 'emphasis');
  15308. },
  15309. /**
  15310. * Downplay series or specified data item
  15311. * @param {module:echarts/model/Series} seriesModel
  15312. * @param {module:echarts/model/Global} ecModel
  15313. * @param {module:echarts/ExtensionAPI} api
  15314. * @param {Object} payload
  15315. */
  15316. downplay: function (seriesModel, ecModel, api, payload) {
  15317. toggleHighlight(seriesModel.getData(), payload, 'normal');
  15318. },
  15319. /**
  15320. * Remove self
  15321. * @param {module:echarts/model/Global} ecModel
  15322. * @param {module:echarts/ExtensionAPI} api
  15323. */
  15324. remove: function (ecModel, api) {
  15325. this.group.removeAll();
  15326. },
  15327. /**
  15328. * Dispose self
  15329. * @param {module:echarts/model/Global} ecModel
  15330. * @param {module:echarts/ExtensionAPI} api
  15331. */
  15332. dispose: function () {}
  15333. /**
  15334. * The view contains the given point.
  15335. * @interface
  15336. * @param {Array.<number>} point
  15337. * @return {boolean}
  15338. */
  15339. // containPoint: function () {}
  15340. };
  15341. var chartProto = Chart.prototype;
  15342. chartProto.updateView
  15343. = chartProto.updateLayout
  15344. = chartProto.updateVisual
  15345. = function (seriesModel, ecModel, api, payload) {
  15346. this.render(seriesModel, ecModel, api, payload);
  15347. };
  15348. /**
  15349. * Set state of single element
  15350. * @param {module:zrender/Element} el
  15351. * @param {string} state
  15352. */
  15353. function elSetState(el, state) {
  15354. if (el) {
  15355. el.trigger(state);
  15356. if (el.type === 'group') {
  15357. for (var i = 0; i < el.childCount(); i++) {
  15358. elSetState(el.childAt(i), state);
  15359. }
  15360. }
  15361. }
  15362. }
  15363. /**
  15364. * @param {module:echarts/data/List} data
  15365. * @param {Object} payload
  15366. * @param {string} state 'normal'|'emphasis'
  15367. * @inner
  15368. */
  15369. function toggleHighlight(data, payload, state) {
  15370. var dataIndex = modelUtil.queryDataIndex(data, payload);
  15371. if (dataIndex != null) {
  15372. zrUtil.each(modelUtil.normalizeToArray(dataIndex), function (dataIdx) {
  15373. elSetState(data.getItemGraphicEl(dataIdx), state);
  15374. });
  15375. }
  15376. else {
  15377. data.eachItemGraphicEl(function (el) {
  15378. elSetState(el, state);
  15379. });
  15380. }
  15381. }
  15382. // Enable Chart.extend.
  15383. clazzUtil.enableClassExtend(Chart, ['dispose']);
  15384. // Add capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on.
  15385. clazzUtil.enableClassManagement(Chart, {registerWhenExtend: true});
  15386. module.exports = Chart;
  15387. /***/ },
  15388. /* 81 */
  15389. /***/ function(module, exports) {
  15390. var lib = {};
  15391. var ORIGIN_METHOD = '\0__throttleOriginMethod';
  15392. var RATE = '\0__throttleRate';
  15393. var THROTTLE_TYPE = '\0__throttleType';
  15394. /**
  15395. * @public
  15396. * @param {(Function)} fn
  15397. * @param {number} [delay=0] Unit: ms.
  15398. * @param {boolean} [debounce=false]
  15399. * true: If call interval less than `delay`, only the last call works.
  15400. * false: If call interval less than `delay, call works on fixed rate.
  15401. * @return {(Function)} throttled fn.
  15402. */
  15403. lib.throttle = function (fn, delay, debounce) {
  15404. var currCall;
  15405. var lastCall = 0;
  15406. var lastExec = 0;
  15407. var timer = null;
  15408. var diff;
  15409. var scope;
  15410. var args;
  15411. var debounceNextCall;
  15412. delay = delay || 0;
  15413. function exec() {
  15414. lastExec = (new Date()).getTime();
  15415. timer = null;
  15416. fn.apply(scope, args || []);
  15417. }
  15418. var cb = function () {
  15419. currCall = (new Date()).getTime();
  15420. scope = this;
  15421. args = arguments;
  15422. var thisDelay = debounceNextCall || delay;
  15423. var thisDebounce = debounceNextCall || debounce;
  15424. debounceNextCall = null;
  15425. diff = currCall - (thisDebounce ? lastCall : lastExec) - thisDelay;
  15426. clearTimeout(timer);
  15427. if (thisDebounce) {
  15428. timer = setTimeout(exec, thisDelay);
  15429. }
  15430. else {
  15431. if (diff >= 0) {
  15432. exec();
  15433. }
  15434. else {
  15435. timer = setTimeout(exec, -diff);
  15436. }
  15437. }
  15438. lastCall = currCall;
  15439. };
  15440. /**
  15441. * Clear throttle.
  15442. * @public
  15443. */
  15444. cb.clear = function () {
  15445. if (timer) {
  15446. clearTimeout(timer);
  15447. timer = null;
  15448. }
  15449. };
  15450. /**
  15451. * Enable debounce once.
  15452. */
  15453. cb.debounceNextCall = function (debounceDelay) {
  15454. debounceNextCall = debounceDelay;
  15455. };
  15456. return cb;
  15457. };
  15458. /**
  15459. * Create throttle method or update throttle rate.
  15460. *
  15461. * @example
  15462. * ComponentView.prototype.render = function () {
  15463. * ...
  15464. * throttle.createOrUpdate(
  15465. * this,
  15466. * '_dispatchAction',
  15467. * this.model.get('throttle'),
  15468. * 'fixRate'
  15469. * );
  15470. * };
  15471. * ComponentView.prototype.remove = function () {
  15472. * throttle.clear(this, '_dispatchAction');
  15473. * };
  15474. * ComponentView.prototype.dispose = function () {
  15475. * throttle.clear(this, '_dispatchAction');
  15476. * };
  15477. *
  15478. * @public
  15479. * @param {Object} obj
  15480. * @param {string} fnAttr
  15481. * @param {number} [rate]
  15482. * @param {string} [throttleType='fixRate'] 'fixRate' or 'debounce'
  15483. * @return {Function} throttled function.
  15484. */
  15485. lib.createOrUpdate = function (obj, fnAttr, rate, throttleType) {
  15486. var fn = obj[fnAttr];
  15487. if (!fn) {
  15488. return;
  15489. }
  15490. var originFn = fn[ORIGIN_METHOD] || fn;
  15491. var lastThrottleType = fn[THROTTLE_TYPE];
  15492. var lastRate = fn[RATE];
  15493. if (lastRate !== rate || lastThrottleType !== throttleType) {
  15494. if (rate == null || !throttleType) {
  15495. return (obj[fnAttr] = originFn);
  15496. }
  15497. fn = obj[fnAttr] = lib.throttle(
  15498. originFn, rate, throttleType === 'debounce'
  15499. );
  15500. fn[ORIGIN_METHOD] = originFn;
  15501. fn[THROTTLE_TYPE] = throttleType;
  15502. fn[RATE] = rate;
  15503. }
  15504. return fn;
  15505. };
  15506. /**
  15507. * Clear throttle. Example see throttle.createOrUpdate.
  15508. *
  15509. * @public
  15510. * @param {Object} obj
  15511. * @param {string} fnAttr
  15512. */
  15513. lib.clear = function (obj, fnAttr) {
  15514. var fn = obj[fnAttr];
  15515. if (fn && fn[ORIGIN_METHOD]) {
  15516. obj[fnAttr] = fn[ORIGIN_METHOD];
  15517. }
  15518. };
  15519. module.exports = lib;
  15520. /***/ },
  15521. /* 82 */
  15522. /***/ function(module, exports, __webpack_require__) {
  15523. /*!
  15524. * ZRender, a high performance 2d drawing library.
  15525. *
  15526. * Copyright (c) 2013, Baidu Inc.
  15527. * All rights reserved.
  15528. *
  15529. * LICENSE
  15530. * https://github.com/ecomfe/zrender/blob/master/LICENSE.txt
  15531. */
  15532. // Global defines
  15533. var guid = __webpack_require__(24);
  15534. var env = __webpack_require__(2);
  15535. var zrUtil = __webpack_require__(4);
  15536. var Handler = __webpack_require__(83);
  15537. var Storage = __webpack_require__(85);
  15538. var Animation = __webpack_require__(87);
  15539. var HandlerProxy = __webpack_require__(90);
  15540. var useVML = !env.canvasSupported;
  15541. var painterCtors = {
  15542. canvas: __webpack_require__(92)
  15543. };
  15544. var instances = {}; // ZRender实例map索引
  15545. var zrender = {};
  15546. /**
  15547. * @type {string}
  15548. */
  15549. zrender.version = '3.5.0';
  15550. /**
  15551. * Initializing a zrender instance
  15552. * @param {HTMLElement} dom
  15553. * @param {Object} opts
  15554. * @param {string} [opts.renderer='canvas'] 'canvas' or 'svg'
  15555. * @param {number} [opts.devicePixelRatio]
  15556. * @param {number|string} [opts.width] Can be 'auto' (the same as null/undefined)
  15557. * @param {number|string} [opts.height] Can be 'auto' (the same as null/undefined)
  15558. * @return {module:zrender/ZRender}
  15559. */
  15560. zrender.init = function(dom, opts) {
  15561. var zr = new ZRender(guid(), dom, opts);
  15562. instances[zr.id] = zr;
  15563. return zr;
  15564. };
  15565. /**
  15566. * Dispose zrender instance
  15567. * @param {module:zrender/ZRender} zr
  15568. */
  15569. zrender.dispose = function (zr) {
  15570. if (zr) {
  15571. zr.dispose();
  15572. }
  15573. else {
  15574. for (var key in instances) {
  15575. if (instances.hasOwnProperty(key)) {
  15576. instances[key].dispose();
  15577. }
  15578. }
  15579. instances = {};
  15580. }
  15581. return zrender;
  15582. };
  15583. /**
  15584. * Get zrender instance by id
  15585. * @param {string} id zrender instance id
  15586. * @return {module:zrender/ZRender}
  15587. */
  15588. zrender.getInstance = function (id) {
  15589. return instances[id];
  15590. };
  15591. zrender.registerPainter = function (name, Ctor) {
  15592. painterCtors[name] = Ctor;
  15593. };
  15594. function delInstance(id) {
  15595. delete instances[id];
  15596. }
  15597. /**
  15598. * @module zrender/ZRender
  15599. */
  15600. /**
  15601. * @constructor
  15602. * @alias module:zrender/ZRender
  15603. * @param {string} id
  15604. * @param {HTMLDomElement} dom
  15605. * @param {Object} opts
  15606. * @param {string} [opts.renderer='canvas'] 'canvas' or 'svg'
  15607. * @param {number} [opts.devicePixelRatio]
  15608. * @param {number} [opts.width] Can be 'auto' (the same as null/undefined)
  15609. * @param {number} [opts.height] Can be 'auto' (the same as null/undefined)
  15610. */
  15611. var ZRender = function(id, dom, opts) {
  15612. opts = opts || {};
  15613. /**
  15614. * @type {HTMLDomElement}
  15615. */
  15616. this.dom = dom;
  15617. /**
  15618. * @type {string}
  15619. */
  15620. this.id = id;
  15621. var self = this;
  15622. var storage = new Storage();
  15623. var rendererType = opts.renderer;
  15624. // TODO WebGL
  15625. if (useVML) {
  15626. if (!painterCtors.vml) {
  15627. throw new Error('You need to require \'zrender/vml/vml\' to support IE8');
  15628. }
  15629. rendererType = 'vml';
  15630. }
  15631. else if (!rendererType || !painterCtors[rendererType]) {
  15632. rendererType = 'canvas';
  15633. }
  15634. var painter = new painterCtors[rendererType](dom, storage, opts);
  15635. this.storage = storage;
  15636. this.painter = painter;
  15637. var handerProxy = !env.node ? new HandlerProxy(painter.getViewportRoot()) : null;
  15638. this.handler = new Handler(storage, painter, handerProxy, painter.root);
  15639. /**
  15640. * @type {module:zrender/animation/Animation}
  15641. */
  15642. this.animation = new Animation({
  15643. stage: {
  15644. update: zrUtil.bind(this.flush, this)
  15645. }
  15646. });
  15647. this.animation.start();
  15648. /**
  15649. * @type {boolean}
  15650. * @private
  15651. */
  15652. this._needsRefresh;
  15653. // 修改 storage.delFromStorage, 每次删除元素之前删除动画
  15654. // FIXME 有点ugly
  15655. var oldDelFromStorage = storage.delFromStorage;
  15656. var oldAddToStorage = storage.addToStorage;
  15657. storage.delFromStorage = function (el) {
  15658. oldDelFromStorage.call(storage, el);
  15659. el && el.removeSelfFromZr(self);
  15660. };
  15661. storage.addToStorage = function (el) {
  15662. oldAddToStorage.call(storage, el);
  15663. el.addSelfToZr(self);
  15664. };
  15665. };
  15666. ZRender.prototype = {
  15667. constructor: ZRender,
  15668. /**
  15669. * 获取实例唯一标识
  15670. * @return {string}
  15671. */
  15672. getId: function () {
  15673. return this.id;
  15674. },
  15675. /**
  15676. * 添加元素
  15677. * @param {module:zrender/Element} el
  15678. */
  15679. add: function (el) {
  15680. this.storage.addRoot(el);
  15681. this._needsRefresh = true;
  15682. },
  15683. /**
  15684. * 删除元素
  15685. * @param {module:zrender/Element} el
  15686. */
  15687. remove: function (el) {
  15688. this.storage.delRoot(el);
  15689. this._needsRefresh = true;
  15690. },
  15691. /**
  15692. * Change configuration of layer
  15693. * @param {string} zLevel
  15694. * @param {Object} config
  15695. * @param {string} [config.clearColor=0] Clear color
  15696. * @param {string} [config.motionBlur=false] If enable motion blur
  15697. * @param {number} [config.lastFrameAlpha=0.7] Motion blur factor. Larger value cause longer trailer
  15698. */
  15699. configLayer: function (zLevel, config) {
  15700. this.painter.configLayer(zLevel, config);
  15701. this._needsRefresh = true;
  15702. },
  15703. /**
  15704. * Repaint the canvas immediately
  15705. */
  15706. refreshImmediately: function () {
  15707. // Clear needsRefresh ahead to avoid something wrong happens in refresh
  15708. // Or it will cause zrender refreshes again and again.
  15709. this._needsRefresh = false;
  15710. this.painter.refresh();
  15711. /**
  15712. * Avoid trigger zr.refresh in Element#beforeUpdate hook
  15713. */
  15714. this._needsRefresh = false;
  15715. },
  15716. /**
  15717. * Mark and repaint the canvas in the next frame of browser
  15718. */
  15719. refresh: function() {
  15720. this._needsRefresh = true;
  15721. },
  15722. /**
  15723. * Perform all refresh
  15724. */
  15725. flush: function () {
  15726. if (this._needsRefresh) {
  15727. this.refreshImmediately();
  15728. }
  15729. if (this._needsRefreshHover) {
  15730. this.refreshHoverImmediately();
  15731. }
  15732. },
  15733. /**
  15734. * Add element to hover layer
  15735. * @param {module:zrender/Element} el
  15736. * @param {Object} style
  15737. */
  15738. addHover: function (el, style) {
  15739. if (this.painter.addHover) {
  15740. this.painter.addHover(el, style);
  15741. this.refreshHover();
  15742. }
  15743. },
  15744. /**
  15745. * Add element from hover layer
  15746. * @param {module:zrender/Element} el
  15747. */
  15748. removeHover: function (el) {
  15749. if (this.painter.removeHover) {
  15750. this.painter.removeHover(el);
  15751. this.refreshHover();
  15752. }
  15753. },
  15754. /**
  15755. * Clear all hover elements in hover layer
  15756. * @param {module:zrender/Element} el
  15757. */
  15758. clearHover: function () {
  15759. if (this.painter.clearHover) {
  15760. this.painter.clearHover();
  15761. this.refreshHover();
  15762. }
  15763. },
  15764. /**
  15765. * Refresh hover in next frame
  15766. */
  15767. refreshHover: function () {
  15768. this._needsRefreshHover = true;
  15769. },
  15770. /**
  15771. * Refresh hover immediately
  15772. */
  15773. refreshHoverImmediately: function () {
  15774. this._needsRefreshHover = false;
  15775. this.painter.refreshHover && this.painter.refreshHover();
  15776. },
  15777. /**
  15778. * Resize the canvas.
  15779. * Should be invoked when container size is changed
  15780. * @param {Object} [opts]
  15781. * @param {number|string} [opts.width] Can be 'auto' (the same as null/undefined)
  15782. * @param {number|string} [opts.height] Can be 'auto' (the same as null/undefined)
  15783. */
  15784. resize: function(opts) {
  15785. opts = opts || {};
  15786. this.painter.resize(opts.width, opts.height);
  15787. this.handler.resize();
  15788. },
  15789. /**
  15790. * Stop and clear all animation immediately
  15791. */
  15792. clearAnimation: function () {
  15793. this.animation.clear();
  15794. },
  15795. /**
  15796. * Get container width
  15797. */
  15798. getWidth: function() {
  15799. return this.painter.getWidth();
  15800. },
  15801. /**
  15802. * Get container height
  15803. */
  15804. getHeight: function() {
  15805. return this.painter.getHeight();
  15806. },
  15807. /**
  15808. * Export the canvas as Base64 URL
  15809. * @param {string} type
  15810. * @param {string} [backgroundColor='#fff']
  15811. * @return {string} Base64 URL
  15812. */
  15813. // toDataURL: function(type, backgroundColor) {
  15814. // return this.painter.getRenderedCanvas({
  15815. // backgroundColor: backgroundColor
  15816. // }).toDataURL(type);
  15817. // },
  15818. /**
  15819. * Converting a path to image.
  15820. * It has much better performance of drawing image rather than drawing a vector path.
  15821. * @param {module:zrender/graphic/Path} e
  15822. * @param {number} width
  15823. * @param {number} height
  15824. */
  15825. pathToImage: function(e, dpr) {
  15826. return this.painter.pathToImage(e, dpr);
  15827. },
  15828. /**
  15829. * Set default cursor
  15830. * @param {string} [cursorStyle='default'] 例如 crosshair
  15831. */
  15832. setCursorStyle: function (cursorStyle) {
  15833. this.handler.setCursorStyle(cursorStyle);
  15834. },
  15835. /**
  15836. * Find hovered element
  15837. * @param {number} x
  15838. * @param {number} y
  15839. * @return {Object} {target, topTarget}
  15840. */
  15841. findHover: function (x, y) {
  15842. return this.handler.findHover(x, y);
  15843. },
  15844. /**
  15845. * Bind event
  15846. *
  15847. * @param {string} eventName Event name
  15848. * @param {Function} eventHandler Handler function
  15849. * @param {Object} [context] Context object
  15850. */
  15851. on: function(eventName, eventHandler, context) {
  15852. this.handler.on(eventName, eventHandler, context);
  15853. },
  15854. /**
  15855. * Unbind event
  15856. * @param {string} eventName Event name
  15857. * @param {Function} [eventHandler] Handler function
  15858. */
  15859. off: function(eventName, eventHandler) {
  15860. this.handler.off(eventName, eventHandler);
  15861. },
  15862. /**
  15863. * Trigger event manually
  15864. *
  15865. * @param {string} eventName Event name
  15866. * @param {event=} event Event object
  15867. */
  15868. trigger: function (eventName, event) {
  15869. this.handler.trigger(eventName, event);
  15870. },
  15871. /**
  15872. * Clear all objects and the canvas.
  15873. */
  15874. clear: function () {
  15875. this.storage.delRoot();
  15876. this.painter.clear();
  15877. },
  15878. /**
  15879. * Dispose self.
  15880. */
  15881. dispose: function () {
  15882. this.animation.stop();
  15883. this.clear();
  15884. this.storage.dispose();
  15885. this.painter.dispose();
  15886. this.handler.dispose();
  15887. this.animation =
  15888. this.storage =
  15889. this.painter =
  15890. this.handler = null;
  15891. delInstance(this.id);
  15892. }
  15893. };
  15894. module.exports = zrender;
  15895. /***/ },
  15896. /* 83 */
  15897. /***/ function(module, exports, __webpack_require__) {
  15898. 'use strict';
  15899. /**
  15900. * Handler
  15901. * @module zrender/Handler
  15902. * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
  15903. * errorrik (errorrik@gmail.com)
  15904. * pissang (shenyi.914@gmail.com)
  15905. */
  15906. var util = __webpack_require__(4);
  15907. var Draggable = __webpack_require__(84);
  15908. var Eventful = __webpack_require__(25);
  15909. var SILENT = 'silent';
  15910. function makeEventPacket(eveType, targetInfo, event) {
  15911. return {
  15912. type: eveType,
  15913. event: event,
  15914. // target can only be an element that is not silent.
  15915. target: targetInfo.target,
  15916. // topTarget can be a silent element.
  15917. topTarget: targetInfo.topTarget,
  15918. cancelBubble: false,
  15919. offsetX: event.zrX,
  15920. offsetY: event.zrY,
  15921. gestureEvent: event.gestureEvent,
  15922. pinchX: event.pinchX,
  15923. pinchY: event.pinchY,
  15924. pinchScale: event.pinchScale,
  15925. wheelDelta: event.zrDelta,
  15926. zrByTouch: event.zrByTouch
  15927. };
  15928. }
  15929. function EmptyProxy () {}
  15930. EmptyProxy.prototype.dispose = function () {};
  15931. var handlerNames = [
  15932. 'click', 'dblclick', 'mousewheel', 'mouseout',
  15933. 'mouseup', 'mousedown', 'mousemove', 'contextmenu'
  15934. ];
  15935. /**
  15936. * @alias module:zrender/Handler
  15937. * @constructor
  15938. * @extends module:zrender/mixin/Eventful
  15939. * @param {module:zrender/Storage} storage Storage instance.
  15940. * @param {module:zrender/Painter} painter Painter instance.
  15941. * @param {module:zrender/dom/HandlerProxy} proxy HandlerProxy instance.
  15942. * @param {HTMLElement} painterRoot painter.root (not painter.getViewportRoot()).
  15943. */
  15944. var Handler = function(storage, painter, proxy, painterRoot) {
  15945. Eventful.call(this);
  15946. this.storage = storage;
  15947. this.painter = painter;
  15948. this.painterRoot = painterRoot;
  15949. proxy = proxy || new EmptyProxy();
  15950. /**
  15951. * Proxy of event. can be Dom, WebGLSurface, etc.
  15952. */
  15953. this.proxy = proxy;
  15954. // Attach handler
  15955. proxy.handler = this;
  15956. /**
  15957. * {target, topTarget}
  15958. * @private
  15959. * @type {Object}
  15960. */
  15961. this._hovered = {};
  15962. /**
  15963. * @private
  15964. * @type {Date}
  15965. */
  15966. this._lastTouchMoment;
  15967. /**
  15968. * @private
  15969. * @type {number}
  15970. */
  15971. this._lastX;
  15972. /**
  15973. * @private
  15974. * @type {number}
  15975. */
  15976. this._lastY;
  15977. Draggable.call(this);
  15978. util.each(handlerNames, function (name) {
  15979. proxy.on && proxy.on(name, this[name], this);
  15980. }, this);
  15981. };
  15982. Handler.prototype = {
  15983. constructor: Handler,
  15984. mousemove: function (event) {
  15985. var x = event.zrX;
  15986. var y = event.zrY;
  15987. var lastHovered = this._hovered;
  15988. var hovered = this._hovered = this.findHover(x, y);
  15989. var hoveredTarget = hovered.target;
  15990. var lastHoveredTarget = lastHovered.target;
  15991. var proxy = this.proxy;
  15992. proxy.setCursor && proxy.setCursor(hoveredTarget ? hoveredTarget.cursor : 'default');
  15993. // Mouse out on previous hovered element
  15994. if (lastHoveredTarget && hoveredTarget !== lastHoveredTarget && lastHoveredTarget.__zr) {
  15995. this.dispatchToElement(lastHovered, 'mouseout', event);
  15996. }
  15997. // Mouse moving on one element
  15998. this.dispatchToElement(hovered, 'mousemove', event);
  15999. // Mouse over on a new element
  16000. if (hoveredTarget && hoveredTarget !== lastHoveredTarget) {
  16001. this.dispatchToElement(hovered, 'mouseover', event);
  16002. }
  16003. },
  16004. mouseout: function (event) {
  16005. this.dispatchToElement(this._hovered, 'mouseout', event);
  16006. // There might be some doms created by upper layer application
  16007. // at the same level of painter.getViewportRoot() (e.g., tooltip
  16008. // dom created by echarts), where 'globalout' event should not
  16009. // be triggered when mouse enters these doms. (But 'mouseout'
  16010. // should be triggered at the original hovered element as usual).
  16011. var element = event.toElement || event.relatedTarget;
  16012. var innerDom;
  16013. do {
  16014. element = element && element.parentNode;
  16015. }
  16016. while (element && element.nodeType != 9 && !(
  16017. innerDom = element === this.painterRoot
  16018. ));
  16019. !innerDom && this.trigger('globalout', {event: event});
  16020. },
  16021. /**
  16022. * Resize
  16023. */
  16024. resize: function (event) {
  16025. this._hovered = {};
  16026. },
  16027. /**
  16028. * Dispatch event
  16029. * @param {string} eventName
  16030. * @param {event=} eventArgs
  16031. */
  16032. dispatch: function (eventName, eventArgs) {
  16033. var handler = this[eventName];
  16034. handler && handler.call(this, eventArgs);
  16035. },
  16036. /**
  16037. * Dispose
  16038. */
  16039. dispose: function () {
  16040. this.proxy.dispose();
  16041. this.storage =
  16042. this.proxy =
  16043. this.painter = null;
  16044. },
  16045. /**
  16046. * 设置默认的cursor style
  16047. * @param {string} [cursorStyle='default'] 例如 crosshair
  16048. */
  16049. setCursorStyle: function (cursorStyle) {
  16050. var proxy = this.proxy;
  16051. proxy.setCursor && proxy.setCursor(cursorStyle);
  16052. },
  16053. /**
  16054. * 事件分发代理
  16055. *
  16056. * @private
  16057. * @param {Object} targetInfo {target, topTarget} 目标图形元素
  16058. * @param {string} eventName 事件名称
  16059. * @param {Object} event 事件对象
  16060. */
  16061. dispatchToElement: function (targetInfo, eventName, event) {
  16062. targetInfo = targetInfo || {};
  16063. var eventHandler = 'on' + eventName;
  16064. var eventPacket = makeEventPacket(eventName, targetInfo, event);
  16065. var el = targetInfo.target;
  16066. while (el) {
  16067. el[eventHandler]
  16068. && (eventPacket.cancelBubble = el[eventHandler].call(el, eventPacket));
  16069. el.trigger(eventName, eventPacket);
  16070. el = el.parent;
  16071. if (eventPacket.cancelBubble) {
  16072. break;
  16073. }
  16074. }
  16075. if (!eventPacket.cancelBubble) {
  16076. // 冒泡到顶级 zrender 对象
  16077. this.trigger(eventName, eventPacket);
  16078. // 分发事件到用户自定义层
  16079. // 用户有可能在全局 click 事件中 dispose,所以需要判断下 painter 是否存在
  16080. this.painter && this.painter.eachOtherLayer(function (layer) {
  16081. if (typeof(layer[eventHandler]) == 'function') {
  16082. layer[eventHandler].call(layer, eventPacket);
  16083. }
  16084. if (layer.trigger) {
  16085. layer.trigger(eventName, eventPacket);
  16086. }
  16087. });
  16088. }
  16089. },
  16090. /**
  16091. * @private
  16092. * @param {number} x
  16093. * @param {number} y
  16094. * @param {module:zrender/graphic/Displayable} exclude
  16095. * @return {model:zrender/Element}
  16096. * @method
  16097. */
  16098. findHover: function(x, y, exclude) {
  16099. var list = this.storage.getDisplayList();
  16100. var out = {};
  16101. for (var i = list.length - 1; i >= 0 ; i--) {
  16102. var hoverCheckResult;
  16103. if (list[i] !== exclude
  16104. // getDisplayList may include ignored item in VML mode
  16105. && !list[i].ignore
  16106. && (hoverCheckResult = isHover(list[i], x, y))
  16107. ) {
  16108. !out.topTarget && (out.topTarget = list[i]);
  16109. if (hoverCheckResult !== SILENT) {
  16110. out.target = list[i];
  16111. break;
  16112. }
  16113. }
  16114. }
  16115. return out;
  16116. }
  16117. };
  16118. // Common handlers
  16119. util.each(['click', 'mousedown', 'mouseup', 'mousewheel', 'dblclick', 'contextmenu'], function (name) {
  16120. Handler.prototype[name] = function (event) {
  16121. // Find hover again to avoid click event is dispatched manually. Or click is triggered without mouseover
  16122. var hovered = this.findHover(event.zrX, event.zrY);
  16123. var hoveredTarget = hovered.target;
  16124. if (name === 'mousedown') {
  16125. this._downel = hoveredTarget;
  16126. // In case click triggered before mouseup
  16127. this._upel = hoveredTarget;
  16128. }
  16129. else if (name === 'mosueup') {
  16130. this._upel = hoveredTarget;
  16131. }
  16132. else if (name === 'click') {
  16133. if (this._downel !== this._upel) {
  16134. return;
  16135. }
  16136. }
  16137. this.dispatchToElement(hovered, name, event);
  16138. };
  16139. });
  16140. function isHover(displayable, x, y) {
  16141. if (displayable[displayable.rectHover ? 'rectContain' : 'contain'](x, y)) {
  16142. var el = displayable;
  16143. var isSilent;
  16144. while (el) {
  16145. // If clipped by ancestor.
  16146. // FIXME: If clipPath has neither stroke nor fill,
  16147. // el.clipPath.contain(x, y) will always return false.
  16148. if (el.clipPath && !el.clipPath.contain(x, y)) {
  16149. return false;
  16150. }
  16151. if (el.silent) {
  16152. isSilent = true;
  16153. }
  16154. el = el.parent;
  16155. }
  16156. return isSilent ? SILENT : true;
  16157. }
  16158. return false;
  16159. }
  16160. util.mixin(Handler, Eventful);
  16161. util.mixin(Handler, Draggable);
  16162. module.exports = Handler;
  16163. /***/ },
  16164. /* 84 */
  16165. /***/ function(module, exports) {
  16166. // TODO Draggable for group
  16167. // FIXME Draggable on element which has parent rotation or scale
  16168. function Draggable() {
  16169. this.on('mousedown', this._dragStart, this);
  16170. this.on('mousemove', this._drag, this);
  16171. this.on('mouseup', this._dragEnd, this);
  16172. this.on('globalout', this._dragEnd, this);
  16173. // this._dropTarget = null;
  16174. // this._draggingTarget = null;
  16175. // this._x = 0;
  16176. // this._y = 0;
  16177. }
  16178. Draggable.prototype = {
  16179. constructor: Draggable,
  16180. _dragStart: function (e) {
  16181. var draggingTarget = e.target;
  16182. if (draggingTarget && draggingTarget.draggable) {
  16183. this._draggingTarget = draggingTarget;
  16184. draggingTarget.dragging = true;
  16185. this._x = e.offsetX;
  16186. this._y = e.offsetY;
  16187. this.dispatchToElement(param(draggingTarget, e), 'dragstart', e.event);
  16188. }
  16189. },
  16190. _drag: function (e) {
  16191. var draggingTarget = this._draggingTarget;
  16192. if (draggingTarget) {
  16193. var x = e.offsetX;
  16194. var y = e.offsetY;
  16195. var dx = x - this._x;
  16196. var dy = y - this._y;
  16197. this._x = x;
  16198. this._y = y;
  16199. draggingTarget.drift(dx, dy, e);
  16200. this.dispatchToElement(param(draggingTarget, e), 'drag', e.event);
  16201. var dropTarget = this.findHover(x, y, draggingTarget).target;
  16202. var lastDropTarget = this._dropTarget;
  16203. this._dropTarget = dropTarget;
  16204. if (draggingTarget !== dropTarget) {
  16205. if (lastDropTarget && dropTarget !== lastDropTarget) {
  16206. this.dispatchToElement(param(lastDropTarget, e), 'dragleave', e.event);
  16207. }
  16208. if (dropTarget && dropTarget !== lastDropTarget) {
  16209. this.dispatchToElement(param(dropTarget, e), 'dragenter', e.event);
  16210. }
  16211. }
  16212. }
  16213. },
  16214. _dragEnd: function (e) {
  16215. var draggingTarget = this._draggingTarget;
  16216. if (draggingTarget) {
  16217. draggingTarget.dragging = false;
  16218. }
  16219. this.dispatchToElement(param(draggingTarget, e), 'dragend', e.event);
  16220. if (this._dropTarget) {
  16221. this.dispatchToElement(param(this._dropTarget, e), 'drop', e.event);
  16222. }
  16223. this._draggingTarget = null;
  16224. this._dropTarget = null;
  16225. }
  16226. };
  16227. function param(target, e) {
  16228. return {target: target, topTarget: e && e.topTarget};
  16229. }
  16230. module.exports = Draggable;
  16231. /***/ },
  16232. /* 85 */
  16233. /***/ function(module, exports, __webpack_require__) {
  16234. 'use strict';
  16235. /**
  16236. * Storage内容仓库模块
  16237. * @module zrender/Storage
  16238. * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
  16239. * @author errorrik (errorrik@gmail.com)
  16240. * @author pissang (https://github.com/pissang/)
  16241. */
  16242. var util = __webpack_require__(4);
  16243. var env = __webpack_require__(2);
  16244. var Group = __webpack_require__(48);
  16245. // Use timsort because in most case elements are partially sorted
  16246. // https://jsfiddle.net/pissang/jr4x7mdm/8/
  16247. var timsort = __webpack_require__(86);
  16248. function shapeCompareFunc(a, b) {
  16249. if (a.zlevel === b.zlevel) {
  16250. if (a.z === b.z) {
  16251. // if (a.z2 === b.z2) {
  16252. // // FIXME Slow has renderidx compare
  16253. // // http://stackoverflow.com/questions/20883421/sorting-in-javascript-should-every-compare-function-have-a-return-0-statement
  16254. // // https://github.com/v8/v8/blob/47cce544a31ed5577ffe2963f67acb4144ee0232/src/js/array.js#L1012
  16255. // return a.__renderidx - b.__renderidx;
  16256. // }
  16257. return a.z2 - b.z2;
  16258. }
  16259. return a.z - b.z;
  16260. }
  16261. return a.zlevel - b.zlevel;
  16262. }
  16263. /**
  16264. * 内容仓库 (M)
  16265. * @alias module:zrender/Storage
  16266. * @constructor
  16267. */
  16268. var Storage = function () {
  16269. this._roots = [];
  16270. this._displayList = [];
  16271. this._displayListLen = 0;
  16272. };
  16273. Storage.prototype = {
  16274. constructor: Storage,
  16275. /**
  16276. * @param {Function} cb
  16277. *
  16278. */
  16279. traverse: function (cb, context) {
  16280. for (var i = 0; i < this._roots.length; i++) {
  16281. this._roots[i].traverse(cb, context);
  16282. }
  16283. },
  16284. /**
  16285. * 返回所有图形的绘制队列
  16286. * @param {boolean} [update=false] 是否在返回前更新该数组
  16287. * @param {boolean} [includeIgnore=false] 是否包含 ignore 的数组, 在 update 为 true 的时候有效
  16288. *
  16289. * 详见{@link module:zrender/graphic/Displayable.prototype.updateDisplayList}
  16290. * @return {Array.<module:zrender/graphic/Displayable>}
  16291. */
  16292. getDisplayList: function (update, includeIgnore) {
  16293. includeIgnore = includeIgnore || false;
  16294. if (update) {
  16295. this.updateDisplayList(includeIgnore);
  16296. }
  16297. return this._displayList;
  16298. },
  16299. /**
  16300. * 更新图形的绘制队列。
  16301. * 每次绘制前都会调用,该方法会先深度优先遍历整个树,更新所有Group和Shape的变换并且把所有可见的Shape保存到数组中,
  16302. * 最后根据绘制的优先级(zlevel > z > 插入顺序)排序得到绘制队列
  16303. * @param {boolean} [includeIgnore=false] 是否包含 ignore 的数组
  16304. */
  16305. updateDisplayList: function (includeIgnore) {
  16306. this._displayListLen = 0;
  16307. var roots = this._roots;
  16308. var displayList = this._displayList;
  16309. for (var i = 0, len = roots.length; i < len; i++) {
  16310. this._updateAndAddDisplayable(roots[i], null, includeIgnore);
  16311. }
  16312. displayList.length = this._displayListLen;
  16313. // for (var i = 0, len = displayList.length; i < len; i++) {
  16314. // displayList[i].__renderidx = i;
  16315. // }
  16316. // displayList.sort(shapeCompareFunc);
  16317. env.canvasSupported && timsort(displayList, shapeCompareFunc);
  16318. },
  16319. _updateAndAddDisplayable: function (el, clipPaths, includeIgnore) {
  16320. if (el.ignore && !includeIgnore) {
  16321. return;
  16322. }
  16323. el.beforeUpdate();
  16324. if (el.__dirty) {
  16325. el.update();
  16326. }
  16327. el.afterUpdate();
  16328. var userSetClipPath = el.clipPath;
  16329. if (userSetClipPath) {
  16330. // FIXME 效率影响
  16331. if (clipPaths) {
  16332. clipPaths = clipPaths.slice();
  16333. }
  16334. else {
  16335. clipPaths = [];
  16336. }
  16337. var currentClipPath = userSetClipPath;
  16338. var parentClipPath = el;
  16339. // Recursively add clip path
  16340. while (currentClipPath) {
  16341. // clipPath 的变换是基于使用这个 clipPath 的元素
  16342. currentClipPath.parent = parentClipPath;
  16343. currentClipPath.updateTransform();
  16344. clipPaths.push(currentClipPath);
  16345. parentClipPath = currentClipPath;
  16346. currentClipPath = currentClipPath.clipPath;
  16347. }
  16348. }
  16349. if (el.isGroup) {
  16350. var children = el._children;
  16351. for (var i = 0; i < children.length; i++) {
  16352. var child = children[i];
  16353. // Force to mark as dirty if group is dirty
  16354. // FIXME __dirtyPath ?
  16355. if (el.__dirty) {
  16356. child.__dirty = true;
  16357. }
  16358. this._updateAndAddDisplayable(child, clipPaths, includeIgnore);
  16359. }
  16360. // Mark group clean here
  16361. el.__dirty = false;
  16362. }
  16363. else {
  16364. el.__clipPaths = clipPaths;
  16365. this._displayList[this._displayListLen++] = el;
  16366. }
  16367. },
  16368. /**
  16369. * 添加图形(Shape)或者组(Group)到根节点
  16370. * @param {module:zrender/Element} el
  16371. */
  16372. addRoot: function (el) {
  16373. if (el.__storage === this) {
  16374. return;
  16375. }
  16376. if (el instanceof Group) {
  16377. el.addChildrenToStorage(this);
  16378. }
  16379. this.addToStorage(el);
  16380. this._roots.push(el);
  16381. },
  16382. /**
  16383. * 删除指定的图形(Shape)或者组(Group)
  16384. * @param {string|Array.<string>} [el] 如果为空清空整个Storage
  16385. */
  16386. delRoot: function (el) {
  16387. if (el == null) {
  16388. // 不指定el清空
  16389. for (var i = 0; i < this._roots.length; i++) {
  16390. var root = this._roots[i];
  16391. if (root instanceof Group) {
  16392. root.delChildrenFromStorage(this);
  16393. }
  16394. }
  16395. this._roots = [];
  16396. this._displayList = [];
  16397. this._displayListLen = 0;
  16398. return;
  16399. }
  16400. if (el instanceof Array) {
  16401. for (var i = 0, l = el.length; i < l; i++) {
  16402. this.delRoot(el[i]);
  16403. }
  16404. return;
  16405. }
  16406. var idx = util.indexOf(this._roots, el);
  16407. if (idx >= 0) {
  16408. this.delFromStorage(el);
  16409. this._roots.splice(idx, 1);
  16410. if (el instanceof Group) {
  16411. el.delChildrenFromStorage(this);
  16412. }
  16413. }
  16414. },
  16415. addToStorage: function (el) {
  16416. el.__storage = this;
  16417. el.dirty(false);
  16418. return this;
  16419. },
  16420. delFromStorage: function (el) {
  16421. if (el) {
  16422. el.__storage = null;
  16423. }
  16424. return this;
  16425. },
  16426. /**
  16427. * 清空并且释放Storage
  16428. */
  16429. dispose: function () {
  16430. this._renderList =
  16431. this._roots = null;
  16432. },
  16433. displayableSortFunc: shapeCompareFunc
  16434. };
  16435. module.exports = Storage;
  16436. /***/ },
  16437. /* 86 */
  16438. /***/ function(module, exports) {
  16439. // https://github.com/mziccard/node-timsort
  16440. var DEFAULT_MIN_MERGE = 32;
  16441. var DEFAULT_MIN_GALLOPING = 7;
  16442. var DEFAULT_TMP_STORAGE_LENGTH = 256;
  16443. function minRunLength(n) {
  16444. var r = 0;
  16445. while (n >= DEFAULT_MIN_MERGE) {
  16446. r |= n & 1;
  16447. n >>= 1;
  16448. }
  16449. return n + r;
  16450. }
  16451. function makeAscendingRun(array, lo, hi, compare) {
  16452. var runHi = lo + 1;
  16453. if (runHi === hi) {
  16454. return 1;
  16455. }
  16456. if (compare(array[runHi++], array[lo]) < 0) {
  16457. while (runHi < hi && compare(array[runHi], array[runHi - 1]) < 0) {
  16458. runHi++;
  16459. }
  16460. reverseRun(array, lo, runHi);
  16461. }
  16462. else {
  16463. while (runHi < hi && compare(array[runHi], array[runHi - 1]) >= 0) {
  16464. runHi++;
  16465. }
  16466. }
  16467. return runHi - lo;
  16468. }
  16469. function reverseRun(array, lo, hi) {
  16470. hi--;
  16471. while (lo < hi) {
  16472. var t = array[lo];
  16473. array[lo++] = array[hi];
  16474. array[hi--] = t;
  16475. }
  16476. }
  16477. function binaryInsertionSort(array, lo, hi, start, compare) {
  16478. if (start === lo) {
  16479. start++;
  16480. }
  16481. for (; start < hi; start++) {
  16482. var pivot = array[start];
  16483. var left = lo;
  16484. var right = start;
  16485. var mid;
  16486. while (left < right) {
  16487. mid = left + right >>> 1;
  16488. if (compare(pivot, array[mid]) < 0) {
  16489. right = mid;
  16490. }
  16491. else {
  16492. left = mid + 1;
  16493. }
  16494. }
  16495. var n = start - left;
  16496. switch (n) {
  16497. case 3:
  16498. array[left + 3] = array[left + 2];
  16499. case 2:
  16500. array[left + 2] = array[left + 1];
  16501. case 1:
  16502. array[left + 1] = array[left];
  16503. break;
  16504. default:
  16505. while (n > 0) {
  16506. array[left + n] = array[left + n - 1];
  16507. n--;
  16508. }
  16509. }
  16510. array[left] = pivot;
  16511. }
  16512. }
  16513. function gallopLeft(value, array, start, length, hint, compare) {
  16514. var lastOffset = 0;
  16515. var maxOffset = 0;
  16516. var offset = 1;
  16517. if (compare(value, array[start + hint]) > 0) {
  16518. maxOffset = length - hint;
  16519. while (offset < maxOffset && compare(value, array[start + hint + offset]) > 0) {
  16520. lastOffset = offset;
  16521. offset = (offset << 1) + 1;
  16522. if (offset <= 0) {
  16523. offset = maxOffset;
  16524. }
  16525. }
  16526. if (offset > maxOffset) {
  16527. offset = maxOffset;
  16528. }
  16529. lastOffset += hint;
  16530. offset += hint;
  16531. }
  16532. else {
  16533. maxOffset = hint + 1;
  16534. while (offset < maxOffset && compare(value, array[start + hint - offset]) <= 0) {
  16535. lastOffset = offset;
  16536. offset = (offset << 1) + 1;
  16537. if (offset <= 0) {
  16538. offset = maxOffset;
  16539. }
  16540. }
  16541. if (offset > maxOffset) {
  16542. offset = maxOffset;
  16543. }
  16544. var tmp = lastOffset;
  16545. lastOffset = hint - offset;
  16546. offset = hint - tmp;
  16547. }
  16548. lastOffset++;
  16549. while (lastOffset < offset) {
  16550. var m = lastOffset + (offset - lastOffset >>> 1);
  16551. if (compare(value, array[start + m]) > 0) {
  16552. lastOffset = m + 1;
  16553. }
  16554. else {
  16555. offset = m;
  16556. }
  16557. }
  16558. return offset;
  16559. }
  16560. function gallopRight(value, array, start, length, hint, compare) {
  16561. var lastOffset = 0;
  16562. var maxOffset = 0;
  16563. var offset = 1;
  16564. if (compare(value, array[start + hint]) < 0) {
  16565. maxOffset = hint + 1;
  16566. while (offset < maxOffset && compare(value, array[start + hint - offset]) < 0) {
  16567. lastOffset = offset;
  16568. offset = (offset << 1) + 1;
  16569. if (offset <= 0) {
  16570. offset = maxOffset;
  16571. }
  16572. }
  16573. if (offset > maxOffset) {
  16574. offset = maxOffset;
  16575. }
  16576. var tmp = lastOffset;
  16577. lastOffset = hint - offset;
  16578. offset = hint - tmp;
  16579. }
  16580. else {
  16581. maxOffset = length - hint;
  16582. while (offset < maxOffset && compare(value, array[start + hint + offset]) >= 0) {
  16583. lastOffset = offset;
  16584. offset = (offset << 1) + 1;
  16585. if (offset <= 0) {
  16586. offset = maxOffset;
  16587. }
  16588. }
  16589. if (offset > maxOffset) {
  16590. offset = maxOffset;
  16591. }
  16592. lastOffset += hint;
  16593. offset += hint;
  16594. }
  16595. lastOffset++;
  16596. while (lastOffset < offset) {
  16597. var m = lastOffset + (offset - lastOffset >>> 1);
  16598. if (compare(value, array[start + m]) < 0) {
  16599. offset = m;
  16600. }
  16601. else {
  16602. lastOffset = m + 1;
  16603. }
  16604. }
  16605. return offset;
  16606. }
  16607. function TimSort(array, compare) {
  16608. var minGallop = DEFAULT_MIN_GALLOPING;
  16609. var length = 0;
  16610. var tmpStorageLength = DEFAULT_TMP_STORAGE_LENGTH;
  16611. var stackLength = 0;
  16612. var runStart;
  16613. var runLength;
  16614. var stackSize = 0;
  16615. length = array.length;
  16616. if (length < 2 * DEFAULT_TMP_STORAGE_LENGTH) {
  16617. tmpStorageLength = length >>> 1;
  16618. }
  16619. var tmp = [];
  16620. stackLength = length < 120 ? 5 : length < 1542 ? 10 : length < 119151 ? 19 : 40;
  16621. runStart = [];
  16622. runLength = [];
  16623. function pushRun(_runStart, _runLength) {
  16624. runStart[stackSize] = _runStart;
  16625. runLength[stackSize] = _runLength;
  16626. stackSize += 1;
  16627. }
  16628. function mergeRuns() {
  16629. while (stackSize > 1) {
  16630. var n = stackSize - 2;
  16631. if (n >= 1 && runLength[n - 1] <= runLength[n] + runLength[n + 1] || n >= 2 && runLength[n - 2] <= runLength[n] + runLength[n - 1]) {
  16632. if (runLength[n - 1] < runLength[n + 1]) {
  16633. n--;
  16634. }
  16635. }
  16636. else if (runLength[n] > runLength[n + 1]) {
  16637. break;
  16638. }
  16639. mergeAt(n);
  16640. }
  16641. }
  16642. function forceMergeRuns() {
  16643. while (stackSize > 1) {
  16644. var n = stackSize - 2;
  16645. if (n > 0 && runLength[n - 1] < runLength[n + 1]) {
  16646. n--;
  16647. }
  16648. mergeAt(n);
  16649. }
  16650. }
  16651. function mergeAt(i) {
  16652. var start1 = runStart[i];
  16653. var length1 = runLength[i];
  16654. var start2 = runStart[i + 1];
  16655. var length2 = runLength[i + 1];
  16656. runLength[i] = length1 + length2;
  16657. if (i === stackSize - 3) {
  16658. runStart[i + 1] = runStart[i + 2];
  16659. runLength[i + 1] = runLength[i + 2];
  16660. }
  16661. stackSize--;
  16662. var k = gallopRight(array[start2], array, start1, length1, 0, compare);
  16663. start1 += k;
  16664. length1 -= k;
  16665. if (length1 === 0) {
  16666. return;
  16667. }
  16668. length2 = gallopLeft(array[start1 + length1 - 1], array, start2, length2, length2 - 1, compare);
  16669. if (length2 === 0) {
  16670. return;
  16671. }
  16672. if (length1 <= length2) {
  16673. mergeLow(start1, length1, start2, length2);
  16674. }
  16675. else {
  16676. mergeHigh(start1, length1, start2, length2);
  16677. }
  16678. }
  16679. function mergeLow(start1, length1, start2, length2) {
  16680. var i = 0;
  16681. for (i = 0; i < length1; i++) {
  16682. tmp[i] = array[start1 + i];
  16683. }
  16684. var cursor1 = 0;
  16685. var cursor2 = start2;
  16686. var dest = start1;
  16687. array[dest++] = array[cursor2++];
  16688. if (--length2 === 0) {
  16689. for (i = 0; i < length1; i++) {
  16690. array[dest + i] = tmp[cursor1 + i];
  16691. }
  16692. return;
  16693. }
  16694. if (length1 === 1) {
  16695. for (i = 0; i < length2; i++) {
  16696. array[dest + i] = array[cursor2 + i];
  16697. }
  16698. array[dest + length2] = tmp[cursor1];
  16699. return;
  16700. }
  16701. var _minGallop = minGallop;
  16702. var count1, count2, exit;
  16703. while (1) {
  16704. count1 = 0;
  16705. count2 = 0;
  16706. exit = false;
  16707. do {
  16708. if (compare(array[cursor2], tmp[cursor1]) < 0) {
  16709. array[dest++] = array[cursor2++];
  16710. count2++;
  16711. count1 = 0;
  16712. if (--length2 === 0) {
  16713. exit = true;
  16714. break;
  16715. }
  16716. }
  16717. else {
  16718. array[dest++] = tmp[cursor1++];
  16719. count1++;
  16720. count2 = 0;
  16721. if (--length1 === 1) {
  16722. exit = true;
  16723. break;
  16724. }
  16725. }
  16726. } while ((count1 | count2) < _minGallop);
  16727. if (exit) {
  16728. break;
  16729. }
  16730. do {
  16731. count1 = gallopRight(array[cursor2], tmp, cursor1, length1, 0, compare);
  16732. if (count1 !== 0) {
  16733. for (i = 0; i < count1; i++) {
  16734. array[dest + i] = tmp[cursor1 + i];
  16735. }
  16736. dest += count1;
  16737. cursor1 += count1;
  16738. length1 -= count1;
  16739. if (length1 <= 1) {
  16740. exit = true;
  16741. break;
  16742. }
  16743. }
  16744. array[dest++] = array[cursor2++];
  16745. if (--length2 === 0) {
  16746. exit = true;
  16747. break;
  16748. }
  16749. count2 = gallopLeft(tmp[cursor1], array, cursor2, length2, 0, compare);
  16750. if (count2 !== 0) {
  16751. for (i = 0; i < count2; i++) {
  16752. array[dest + i] = array[cursor2 + i];
  16753. }
  16754. dest += count2;
  16755. cursor2 += count2;
  16756. length2 -= count2;
  16757. if (length2 === 0) {
  16758. exit = true;
  16759. break;
  16760. }
  16761. }
  16762. array[dest++] = tmp[cursor1++];
  16763. if (--length1 === 1) {
  16764. exit = true;
  16765. break;
  16766. }
  16767. _minGallop--;
  16768. } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING);
  16769. if (exit) {
  16770. break;
  16771. }
  16772. if (_minGallop < 0) {
  16773. _minGallop = 0;
  16774. }
  16775. _minGallop += 2;
  16776. }
  16777. minGallop = _minGallop;
  16778. minGallop < 1 && (minGallop = 1);
  16779. if (length1 === 1) {
  16780. for (i = 0; i < length2; i++) {
  16781. array[dest + i] = array[cursor2 + i];
  16782. }
  16783. array[dest + length2] = tmp[cursor1];
  16784. }
  16785. else if (length1 === 0) {
  16786. throw new Error();
  16787. // throw new Error('mergeLow preconditions were not respected');
  16788. }
  16789. else {
  16790. for (i = 0; i < length1; i++) {
  16791. array[dest + i] = tmp[cursor1 + i];
  16792. }
  16793. }
  16794. }
  16795. function mergeHigh (start1, length1, start2, length2) {
  16796. var i = 0;
  16797. for (i = 0; i < length2; i++) {
  16798. tmp[i] = array[start2 + i];
  16799. }
  16800. var cursor1 = start1 + length1 - 1;
  16801. var cursor2 = length2 - 1;
  16802. var dest = start2 + length2 - 1;
  16803. var customCursor = 0;
  16804. var customDest = 0;
  16805. array[dest--] = array[cursor1--];
  16806. if (--length1 === 0) {
  16807. customCursor = dest - (length2 - 1);
  16808. for (i = 0; i < length2; i++) {
  16809. array[customCursor + i] = tmp[i];
  16810. }
  16811. return;
  16812. }
  16813. if (length2 === 1) {
  16814. dest -= length1;
  16815. cursor1 -= length1;
  16816. customDest = dest + 1;
  16817. customCursor = cursor1 + 1;
  16818. for (i = length1 - 1; i >= 0; i--) {
  16819. array[customDest + i] = array[customCursor + i];
  16820. }
  16821. array[dest] = tmp[cursor2];
  16822. return;
  16823. }
  16824. var _minGallop = minGallop;
  16825. while (true) {
  16826. var count1 = 0;
  16827. var count2 = 0;
  16828. var exit = false;
  16829. do {
  16830. if (compare(tmp[cursor2], array[cursor1]) < 0) {
  16831. array[dest--] = array[cursor1--];
  16832. count1++;
  16833. count2 = 0;
  16834. if (--length1 === 0) {
  16835. exit = true;
  16836. break;
  16837. }
  16838. }
  16839. else {
  16840. array[dest--] = tmp[cursor2--];
  16841. count2++;
  16842. count1 = 0;
  16843. if (--length2 === 1) {
  16844. exit = true;
  16845. break;
  16846. }
  16847. }
  16848. } while ((count1 | count2) < _minGallop);
  16849. if (exit) {
  16850. break;
  16851. }
  16852. do {
  16853. count1 = length1 - gallopRight(tmp[cursor2], array, start1, length1, length1 - 1, compare);
  16854. if (count1 !== 0) {
  16855. dest -= count1;
  16856. cursor1 -= count1;
  16857. length1 -= count1;
  16858. customDest = dest + 1;
  16859. customCursor = cursor1 + 1;
  16860. for (i = count1 - 1; i >= 0; i--) {
  16861. array[customDest + i] = array[customCursor + i];
  16862. }
  16863. if (length1 === 0) {
  16864. exit = true;
  16865. break;
  16866. }
  16867. }
  16868. array[dest--] = tmp[cursor2--];
  16869. if (--length2 === 1) {
  16870. exit = true;
  16871. break;
  16872. }
  16873. count2 = length2 - gallopLeft(array[cursor1], tmp, 0, length2, length2 - 1, compare);
  16874. if (count2 !== 0) {
  16875. dest -= count2;
  16876. cursor2 -= count2;
  16877. length2 -= count2;
  16878. customDest = dest + 1;
  16879. customCursor = cursor2 + 1;
  16880. for (i = 0; i < count2; i++) {
  16881. array[customDest + i] = tmp[customCursor + i];
  16882. }
  16883. if (length2 <= 1) {
  16884. exit = true;
  16885. break;
  16886. }
  16887. }
  16888. array[dest--] = array[cursor1--];
  16889. if (--length1 === 0) {
  16890. exit = true;
  16891. break;
  16892. }
  16893. _minGallop--;
  16894. } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING);
  16895. if (exit) {
  16896. break;
  16897. }
  16898. if (_minGallop < 0) {
  16899. _minGallop = 0;
  16900. }
  16901. _minGallop += 2;
  16902. }
  16903. minGallop = _minGallop;
  16904. if (minGallop < 1) {
  16905. minGallop = 1;
  16906. }
  16907. if (length2 === 1) {
  16908. dest -= length1;
  16909. cursor1 -= length1;
  16910. customDest = dest + 1;
  16911. customCursor = cursor1 + 1;
  16912. for (i = length1 - 1; i >= 0; i--) {
  16913. array[customDest + i] = array[customCursor + i];
  16914. }
  16915. array[dest] = tmp[cursor2];
  16916. }
  16917. else if (length2 === 0) {
  16918. throw new Error();
  16919. // throw new Error('mergeHigh preconditions were not respected');
  16920. }
  16921. else {
  16922. customCursor = dest - (length2 - 1);
  16923. for (i = 0; i < length2; i++) {
  16924. array[customCursor + i] = tmp[i];
  16925. }
  16926. }
  16927. }
  16928. this.mergeRuns = mergeRuns;
  16929. this.forceMergeRuns = forceMergeRuns;
  16930. this.pushRun = pushRun;
  16931. }
  16932. function sort(array, compare, lo, hi) {
  16933. if (!lo) {
  16934. lo = 0;
  16935. }
  16936. if (!hi) {
  16937. hi = array.length;
  16938. }
  16939. var remaining = hi - lo;
  16940. if (remaining < 2) {
  16941. return;
  16942. }
  16943. var runLength = 0;
  16944. if (remaining < DEFAULT_MIN_MERGE) {
  16945. runLength = makeAscendingRun(array, lo, hi, compare);
  16946. binaryInsertionSort(array, lo, hi, lo + runLength, compare);
  16947. return;
  16948. }
  16949. var ts = new TimSort(array, compare);
  16950. var minRun = minRunLength(remaining);
  16951. do {
  16952. runLength = makeAscendingRun(array, lo, hi, compare);
  16953. if (runLength < minRun) {
  16954. var force = remaining;
  16955. if (force > minRun) {
  16956. force = minRun;
  16957. }
  16958. binaryInsertionSort(array, lo, lo + force, lo + runLength, compare);
  16959. runLength = force;
  16960. }
  16961. ts.pushRun(lo, runLength);
  16962. ts.mergeRuns();
  16963. remaining -= runLength;
  16964. lo += runLength;
  16965. } while (remaining !== 0);
  16966. ts.forceMergeRuns();
  16967. }
  16968. module.exports = sort;
  16969. /***/ },
  16970. /* 87 */
  16971. /***/ function(module, exports, __webpack_require__) {
  16972. 'use strict';
  16973. /**
  16974. * 动画主类, 调度和管理所有动画控制器
  16975. *
  16976. * @module zrender/animation/Animation
  16977. * @author pissang(https://github.com/pissang)
  16978. */
  16979. // TODO Additive animation
  16980. // http://iosoteric.com/additive-animations-animatewithduration-in-ios-8/
  16981. // https://developer.apple.com/videos/wwdc2014/#236
  16982. var util = __webpack_require__(4);
  16983. var Dispatcher = __webpack_require__(88).Dispatcher;
  16984. var requestAnimationFrame = __webpack_require__(89);
  16985. var Animator = __webpack_require__(28);
  16986. /**
  16987. * @typedef {Object} IZRenderStage
  16988. * @property {Function} update
  16989. */
  16990. /**
  16991. * @alias module:zrender/animation/Animation
  16992. * @constructor
  16993. * @param {Object} [options]
  16994. * @param {Function} [options.onframe]
  16995. * @param {IZRenderStage} [options.stage]
  16996. * @example
  16997. * var animation = new Animation();
  16998. * var obj = {
  16999. * x: 100,
  17000. * y: 100
  17001. * };
  17002. * animation.animate(node.position)
  17003. * .when(1000, {
  17004. * x: 500,
  17005. * y: 500
  17006. * })
  17007. * .when(2000, {
  17008. * x: 100,
  17009. * y: 100
  17010. * })
  17011. * .start('spline');
  17012. */
  17013. var Animation = function (options) {
  17014. options = options || {};
  17015. this.stage = options.stage || {};
  17016. this.onframe = options.onframe || function() {};
  17017. // private properties
  17018. this._clips = [];
  17019. this._running = false;
  17020. this._time;
  17021. this._pausedTime;
  17022. this._pauseStart;
  17023. this._paused = false;
  17024. Dispatcher.call(this);
  17025. };
  17026. Animation.prototype = {
  17027. constructor: Animation,
  17028. /**
  17029. * 添加 clip
  17030. * @param {module:zrender/animation/Clip} clip
  17031. */
  17032. addClip: function (clip) {
  17033. this._clips.push(clip);
  17034. },
  17035. /**
  17036. * 添加 animator
  17037. * @param {module:zrender/animation/Animator} animator
  17038. */
  17039. addAnimator: function (animator) {
  17040. animator.animation = this;
  17041. var clips = animator.getClips();
  17042. for (var i = 0; i < clips.length; i++) {
  17043. this.addClip(clips[i]);
  17044. }
  17045. },
  17046. /**
  17047. * 删除动画片段
  17048. * @param {module:zrender/animation/Clip} clip
  17049. */
  17050. removeClip: function(clip) {
  17051. var idx = util.indexOf(this._clips, clip);
  17052. if (idx >= 0) {
  17053. this._clips.splice(idx, 1);
  17054. }
  17055. },
  17056. /**
  17057. * 删除动画片段
  17058. * @param {module:zrender/animation/Animator} animator
  17059. */
  17060. removeAnimator: function (animator) {
  17061. var clips = animator.getClips();
  17062. for (var i = 0; i < clips.length; i++) {
  17063. this.removeClip(clips[i]);
  17064. }
  17065. animator.animation = null;
  17066. },
  17067. _update: function() {
  17068. var time = new Date().getTime() - this._pausedTime;
  17069. var delta = time - this._time;
  17070. var clips = this._clips;
  17071. var len = clips.length;
  17072. var deferredEvents = [];
  17073. var deferredClips = [];
  17074. for (var i = 0; i < len; i++) {
  17075. var clip = clips[i];
  17076. var e = clip.step(time, delta);
  17077. // Throw out the events need to be called after
  17078. // stage.update, like destroy
  17079. if (e) {
  17080. deferredEvents.push(e);
  17081. deferredClips.push(clip);
  17082. }
  17083. }
  17084. // Remove the finished clip
  17085. for (var i = 0; i < len;) {
  17086. if (clips[i]._needsRemove) {
  17087. clips[i] = clips[len - 1];
  17088. clips.pop();
  17089. len--;
  17090. }
  17091. else {
  17092. i++;
  17093. }
  17094. }
  17095. len = deferredEvents.length;
  17096. for (var i = 0; i < len; i++) {
  17097. deferredClips[i].fire(deferredEvents[i]);
  17098. }
  17099. this._time = time;
  17100. this.onframe(delta);
  17101. this.trigger('frame', delta);
  17102. if (this.stage.update) {
  17103. this.stage.update();
  17104. }
  17105. },
  17106. _startLoop: function () {
  17107. var self = this;
  17108. this._running = true;
  17109. function step() {
  17110. if (self._running) {
  17111. requestAnimationFrame(step);
  17112. !self._paused && self._update();
  17113. }
  17114. }
  17115. requestAnimationFrame(step);
  17116. },
  17117. /**
  17118. * 开始运行动画
  17119. */
  17120. start: function () {
  17121. this._time = new Date().getTime();
  17122. this._pausedTime = 0;
  17123. this._startLoop();
  17124. },
  17125. /**
  17126. * 停止运行动画
  17127. */
  17128. stop: function () {
  17129. this._running = false;
  17130. },
  17131. /**
  17132. * Pause
  17133. */
  17134. pause: function () {
  17135. if (!this._paused) {
  17136. this._pauseStart = new Date().getTime();
  17137. this._paused = true;
  17138. }
  17139. },
  17140. /**
  17141. * Resume
  17142. */
  17143. resume: function () {
  17144. if (this._paused) {
  17145. this._pausedTime += (new Date().getTime()) - this._pauseStart;
  17146. this._paused = false;
  17147. }
  17148. },
  17149. /**
  17150. * 清除所有动画片段
  17151. */
  17152. clear: function () {
  17153. this._clips = [];
  17154. },
  17155. /**
  17156. * 对一个目标创建一个animator对象,可以指定目标中的属性使用动画
  17157. * @param {Object} target
  17158. * @param {Object} options
  17159. * @param {boolean} [options.loop=false] 是否循环播放动画
  17160. * @param {Function} [options.getter=null]
  17161. * 如果指定getter函数,会通过getter函数取属性值
  17162. * @param {Function} [options.setter=null]
  17163. * 如果指定setter函数,会通过setter函数设置属性值
  17164. * @return {module:zrender/animation/Animation~Animator}
  17165. */
  17166. // TODO Gap
  17167. animate: function (target, options) {
  17168. options = options || {};
  17169. var animator = new Animator(
  17170. target,
  17171. options.loop,
  17172. options.getter,
  17173. options.setter
  17174. );
  17175. this.addAnimator(animator);
  17176. return animator;
  17177. }
  17178. };
  17179. util.mixin(Animation, Dispatcher);
  17180. module.exports = Animation;
  17181. /***/ },
  17182. /* 88 */
  17183. /***/ function(module, exports, __webpack_require__) {
  17184. 'use strict';
  17185. /**
  17186. * 事件辅助类
  17187. * @module zrender/core/event
  17188. * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
  17189. */
  17190. var Eventful = __webpack_require__(25);
  17191. var env = __webpack_require__(2);
  17192. var isDomLevel2 = (typeof window !== 'undefined') && !!window.addEventListener;
  17193. function getBoundingClientRect(el) {
  17194. // BlackBerry 5, iOS 3 (original iPhone) don't have getBoundingRect
  17195. return el.getBoundingClientRect ? el.getBoundingClientRect() : {left: 0, top: 0};
  17196. }
  17197. // `calculate` is optional, default false
  17198. function clientToLocal(el, e, out, calculate) {
  17199. out = out || {};
  17200. // According to the W3C Working Draft, offsetX and offsetY should be relative
  17201. // to the padding edge of the target element. The only browser using this convention
  17202. // is IE. Webkit uses the border edge, Opera uses the content edge, and FireFox does
  17203. // not support the properties.
  17204. // (see http://www.jacklmoore.com/notes/mouse-position/)
  17205. // In zr painter.dom, padding edge equals to border edge.
  17206. // FIXME
  17207. // When mousemove event triggered on ec tooltip, target is not zr painter.dom, and
  17208. // offsetX/Y is relative to e.target, where the calculation of zrX/Y via offsetX/Y
  17209. // is too complex. So css-transfrom dont support in this case temporarily.
  17210. if (calculate || !env.canvasSupported) {
  17211. defaultGetZrXY(el, e, out);
  17212. }
  17213. // Caution: In FireFox, layerX/layerY Mouse position relative to the closest positioned
  17214. // ancestor element, so we should make sure el is positioned (e.g., not position:static).
  17215. // BTW1, Webkit don't return the same results as FF in non-simple cases (like add
  17216. // zoom-factor, overflow / opacity layers, transforms ...)
  17217. // BTW2, (ev.offsetY || ev.pageY - $(ev.target).offset().top) is not correct in preserve-3d.
  17218. // <https://bugs.jquery.com/ticket/8523#comment:14>
  17219. // BTW3, In ff, offsetX/offsetY is always 0.
  17220. else if (env.browser.firefox && e.layerX != null && e.layerX !== e.offsetX) {
  17221. out.zrX = e.layerX;
  17222. out.zrY = e.layerY;
  17223. }
  17224. // For IE6+, chrome, safari, opera. (When will ff support offsetX?)
  17225. else if (e.offsetX != null) {
  17226. out.zrX = e.offsetX;
  17227. out.zrY = e.offsetY;
  17228. }
  17229. // For some other device, e.g., IOS safari.
  17230. else {
  17231. defaultGetZrXY(el, e, out);
  17232. }
  17233. return out;
  17234. }
  17235. function defaultGetZrXY(el, e, out) {
  17236. // This well-known method below does not support css transform.
  17237. var box = getBoundingClientRect(el);
  17238. out.zrX = e.clientX - box.left;
  17239. out.zrY = e.clientY - box.top;
  17240. }
  17241. /**
  17242. * 如果存在第三方嵌入的一些dom触发的事件,或touch事件,需要转换一下事件坐标.
  17243. * `calculate` is optional, default false.
  17244. */
  17245. function normalizeEvent(el, e, calculate) {
  17246. e = e || window.event;
  17247. if (e.zrX != null) {
  17248. return e;
  17249. }
  17250. var eventType = e.type;
  17251. var isTouch = eventType && eventType.indexOf('touch') >= 0;
  17252. if (!isTouch) {
  17253. clientToLocal(el, e, e, calculate);
  17254. e.zrDelta = (e.wheelDelta) ? e.wheelDelta / 120 : -(e.detail || 0) / 3;
  17255. }
  17256. else {
  17257. var touch = eventType != 'touchend'
  17258. ? e.targetTouches[0]
  17259. : e.changedTouches[0];
  17260. touch && clientToLocal(el, touch, e, calculate);
  17261. }
  17262. return e;
  17263. }
  17264. function addEventListener(el, name, handler) {
  17265. if (isDomLevel2) {
  17266. el.addEventListener(name, handler);
  17267. }
  17268. else {
  17269. el.attachEvent('on' + name, handler);
  17270. }
  17271. }
  17272. function removeEventListener(el, name, handler) {
  17273. if (isDomLevel2) {
  17274. el.removeEventListener(name, handler);
  17275. }
  17276. else {
  17277. el.detachEvent('on' + name, handler);
  17278. }
  17279. }
  17280. /**
  17281. * preventDefault and stopPropagation.
  17282. * Notice: do not do that in zrender. Upper application
  17283. * do that if necessary.
  17284. *
  17285. * @memberOf module:zrender/core/event
  17286. * @method
  17287. * @param {Event} e : event对象
  17288. */
  17289. var stop = isDomLevel2
  17290. ? function (e) {
  17291. e.preventDefault();
  17292. e.stopPropagation();
  17293. e.cancelBubble = true;
  17294. }
  17295. : function (e) {
  17296. e.returnValue = false;
  17297. e.cancelBubble = true;
  17298. };
  17299. module.exports = {
  17300. clientToLocal: clientToLocal,
  17301. normalizeEvent: normalizeEvent,
  17302. addEventListener: addEventListener,
  17303. removeEventListener: removeEventListener,
  17304. stop: stop,
  17305. // 做向上兼容
  17306. Dispatcher: Eventful
  17307. };
  17308. /***/ },
  17309. /* 89 */
  17310. /***/ function(module, exports) {
  17311. module.exports = (typeof window !== 'undefined' &&
  17312. (window.requestAnimationFrame
  17313. || window.msRequestAnimationFrame
  17314. || window.mozRequestAnimationFrame
  17315. || window.webkitRequestAnimationFrame))
  17316. || function (func) {
  17317. setTimeout(func, 16);
  17318. };
  17319. /***/ },
  17320. /* 90 */
  17321. /***/ function(module, exports, __webpack_require__) {
  17322. var eventTool = __webpack_require__(88);
  17323. var zrUtil = __webpack_require__(4);
  17324. var Eventful = __webpack_require__(25);
  17325. var env = __webpack_require__(2);
  17326. var GestureMgr = __webpack_require__(91);
  17327. var addEventListener = eventTool.addEventListener;
  17328. var removeEventListener = eventTool.removeEventListener;
  17329. var normalizeEvent = eventTool.normalizeEvent;
  17330. var TOUCH_CLICK_DELAY = 300;
  17331. var mouseHandlerNames = [
  17332. 'click', 'dblclick', 'mousewheel', 'mouseout',
  17333. 'mouseup', 'mousedown', 'mousemove', 'contextmenu'
  17334. ];
  17335. var touchHandlerNames = [
  17336. 'touchstart', 'touchend', 'touchmove'
  17337. ];
  17338. var pointerEventNames = {
  17339. pointerdown: 1, pointerup: 1, pointermove: 1, pointerout: 1
  17340. };
  17341. var pointerHandlerNames = zrUtil.map(mouseHandlerNames, function (name) {
  17342. var nm = name.replace('mouse', 'pointer');
  17343. return pointerEventNames[nm] ? nm : name;
  17344. });
  17345. function eventNameFix(name) {
  17346. return (name === 'mousewheel' && env.browser.firefox) ? 'DOMMouseScroll' : name;
  17347. }
  17348. function processGesture(proxy, event, stage) {
  17349. var gestureMgr = proxy._gestureMgr;
  17350. stage === 'start' && gestureMgr.clear();
  17351. var gestureInfo = gestureMgr.recognize(
  17352. event,
  17353. proxy.handler.findHover(event.zrX, event.zrY, null).target,
  17354. proxy.dom
  17355. );
  17356. stage === 'end' && gestureMgr.clear();
  17357. // Do not do any preventDefault here. Upper application do that if necessary.
  17358. if (gestureInfo) {
  17359. var type = gestureInfo.type;
  17360. event.gestureEvent = type;
  17361. proxy.handler.dispatchToElement({target: gestureInfo.target}, type, gestureInfo.event);
  17362. }
  17363. }
  17364. // function onMSGestureChange(proxy, event) {
  17365. // if (event.translationX || event.translationY) {
  17366. // // mousemove is carried by MSGesture to reduce the sensitivity.
  17367. // proxy.handler.dispatchToElement(event.target, 'mousemove', event);
  17368. // }
  17369. // if (event.scale !== 1) {
  17370. // event.pinchX = event.offsetX;
  17371. // event.pinchY = event.offsetY;
  17372. // event.pinchScale = event.scale;
  17373. // proxy.handler.dispatchToElement(event.target, 'pinch', event);
  17374. // }
  17375. // }
  17376. /**
  17377. * Prevent mouse event from being dispatched after Touch Events action
  17378. * @see <https://github.com/deltakosh/handjs/blob/master/src/hand.base.js>
  17379. * 1. Mobile browsers dispatch mouse events 300ms after touchend.
  17380. * 2. Chrome for Android dispatch mousedown for long-touch about 650ms
  17381. * Result: Blocking Mouse Events for 700ms.
  17382. */
  17383. function setTouchTimer(instance) {
  17384. instance._touching = true;
  17385. clearTimeout(instance._touchTimer);
  17386. instance._touchTimer = setTimeout(function () {
  17387. instance._touching = false;
  17388. }, 700);
  17389. }
  17390. var domHandlers = {
  17391. /**
  17392. * Mouse move handler
  17393. * @inner
  17394. * @param {Event} event
  17395. */
  17396. mousemove: function (event) {
  17397. event = normalizeEvent(this.dom, event);
  17398. this.trigger('mousemove', event);
  17399. },
  17400. /**
  17401. * Mouse out handler
  17402. * @inner
  17403. * @param {Event} event
  17404. */
  17405. mouseout: function (event) {
  17406. event = normalizeEvent(this.dom, event);
  17407. var element = event.toElement || event.relatedTarget;
  17408. if (element != this.dom) {
  17409. while (element && element.nodeType != 9) {
  17410. // 忽略包含在root中的dom引起的mouseOut
  17411. if (element === this.dom) {
  17412. return;
  17413. }
  17414. element = element.parentNode;
  17415. }
  17416. }
  17417. this.trigger('mouseout', event);
  17418. },
  17419. /**
  17420. * Touch开始响应函数
  17421. * @inner
  17422. * @param {Event} event
  17423. */
  17424. touchstart: function (event) {
  17425. // Default mouse behaviour should not be disabled here.
  17426. // For example, page may needs to be slided.
  17427. event = normalizeEvent(this.dom, event);
  17428. // Mark touch, which is useful in distinguish touch and
  17429. // mouse event in upper applicatoin.
  17430. event.zrByTouch = true;
  17431. this._lastTouchMoment = new Date();
  17432. processGesture(this, event, 'start');
  17433. // In touch device, trigger `mousemove`(`mouseover`) should
  17434. // be triggered, and must before `mousedown` triggered.
  17435. domHandlers.mousemove.call(this, event);
  17436. domHandlers.mousedown.call(this, event);
  17437. setTouchTimer(this);
  17438. },
  17439. /**
  17440. * Touch移动响应函数
  17441. * @inner
  17442. * @param {Event} event
  17443. */
  17444. touchmove: function (event) {
  17445. event = normalizeEvent(this.dom, event);
  17446. // Mark touch, which is useful in distinguish touch and
  17447. // mouse event in upper applicatoin.
  17448. event.zrByTouch = true;
  17449. processGesture(this, event, 'change');
  17450. // Mouse move should always be triggered no matter whether
  17451. // there is gestrue event, because mouse move and pinch may
  17452. // be used at the same time.
  17453. domHandlers.mousemove.call(this, event);
  17454. setTouchTimer(this);
  17455. },
  17456. /**
  17457. * Touch结束响应函数
  17458. * @inner
  17459. * @param {Event} event
  17460. */
  17461. touchend: function (event) {
  17462. event = normalizeEvent(this.dom, event);
  17463. // Mark touch, which is useful in distinguish touch and
  17464. // mouse event in upper applicatoin.
  17465. event.zrByTouch = true;
  17466. processGesture(this, event, 'end');
  17467. domHandlers.mouseup.call(this, event);
  17468. // Do not trigger `mouseout` here, in spite of `mousemove`(`mouseover`) is
  17469. // triggered in `touchstart`. This seems to be illogical, but by this mechanism,
  17470. // we can conveniently implement "hover style" in both PC and touch device just
  17471. // by listening to `mouseover` to add "hover style" and listening to `mouseout`
  17472. // to remove "hover style" on an element, without any additional code for
  17473. // compatibility. (`mouseout` will not be triggered in `touchend`, so "hover
  17474. // style" will remain for user view)
  17475. // click event should always be triggered no matter whether
  17476. // there is gestrue event. System click can not be prevented.
  17477. if (+new Date() - this._lastTouchMoment < TOUCH_CLICK_DELAY) {
  17478. domHandlers.click.call(this, event);
  17479. }
  17480. setTouchTimer(this);
  17481. },
  17482. pointerdown: function (event) {
  17483. domHandlers.mousedown.call(this, event);
  17484. // if (useMSGuesture(this, event)) {
  17485. // this._msGesture.addPointer(event.pointerId);
  17486. // }
  17487. },
  17488. pointermove: function (event) {
  17489. // FIXME
  17490. // pointermove is so sensitive that it always triggered when
  17491. // tap(click) on touch screen, which affect some judgement in
  17492. // upper application. So, we dont support mousemove on MS touch
  17493. // device yet.
  17494. if (!isPointerFromTouch(event)) {
  17495. domHandlers.mousemove.call(this, event);
  17496. }
  17497. },
  17498. pointerup: function (event) {
  17499. domHandlers.mouseup.call(this, event);
  17500. },
  17501. pointerout: function (event) {
  17502. // pointerout will be triggered when tap on touch screen
  17503. // (IE11+/Edge on MS Surface) after click event triggered,
  17504. // which is inconsistent with the mousout behavior we defined
  17505. // in touchend. So we unify them.
  17506. // (check domHandlers.touchend for detailed explanation)
  17507. if (!isPointerFromTouch(event)) {
  17508. domHandlers.mouseout.call(this, event);
  17509. }
  17510. }
  17511. };
  17512. function isPointerFromTouch(event) {
  17513. var pointerType = event.pointerType;
  17514. return pointerType === 'pen' || pointerType === 'touch';
  17515. }
  17516. // function useMSGuesture(handlerProxy, event) {
  17517. // return isPointerFromTouch(event) && !!handlerProxy._msGesture;
  17518. // }
  17519. // Common handlers
  17520. zrUtil.each(['click', 'mousedown', 'mouseup', 'mousewheel', 'dblclick', 'contextmenu'], function (name) {
  17521. domHandlers[name] = function (event) {
  17522. event = normalizeEvent(this.dom, event);
  17523. this.trigger(name, event);
  17524. };
  17525. });
  17526. /**
  17527. * 为控制类实例初始化dom 事件处理函数
  17528. *
  17529. * @inner
  17530. * @param {module:zrender/Handler} instance 控制类实例
  17531. */
  17532. function initDomHandler(instance) {
  17533. zrUtil.each(touchHandlerNames, function (name) {
  17534. instance._handlers[name] = zrUtil.bind(domHandlers[name], instance);
  17535. });
  17536. zrUtil.each(pointerHandlerNames, function (name) {
  17537. instance._handlers[name] = zrUtil.bind(domHandlers[name], instance);
  17538. });
  17539. zrUtil.each(mouseHandlerNames, function (name) {
  17540. instance._handlers[name] = makeMouseHandler(domHandlers[name], instance);
  17541. });
  17542. function makeMouseHandler(fn, instance) {
  17543. return function () {
  17544. if (instance._touching) {
  17545. return;
  17546. }
  17547. return fn.apply(instance, arguments);
  17548. };
  17549. }
  17550. }
  17551. function HandlerDomProxy(dom) {
  17552. Eventful.call(this);
  17553. this.dom = dom;
  17554. /**
  17555. * @private
  17556. * @type {boolean}
  17557. */
  17558. this._touching = false;
  17559. /**
  17560. * @private
  17561. * @type {number}
  17562. */
  17563. this._touchTimer;
  17564. /**
  17565. * @private
  17566. * @type {module:zrender/core/GestureMgr}
  17567. */
  17568. this._gestureMgr = new GestureMgr();
  17569. this._handlers = {};
  17570. initDomHandler(this);
  17571. if (env.pointerEventsSupported) { // Only IE11+/Edge
  17572. // 1. On devices that both enable touch and mouse (e.g., MS Surface and lenovo X240),
  17573. // IE11+/Edge do not trigger touch event, but trigger pointer event and mouse event
  17574. // at the same time.
  17575. // 2. On MS Surface, it probablely only trigger mousedown but no mouseup when tap on
  17576. // screen, which do not occurs in pointer event.
  17577. // So we use pointer event to both detect touch gesture and mouse behavior.
  17578. mountHandlers(pointerHandlerNames, this);
  17579. // FIXME
  17580. // Note: MS Gesture require CSS touch-action set. But touch-action is not reliable,
  17581. // which does not prevent defuault behavior occasionally (which may cause view port
  17582. // zoomed in but use can not zoom it back). And event.preventDefault() does not work.
  17583. // So we have to not to use MSGesture and not to support touchmove and pinch on MS
  17584. // touch screen. And we only support click behavior on MS touch screen now.
  17585. // MS Gesture Event is only supported on IE11+/Edge and on Windows 8+.
  17586. // We dont support touch on IE on win7.
  17587. // See <https://msdn.microsoft.com/en-us/library/dn433243(v=vs.85).aspx>
  17588. // if (typeof MSGesture === 'function') {
  17589. // (this._msGesture = new MSGesture()).target = dom; // jshint ignore:line
  17590. // dom.addEventListener('MSGestureChange', onMSGestureChange);
  17591. // }
  17592. }
  17593. else {
  17594. if (env.touchEventsSupported) {
  17595. mountHandlers(touchHandlerNames, this);
  17596. // Handler of 'mouseout' event is needed in touch mode, which will be mounted below.
  17597. // addEventListener(root, 'mouseout', this._mouseoutHandler);
  17598. }
  17599. // 1. Considering some devices that both enable touch and mouse event (like on MS Surface
  17600. // and lenovo X240, @see #2350), we make mouse event be always listened, otherwise
  17601. // mouse event can not be handle in those devices.
  17602. // 2. On MS Surface, Chrome will trigger both touch event and mouse event. How to prevent
  17603. // mouseevent after touch event triggered, see `setTouchTimer`.
  17604. mountHandlers(mouseHandlerNames, this);
  17605. }
  17606. function mountHandlers(handlerNames, instance) {
  17607. zrUtil.each(handlerNames, function (name) {
  17608. addEventListener(dom, eventNameFix(name), instance._handlers[name]);
  17609. }, instance);
  17610. }
  17611. }
  17612. var handlerDomProxyProto = HandlerDomProxy.prototype;
  17613. handlerDomProxyProto.dispose = function () {
  17614. var handlerNames = mouseHandlerNames.concat(touchHandlerNames);
  17615. for (var i = 0; i < handlerNames.length; i++) {
  17616. var name = handlerNames[i];
  17617. removeEventListener(this.dom, eventNameFix(name), this._handlers[name]);
  17618. }
  17619. };
  17620. handlerDomProxyProto.setCursor = function (cursorStyle) {
  17621. this.dom.style.cursor = cursorStyle || 'default';
  17622. };
  17623. zrUtil.mixin(HandlerDomProxy, Eventful);
  17624. module.exports = HandlerDomProxy;
  17625. /***/ },
  17626. /* 91 */
  17627. /***/ function(module, exports, __webpack_require__) {
  17628. 'use strict';
  17629. /**
  17630. * Only implements needed gestures for mobile.
  17631. */
  17632. var eventUtil = __webpack_require__(88);
  17633. var GestureMgr = function () {
  17634. /**
  17635. * @private
  17636. * @type {Array.<Object>}
  17637. */
  17638. this._track = [];
  17639. };
  17640. GestureMgr.prototype = {
  17641. constructor: GestureMgr,
  17642. recognize: function (event, target, root) {
  17643. this._doTrack(event, target, root);
  17644. return this._recognize(event);
  17645. },
  17646. clear: function () {
  17647. this._track.length = 0;
  17648. return this;
  17649. },
  17650. _doTrack: function (event, target, root) {
  17651. var touches = event.touches;
  17652. if (!touches) {
  17653. return;
  17654. }
  17655. var trackItem = {
  17656. points: [],
  17657. touches: [],
  17658. target: target,
  17659. event: event
  17660. };
  17661. for (var i = 0, len = touches.length; i < len; i++) {
  17662. var touch = touches[i];
  17663. var pos = eventUtil.clientToLocal(root, touch, {});
  17664. trackItem.points.push([pos.zrX, pos.zrY]);
  17665. trackItem.touches.push(touch);
  17666. }
  17667. this._track.push(trackItem);
  17668. },
  17669. _recognize: function (event) {
  17670. for (var eventName in recognizers) {
  17671. if (recognizers.hasOwnProperty(eventName)) {
  17672. var gestureInfo = recognizers[eventName](this._track, event);
  17673. if (gestureInfo) {
  17674. return gestureInfo;
  17675. }
  17676. }
  17677. }
  17678. }
  17679. };
  17680. function dist(pointPair) {
  17681. var dx = pointPair[1][0] - pointPair[0][0];
  17682. var dy = pointPair[1][1] - pointPair[0][1];
  17683. return Math.sqrt(dx * dx + dy * dy);
  17684. }
  17685. function center(pointPair) {
  17686. return [
  17687. (pointPair[0][0] + pointPair[1][0]) / 2,
  17688. (pointPair[0][1] + pointPair[1][1]) / 2
  17689. ];
  17690. }
  17691. var recognizers = {
  17692. pinch: function (track, event) {
  17693. var trackLen = track.length;
  17694. if (!trackLen) {
  17695. return;
  17696. }
  17697. var pinchEnd = (track[trackLen - 1] || {}).points;
  17698. var pinchPre = (track[trackLen - 2] || {}).points || pinchEnd;
  17699. if (pinchPre
  17700. && pinchPre.length > 1
  17701. && pinchEnd
  17702. && pinchEnd.length > 1
  17703. ) {
  17704. var pinchScale = dist(pinchEnd) / dist(pinchPre);
  17705. !isFinite(pinchScale) && (pinchScale = 1);
  17706. event.pinchScale = pinchScale;
  17707. var pinchCenter = center(pinchEnd);
  17708. event.pinchX = pinchCenter[0];
  17709. event.pinchY = pinchCenter[1];
  17710. return {
  17711. type: 'pinch',
  17712. target: track[0].target,
  17713. event: event
  17714. };
  17715. }
  17716. }
  17717. // Only pinch currently.
  17718. };
  17719. module.exports = GestureMgr;
  17720. /***/ },
  17721. /* 92 */
  17722. /***/ function(module, exports, __webpack_require__) {
  17723. 'use strict';
  17724. /**
  17725. * Default canvas painter
  17726. * @module zrender/Painter
  17727. * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
  17728. * errorrik (errorrik@gmail.com)
  17729. * pissang (https://www.github.com/pissang)
  17730. */
  17731. var config = __webpack_require__(34);
  17732. var util = __webpack_require__(4);
  17733. var log = __webpack_require__(33);
  17734. var BoundingRect = __webpack_require__(9);
  17735. var timsort = __webpack_require__(86);
  17736. var Layer = __webpack_require__(93);
  17737. var requestAnimationFrame = __webpack_require__(89);
  17738. // PENDIGN
  17739. // Layer exceeds MAX_PROGRESSIVE_LAYER_NUMBER may have some problem when flush directly second time.
  17740. //
  17741. // Maximum progressive layer. When exceeding this number. All elements will be drawed in the last layer.
  17742. var MAX_PROGRESSIVE_LAYER_NUMBER = 5;
  17743. function parseInt10(val) {
  17744. return parseInt(val, 10);
  17745. }
  17746. function isLayerValid(layer) {
  17747. if (!layer) {
  17748. return false;
  17749. }
  17750. if (layer.__builtin__) {
  17751. return true;
  17752. }
  17753. if (typeof(layer.resize) !== 'function'
  17754. || typeof(layer.refresh) !== 'function'
  17755. ) {
  17756. return false;
  17757. }
  17758. return true;
  17759. }
  17760. function preProcessLayer(layer) {
  17761. layer.__unusedCount++;
  17762. }
  17763. function postProcessLayer(layer) {
  17764. if (layer.__unusedCount == 1) {
  17765. layer.clear();
  17766. }
  17767. }
  17768. var tmpRect = new BoundingRect(0, 0, 0, 0);
  17769. var viewRect = new BoundingRect(0, 0, 0, 0);
  17770. function isDisplayableCulled(el, width, height) {
  17771. tmpRect.copy(el.getBoundingRect());
  17772. if (el.transform) {
  17773. tmpRect.applyTransform(el.transform);
  17774. }
  17775. viewRect.width = width;
  17776. viewRect.height = height;
  17777. return !tmpRect.intersect(viewRect);
  17778. }
  17779. function isClipPathChanged(clipPaths, prevClipPaths) {
  17780. if (clipPaths == prevClipPaths) { // Can both be null or undefined
  17781. return false;
  17782. }
  17783. if (!clipPaths || !prevClipPaths || (clipPaths.length !== prevClipPaths.length)) {
  17784. return true;
  17785. }
  17786. for (var i = 0; i < clipPaths.length; i++) {
  17787. if (clipPaths[i] !== prevClipPaths[i]) {
  17788. return true;
  17789. }
  17790. }
  17791. }
  17792. function doClip(clipPaths, ctx) {
  17793. for (var i = 0; i < clipPaths.length; i++) {
  17794. var clipPath = clipPaths[i];
  17795. clipPath.setTransform(ctx);
  17796. ctx.beginPath();
  17797. clipPath.buildPath(ctx, clipPath.shape);
  17798. ctx.clip();
  17799. // Transform back
  17800. clipPath.restoreTransform(ctx);
  17801. }
  17802. }
  17803. function createRoot(width, height) {
  17804. var domRoot = document.createElement('div');
  17805. // domRoot.onselectstart = returnFalse; // 避免页面选中的尴尬
  17806. domRoot.style.cssText = [
  17807. 'position:relative',
  17808. 'overflow:hidden',
  17809. 'width:' + width + 'px',
  17810. 'height:' + height + 'px',
  17811. 'padding:0',
  17812. 'margin:0',
  17813. 'border-width:0'
  17814. ].join(';') + ';';
  17815. return domRoot;
  17816. }
  17817. /**
  17818. * @alias module:zrender/Painter
  17819. * @constructor
  17820. * @param {HTMLElement} root 绘图容器
  17821. * @param {module:zrender/Storage} storage
  17822. * @param {Ojbect} opts
  17823. */
  17824. var Painter = function (root, storage, opts) {
  17825. // In node environment using node-canvas
  17826. var singleCanvas = !root.nodeName // In node ?
  17827. || root.nodeName.toUpperCase() === 'CANVAS';
  17828. this._opts = opts = util.extend({}, opts || {});
  17829. /**
  17830. * @type {number}
  17831. */
  17832. this.dpr = opts.devicePixelRatio || config.devicePixelRatio;
  17833. /**
  17834. * @type {boolean}
  17835. * @private
  17836. */
  17837. this._singleCanvas = singleCanvas;
  17838. /**
  17839. * 绘图容器
  17840. * @type {HTMLElement}
  17841. */
  17842. this.root = root;
  17843. var rootStyle = root.style;
  17844. if (rootStyle) {
  17845. rootStyle['-webkit-tap-highlight-color'] = 'transparent';
  17846. rootStyle['-webkit-user-select'] =
  17847. rootStyle['user-select'] =
  17848. rootStyle['-webkit-touch-callout'] = 'none';
  17849. root.innerHTML = '';
  17850. }
  17851. /**
  17852. * @type {module:zrender/Storage}
  17853. */
  17854. this.storage = storage;
  17855. /**
  17856. * @type {Array.<number>}
  17857. * @private
  17858. */
  17859. var zlevelList = this._zlevelList = [];
  17860. /**
  17861. * @type {Object.<string, module:zrender/Layer>}
  17862. * @private
  17863. */
  17864. var layers = this._layers = {};
  17865. /**
  17866. * @type {Object.<string, Object>}
  17867. * @type {private}
  17868. */
  17869. this._layerConfig = {};
  17870. if (!singleCanvas) {
  17871. this._width = this._getSize(0);
  17872. this._height = this._getSize(1);
  17873. var domRoot = this._domRoot = createRoot(
  17874. this._width, this._height
  17875. );
  17876. root.appendChild(domRoot);
  17877. }
  17878. else {
  17879. if (opts.width != null) {
  17880. root.width = opts.width;
  17881. }
  17882. if (opts.height != null) {
  17883. root.height = opts.height;
  17884. }
  17885. // Use canvas width and height directly
  17886. var width = root.width;
  17887. var height = root.height;
  17888. this._width = width;
  17889. this._height = height;
  17890. // Create layer if only one given canvas
  17891. // Device pixel ratio is fixed to 1 because given canvas has its specified width and height
  17892. var mainLayer = new Layer(root, this, 1);
  17893. mainLayer.initContext();
  17894. // FIXME Use canvas width and height
  17895. // mainLayer.resize(width, height);
  17896. layers[0] = mainLayer;
  17897. zlevelList.push(0);
  17898. this._domRoot = root;
  17899. }
  17900. // Layers for progressive rendering
  17901. this._progressiveLayers = [];
  17902. /**
  17903. * @type {module:zrender/Layer}
  17904. * @private
  17905. */
  17906. this._hoverlayer;
  17907. this._hoverElements = [];
  17908. };
  17909. Painter.prototype = {
  17910. constructor: Painter,
  17911. /**
  17912. * If painter use a single canvas
  17913. * @return {boolean}
  17914. */
  17915. isSingleCanvas: function () {
  17916. return this._singleCanvas;
  17917. },
  17918. /**
  17919. * @return {HTMLDivElement}
  17920. */
  17921. getViewportRoot: function () {
  17922. return this._domRoot;
  17923. },
  17924. /**
  17925. * 刷新
  17926. * @param {boolean} [paintAll=false] 强制绘制所有displayable
  17927. */
  17928. refresh: function (paintAll) {
  17929. var list = this.storage.getDisplayList(true);
  17930. var zlevelList = this._zlevelList;
  17931. this._paintList(list, paintAll);
  17932. // Paint custum layers
  17933. for (var i = 0; i < zlevelList.length; i++) {
  17934. var z = zlevelList[i];
  17935. var layer = this._layers[z];
  17936. if (!layer.__builtin__ && layer.refresh) {
  17937. layer.refresh();
  17938. }
  17939. }
  17940. this.refreshHover();
  17941. if (this._progressiveLayers.length) {
  17942. this._startProgessive();
  17943. }
  17944. return this;
  17945. },
  17946. addHover: function (el, hoverStyle) {
  17947. if (el.__hoverMir) {
  17948. return;
  17949. }
  17950. var elMirror = new el.constructor({
  17951. style: el.style,
  17952. shape: el.shape
  17953. });
  17954. elMirror.__from = el;
  17955. el.__hoverMir = elMirror;
  17956. elMirror.setStyle(hoverStyle);
  17957. this._hoverElements.push(elMirror);
  17958. },
  17959. removeHover: function (el) {
  17960. var elMirror = el.__hoverMir;
  17961. var hoverElements = this._hoverElements;
  17962. var idx = util.indexOf(hoverElements, elMirror);
  17963. if (idx >= 0) {
  17964. hoverElements.splice(idx, 1);
  17965. }
  17966. el.__hoverMir = null;
  17967. },
  17968. clearHover: function (el) {
  17969. var hoverElements = this._hoverElements;
  17970. for (var i = 0; i < hoverElements.length; i++) {
  17971. var from = hoverElements[i].__from;
  17972. if (from) {
  17973. from.__hoverMir = null;
  17974. }
  17975. }
  17976. hoverElements.length = 0;
  17977. },
  17978. refreshHover: function () {
  17979. var hoverElements = this._hoverElements;
  17980. var len = hoverElements.length;
  17981. var hoverLayer = this._hoverlayer;
  17982. hoverLayer && hoverLayer.clear();
  17983. if (!len) {
  17984. return;
  17985. }
  17986. timsort(hoverElements, this.storage.displayableSortFunc);
  17987. // Use a extream large zlevel
  17988. // FIXME?
  17989. if (!hoverLayer) {
  17990. hoverLayer = this._hoverlayer = this.getLayer(1e5);
  17991. }
  17992. var scope = {};
  17993. hoverLayer.ctx.save();
  17994. for (var i = 0; i < len;) {
  17995. var el = hoverElements[i];
  17996. var originalEl = el.__from;
  17997. // Original el is removed
  17998. // PENDING
  17999. if (!(originalEl && originalEl.__zr)) {
  18000. hoverElements.splice(i, 1);
  18001. originalEl.__hoverMir = null;
  18002. len--;
  18003. continue;
  18004. }
  18005. i++;
  18006. // Use transform
  18007. // FIXME style and shape ?
  18008. if (!originalEl.invisible) {
  18009. el.transform = originalEl.transform;
  18010. el.invTransform = originalEl.invTransform;
  18011. el.__clipPaths = originalEl.__clipPaths;
  18012. // el.
  18013. this._doPaintEl(el, hoverLayer, true, scope);
  18014. }
  18015. }
  18016. hoverLayer.ctx.restore();
  18017. },
  18018. _startProgessive: function () {
  18019. var self = this;
  18020. if (!self._furtherProgressive) {
  18021. return;
  18022. }
  18023. // Use a token to stop progress steps triggered by
  18024. // previous zr.refresh calling.
  18025. var token = self._progressiveToken = +new Date();
  18026. self._progress++;
  18027. requestAnimationFrame(step);
  18028. function step() {
  18029. // In case refreshed or disposed
  18030. if (token === self._progressiveToken && self.storage) {
  18031. self._doPaintList(self.storage.getDisplayList());
  18032. if (self._furtherProgressive) {
  18033. self._progress++;
  18034. requestAnimationFrame(step);
  18035. }
  18036. else {
  18037. self._progressiveToken = -1;
  18038. }
  18039. }
  18040. }
  18041. },
  18042. _clearProgressive: function () {
  18043. this._progressiveToken = -1;
  18044. this._progress = 0;
  18045. util.each(this._progressiveLayers, function (layer) {
  18046. layer.__dirty && layer.clear();
  18047. });
  18048. },
  18049. _paintList: function (list, paintAll) {
  18050. if (paintAll == null) {
  18051. paintAll = false;
  18052. }
  18053. this._updateLayerStatus(list);
  18054. this._clearProgressive();
  18055. this.eachBuiltinLayer(preProcessLayer);
  18056. this._doPaintList(list, paintAll);
  18057. this.eachBuiltinLayer(postProcessLayer);
  18058. },
  18059. _doPaintList: function (list, paintAll) {
  18060. var currentLayer;
  18061. var currentZLevel;
  18062. var ctx;
  18063. // var invTransform = [];
  18064. var scope;
  18065. var progressiveLayerIdx = 0;
  18066. var currentProgressiveLayer;
  18067. var width = this._width;
  18068. var height = this._height;
  18069. var layerProgress;
  18070. var frame = this._progress;
  18071. function flushProgressiveLayer(layer) {
  18072. var dpr = ctx.dpr || 1;
  18073. ctx.save();
  18074. ctx.globalAlpha = 1;
  18075. ctx.shadowBlur = 0;
  18076. // Avoid layer don't clear in next progressive frame
  18077. currentLayer.__dirty = true;
  18078. ctx.setTransform(1, 0, 0, 1, 0, 0);
  18079. ctx.drawImage(layer.dom, 0, 0, width * dpr, height * dpr);
  18080. ctx.restore();
  18081. }
  18082. for (var i = 0, l = list.length; i < l; i++) {
  18083. var el = list[i];
  18084. var elZLevel = this._singleCanvas ? 0 : el.zlevel;
  18085. var elFrame = el.__frame;
  18086. // Flush at current context
  18087. // PENDING
  18088. if (elFrame < 0 && currentProgressiveLayer) {
  18089. flushProgressiveLayer(currentProgressiveLayer);
  18090. currentProgressiveLayer = null;
  18091. }
  18092. // Change draw layer
  18093. if (currentZLevel !== elZLevel) {
  18094. if (ctx) {
  18095. ctx.restore();
  18096. }
  18097. // Reset scope
  18098. scope = {};
  18099. // Only 0 zlevel if only has one canvas
  18100. currentZLevel = elZLevel;
  18101. currentLayer = this.getLayer(currentZLevel);
  18102. if (!currentLayer.__builtin__) {
  18103. log(
  18104. 'ZLevel ' + currentZLevel
  18105. + ' has been used by unkown layer ' + currentLayer.id
  18106. );
  18107. }
  18108. ctx = currentLayer.ctx;
  18109. ctx.save();
  18110. // Reset the count
  18111. currentLayer.__unusedCount = 0;
  18112. if (currentLayer.__dirty || paintAll) {
  18113. currentLayer.clear();
  18114. }
  18115. }
  18116. if (!(currentLayer.__dirty || paintAll)) {
  18117. continue;
  18118. }
  18119. if (elFrame >= 0) {
  18120. // Progressive layer changed
  18121. if (!currentProgressiveLayer) {
  18122. currentProgressiveLayer = this._progressiveLayers[
  18123. Math.min(progressiveLayerIdx++, MAX_PROGRESSIVE_LAYER_NUMBER - 1)
  18124. ];
  18125. currentProgressiveLayer.ctx.save();
  18126. currentProgressiveLayer.renderScope = {};
  18127. if (currentProgressiveLayer
  18128. && (currentProgressiveLayer.__progress > currentProgressiveLayer.__maxProgress)
  18129. ) {
  18130. // flushProgressiveLayer(currentProgressiveLayer);
  18131. // Quick jump all progressive elements
  18132. // All progressive element are not dirty, jump over and flush directly
  18133. i = currentProgressiveLayer.__nextIdxNotProg - 1;
  18134. // currentProgressiveLayer = null;
  18135. continue;
  18136. }
  18137. layerProgress = currentProgressiveLayer.__progress;
  18138. if (!currentProgressiveLayer.__dirty) {
  18139. // Keep rendering
  18140. frame = layerProgress;
  18141. }
  18142. currentProgressiveLayer.__progress = frame + 1;
  18143. }
  18144. if (elFrame === frame) {
  18145. this._doPaintEl(el, currentProgressiveLayer, true, currentProgressiveLayer.renderScope);
  18146. }
  18147. }
  18148. else {
  18149. this._doPaintEl(el, currentLayer, paintAll, scope);
  18150. }
  18151. el.__dirty = false;
  18152. }
  18153. if (currentProgressiveLayer) {
  18154. flushProgressiveLayer(currentProgressiveLayer);
  18155. }
  18156. // Restore the lastLayer ctx
  18157. ctx && ctx.restore();
  18158. // If still has clipping state
  18159. // if (scope.prevElClipPaths) {
  18160. // ctx.restore();
  18161. // }
  18162. this._furtherProgressive = false;
  18163. util.each(this._progressiveLayers, function (layer) {
  18164. if (layer.__maxProgress >= layer.__progress) {
  18165. this._furtherProgressive = true;
  18166. }
  18167. }, this);
  18168. },
  18169. _doPaintEl: function (el, currentLayer, forcePaint, scope) {
  18170. var ctx = currentLayer.ctx;
  18171. var m = el.transform;
  18172. if (
  18173. (currentLayer.__dirty || forcePaint)
  18174. // Ignore invisible element
  18175. && !el.invisible
  18176. // Ignore transparent element
  18177. && el.style.opacity !== 0
  18178. // Ignore scale 0 element, in some environment like node-canvas
  18179. // Draw a scale 0 element can cause all following draw wrong
  18180. // And setTransform with scale 0 will cause set back transform failed.
  18181. && !(m && !m[0] && !m[3])
  18182. // Ignore culled element
  18183. && !(el.culling && isDisplayableCulled(el, this._width, this._height))
  18184. ) {
  18185. var clipPaths = el.__clipPaths;
  18186. // Optimize when clipping on group with several elements
  18187. if (scope.prevClipLayer !== currentLayer
  18188. || isClipPathChanged(clipPaths, scope.prevElClipPaths)
  18189. ) {
  18190. // If has previous clipping state, restore from it
  18191. if (scope.prevElClipPaths) {
  18192. scope.prevClipLayer.ctx.restore();
  18193. scope.prevClipLayer = scope.prevElClipPaths = null;
  18194. // Reset prevEl since context has been restored
  18195. scope.prevEl = null;
  18196. }
  18197. // New clipping state
  18198. if (clipPaths) {
  18199. ctx.save();
  18200. doClip(clipPaths, ctx);
  18201. scope.prevClipLayer = currentLayer;
  18202. scope.prevElClipPaths = clipPaths;
  18203. }
  18204. }
  18205. el.beforeBrush && el.beforeBrush(ctx);
  18206. el.brush(ctx, scope.prevEl || null);
  18207. scope.prevEl = el;
  18208. el.afterBrush && el.afterBrush(ctx);
  18209. }
  18210. },
  18211. /**
  18212. * 获取 zlevel 所在层,如果不存在则会创建一个新的层
  18213. * @param {number} zlevel
  18214. * @return {module:zrender/Layer}
  18215. */
  18216. getLayer: function (zlevel) {
  18217. if (this._singleCanvas) {
  18218. return this._layers[0];
  18219. }
  18220. var layer = this._layers[zlevel];
  18221. if (!layer) {
  18222. // Create a new layer
  18223. layer = new Layer('zr_' + zlevel, this, this.dpr);
  18224. layer.__builtin__ = true;
  18225. if (this._layerConfig[zlevel]) {
  18226. util.merge(layer, this._layerConfig[zlevel], true);
  18227. }
  18228. this.insertLayer(zlevel, layer);
  18229. // Context is created after dom inserted to document
  18230. // Or excanvas will get 0px clientWidth and clientHeight
  18231. layer.initContext();
  18232. }
  18233. return layer;
  18234. },
  18235. insertLayer: function (zlevel, layer) {
  18236. var layersMap = this._layers;
  18237. var zlevelList = this._zlevelList;
  18238. var len = zlevelList.length;
  18239. var prevLayer = null;
  18240. var i = -1;
  18241. var domRoot = this._domRoot;
  18242. if (layersMap[zlevel]) {
  18243. log('ZLevel ' + zlevel + ' has been used already');
  18244. return;
  18245. }
  18246. // Check if is a valid layer
  18247. if (!isLayerValid(layer)) {
  18248. log('Layer of zlevel ' + zlevel + ' is not valid');
  18249. return;
  18250. }
  18251. if (len > 0 && zlevel > zlevelList[0]) {
  18252. for (i = 0; i < len - 1; i++) {
  18253. if (
  18254. zlevelList[i] < zlevel
  18255. && zlevelList[i + 1] > zlevel
  18256. ) {
  18257. break;
  18258. }
  18259. }
  18260. prevLayer = layersMap[zlevelList[i]];
  18261. }
  18262. zlevelList.splice(i + 1, 0, zlevel);
  18263. layersMap[zlevel] = layer;
  18264. // Vitual layer will not directly show on the screen.
  18265. // (It can be a WebGL layer and assigned to a ZImage element)
  18266. // But it still under management of zrender.
  18267. if (!layer.virtual) {
  18268. if (prevLayer) {
  18269. var prevDom = prevLayer.dom;
  18270. if (prevDom.nextSibling) {
  18271. domRoot.insertBefore(
  18272. layer.dom,
  18273. prevDom.nextSibling
  18274. );
  18275. }
  18276. else {
  18277. domRoot.appendChild(layer.dom);
  18278. }
  18279. }
  18280. else {
  18281. if (domRoot.firstChild) {
  18282. domRoot.insertBefore(layer.dom, domRoot.firstChild);
  18283. }
  18284. else {
  18285. domRoot.appendChild(layer.dom);
  18286. }
  18287. }
  18288. }
  18289. },
  18290. // Iterate each layer
  18291. eachLayer: function (cb, context) {
  18292. var zlevelList = this._zlevelList;
  18293. var z;
  18294. var i;
  18295. for (i = 0; i < zlevelList.length; i++) {
  18296. z = zlevelList[i];
  18297. cb.call(context, this._layers[z], z);
  18298. }
  18299. },
  18300. // Iterate each buildin layer
  18301. eachBuiltinLayer: function (cb, context) {
  18302. var zlevelList = this._zlevelList;
  18303. var layer;
  18304. var z;
  18305. var i;
  18306. for (i = 0; i < zlevelList.length; i++) {
  18307. z = zlevelList[i];
  18308. layer = this._layers[z];
  18309. if (layer.__builtin__) {
  18310. cb.call(context, layer, z);
  18311. }
  18312. }
  18313. },
  18314. // Iterate each other layer except buildin layer
  18315. eachOtherLayer: function (cb, context) {
  18316. var zlevelList = this._zlevelList;
  18317. var layer;
  18318. var z;
  18319. var i;
  18320. for (i = 0; i < zlevelList.length; i++) {
  18321. z = zlevelList[i];
  18322. layer = this._layers[z];
  18323. if (!layer.__builtin__) {
  18324. cb.call(context, layer, z);
  18325. }
  18326. }
  18327. },
  18328. /**
  18329. * 获取所有已创建的层
  18330. * @param {Array.<module:zrender/Layer>} [prevLayer]
  18331. */
  18332. getLayers: function () {
  18333. return this._layers;
  18334. },
  18335. _updateLayerStatus: function (list) {
  18336. var layers = this._layers;
  18337. var progressiveLayers = this._progressiveLayers;
  18338. var elCountsLastFrame = {};
  18339. var progressiveElCountsLastFrame = {};
  18340. this.eachBuiltinLayer(function (layer, z) {
  18341. elCountsLastFrame[z] = layer.elCount;
  18342. layer.elCount = 0;
  18343. layer.__dirty = false;
  18344. });
  18345. util.each(progressiveLayers, function (layer, idx) {
  18346. progressiveElCountsLastFrame[idx] = layer.elCount;
  18347. layer.elCount = 0;
  18348. layer.__dirty = false;
  18349. });
  18350. var progressiveLayerCount = 0;
  18351. var currentProgressiveLayer;
  18352. var lastProgressiveKey;
  18353. var frameCount = 0;
  18354. for (var i = 0, l = list.length; i < l; i++) {
  18355. var el = list[i];
  18356. var zlevel = this._singleCanvas ? 0 : el.zlevel;
  18357. var layer = layers[zlevel];
  18358. var elProgress = el.progressive;
  18359. if (layer) {
  18360. layer.elCount++;
  18361. layer.__dirty = layer.__dirty || el.__dirty;
  18362. }
  18363. /////// Update progressive
  18364. if (elProgress >= 0) {
  18365. // Fix wrong progressive sequence problem.
  18366. if (lastProgressiveKey !== elProgress) {
  18367. lastProgressiveKey = elProgress;
  18368. frameCount++;
  18369. }
  18370. var elFrame = el.__frame = frameCount - 1;
  18371. if (!currentProgressiveLayer) {
  18372. var idx = Math.min(progressiveLayerCount, MAX_PROGRESSIVE_LAYER_NUMBER - 1);
  18373. currentProgressiveLayer = progressiveLayers[idx];
  18374. if (!currentProgressiveLayer) {
  18375. currentProgressiveLayer = progressiveLayers[idx] = new Layer(
  18376. 'progressive', this, this.dpr
  18377. );
  18378. currentProgressiveLayer.initContext();
  18379. }
  18380. currentProgressiveLayer.__maxProgress = 0;
  18381. }
  18382. currentProgressiveLayer.__dirty = currentProgressiveLayer.__dirty || el.__dirty;
  18383. currentProgressiveLayer.elCount++;
  18384. currentProgressiveLayer.__maxProgress = Math.max(
  18385. currentProgressiveLayer.__maxProgress, elFrame
  18386. );
  18387. if (currentProgressiveLayer.__maxProgress >= currentProgressiveLayer.__progress) {
  18388. // Should keep rendering this layer because progressive rendering is not finished yet
  18389. layer.__dirty = true;
  18390. }
  18391. }
  18392. else {
  18393. el.__frame = -1;
  18394. if (currentProgressiveLayer) {
  18395. currentProgressiveLayer.__nextIdxNotProg = i;
  18396. progressiveLayerCount++;
  18397. currentProgressiveLayer = null;
  18398. }
  18399. }
  18400. }
  18401. if (currentProgressiveLayer) {
  18402. progressiveLayerCount++;
  18403. currentProgressiveLayer.__nextIdxNotProg = i;
  18404. }
  18405. // 层中的元素数量有发生变化
  18406. this.eachBuiltinLayer(function (layer, z) {
  18407. if (elCountsLastFrame[z] !== layer.elCount) {
  18408. layer.__dirty = true;
  18409. }
  18410. });
  18411. progressiveLayers.length = Math.min(progressiveLayerCount, MAX_PROGRESSIVE_LAYER_NUMBER);
  18412. util.each(progressiveLayers, function (layer, idx) {
  18413. if (progressiveElCountsLastFrame[idx] !== layer.elCount) {
  18414. el.__dirty = true;
  18415. }
  18416. if (layer.__dirty) {
  18417. layer.__progress = 0;
  18418. }
  18419. });
  18420. },
  18421. /**
  18422. * 清除hover层外所有内容
  18423. */
  18424. clear: function () {
  18425. this.eachBuiltinLayer(this._clearLayer);
  18426. return this;
  18427. },
  18428. _clearLayer: function (layer) {
  18429. layer.clear();
  18430. },
  18431. /**
  18432. * 修改指定zlevel的绘制参数
  18433. *
  18434. * @param {string} zlevel
  18435. * @param {Object} config 配置对象
  18436. * @param {string} [config.clearColor=0] 每次清空画布的颜色
  18437. * @param {string} [config.motionBlur=false] 是否开启动态模糊
  18438. * @param {number} [config.lastFrameAlpha=0.7]
  18439. * 在开启动态模糊的时候使用,与上一帧混合的alpha值,值越大尾迹越明显
  18440. */
  18441. configLayer: function (zlevel, config) {
  18442. if (config) {
  18443. var layerConfig = this._layerConfig;
  18444. if (!layerConfig[zlevel]) {
  18445. layerConfig[zlevel] = config;
  18446. }
  18447. else {
  18448. util.merge(layerConfig[zlevel], config, true);
  18449. }
  18450. var layer = this._layers[zlevel];
  18451. if (layer) {
  18452. util.merge(layer, layerConfig[zlevel], true);
  18453. }
  18454. }
  18455. },
  18456. /**
  18457. * 删除指定层
  18458. * @param {number} zlevel 层所在的zlevel
  18459. */
  18460. delLayer: function (zlevel) {
  18461. var layers = this._layers;
  18462. var zlevelList = this._zlevelList;
  18463. var layer = layers[zlevel];
  18464. if (!layer) {
  18465. return;
  18466. }
  18467. layer.dom.parentNode.removeChild(layer.dom);
  18468. delete layers[zlevel];
  18469. zlevelList.splice(util.indexOf(zlevelList, zlevel), 1);
  18470. },
  18471. /**
  18472. * 区域大小变化后重绘
  18473. */
  18474. resize: function (width, height) {
  18475. var domRoot = this._domRoot;
  18476. // FIXME Why ?
  18477. domRoot.style.display = 'none';
  18478. // Save input w/h
  18479. var opts = this._opts;
  18480. width != null && (opts.width = width);
  18481. height != null && (opts.height = height);
  18482. width = this._getSize(0);
  18483. height = this._getSize(1);
  18484. domRoot.style.display = '';
  18485. // 优化没有实际改变的resize
  18486. if (this._width != width || height != this._height) {
  18487. domRoot.style.width = width + 'px';
  18488. domRoot.style.height = height + 'px';
  18489. for (var id in this._layers) {
  18490. if (this._layers.hasOwnProperty(id)) {
  18491. this._layers[id].resize(width, height);
  18492. }
  18493. }
  18494. util.each(this._progressiveLayers, function (layer) {
  18495. layer.resize(width, height);
  18496. });
  18497. this.refresh(true);
  18498. }
  18499. this._width = width;
  18500. this._height = height;
  18501. return this;
  18502. },
  18503. /**
  18504. * 清除单独的一个层
  18505. * @param {number} zlevel
  18506. */
  18507. clearLayer: function (zlevel) {
  18508. var layer = this._layers[zlevel];
  18509. if (layer) {
  18510. layer.clear();
  18511. }
  18512. },
  18513. /**
  18514. * 释放
  18515. */
  18516. dispose: function () {
  18517. this.root.innerHTML = '';
  18518. this.root =
  18519. this.storage =
  18520. this._domRoot =
  18521. this._layers = null;
  18522. },
  18523. /**
  18524. * Get canvas which has all thing rendered
  18525. * @param {Object} opts
  18526. * @param {string} [opts.backgroundColor]
  18527. */
  18528. getRenderedCanvas: function (opts) {
  18529. opts = opts || {};
  18530. if (this._singleCanvas) {
  18531. return this._layers[0].dom;
  18532. }
  18533. var imageLayer = new Layer('image', this, opts.pixelRatio || this.dpr);
  18534. imageLayer.initContext();
  18535. imageLayer.clearColor = opts.backgroundColor;
  18536. imageLayer.clear();
  18537. var displayList = this.storage.getDisplayList(true);
  18538. var scope = {};
  18539. var zlevel;
  18540. var self = this;
  18541. function findAndDrawOtherLayer(smaller, larger) {
  18542. var zlevelList = self._zlevelList;
  18543. if (smaller == null) {
  18544. smaller = -Infinity;
  18545. }
  18546. var intermediateLayer;
  18547. for (var i = 0; i < zlevelList.length; i++) {
  18548. var z = zlevelList[i];
  18549. var layer = self._layers[z];
  18550. if (!layer.__builtin__ && z > smaller && z < larger) {
  18551. intermediateLayer = layer;
  18552. break;
  18553. }
  18554. }
  18555. if (intermediateLayer && intermediateLayer.renderToCanvas) {
  18556. imageLayer.ctx.save();
  18557. intermediateLayer.renderToCanvas(imageLayer.ctx);
  18558. imageLayer.ctx.restore();
  18559. }
  18560. }
  18561. for (var i = 0; i < displayList.length; i++) {
  18562. var el = displayList[i];
  18563. if (el.zlevel !== zlevel) {
  18564. findAndDrawOtherLayer(zlevel, el.zlevel);
  18565. zlevel = el.zlevel;
  18566. }
  18567. this._doPaintEl(el, imageLayer, true, scope);
  18568. }
  18569. findAndDrawOtherLayer(zlevel, Infinity);
  18570. return imageLayer.dom;
  18571. },
  18572. /**
  18573. * 获取绘图区域宽度
  18574. */
  18575. getWidth: function () {
  18576. return this._width;
  18577. },
  18578. /**
  18579. * 获取绘图区域高度
  18580. */
  18581. getHeight: function () {
  18582. return this._height;
  18583. },
  18584. _getSize: function (whIdx) {
  18585. var opts = this._opts;
  18586. var wh = ['width', 'height'][whIdx];
  18587. var cwh = ['clientWidth', 'clientHeight'][whIdx];
  18588. var plt = ['paddingLeft', 'paddingTop'][whIdx];
  18589. var prb = ['paddingRight', 'paddingBottom'][whIdx];
  18590. if (opts[wh] != null && opts[wh] !== 'auto') {
  18591. return parseFloat(opts[wh]);
  18592. }
  18593. var root = this.root;
  18594. var stl = document.defaultView.getComputedStyle(root);
  18595. return (
  18596. (root[cwh] || parseInt10(stl[wh]) || parseInt10(root.style[wh]))
  18597. - (parseInt10(stl[plt]) || 0)
  18598. - (parseInt10(stl[prb]) || 0)
  18599. ) | 0;
  18600. },
  18601. pathToImage: function (path, dpr) {
  18602. dpr = dpr || this.dpr;
  18603. var canvas = document.createElement('canvas');
  18604. var ctx = canvas.getContext('2d');
  18605. var rect = path.getBoundingRect();
  18606. var style = path.style;
  18607. var shadowBlurSize = style.shadowBlur;
  18608. var shadowOffsetX = style.shadowOffsetX;
  18609. var shadowOffsetY = style.shadowOffsetY;
  18610. var lineWidth = style.hasStroke() ? style.lineWidth : 0;
  18611. var leftMargin = Math.max(lineWidth / 2, -shadowOffsetX + shadowBlurSize);
  18612. var rightMargin = Math.max(lineWidth / 2, shadowOffsetX + shadowBlurSize);
  18613. var topMargin = Math.max(lineWidth / 2, -shadowOffsetY + shadowBlurSize);
  18614. var bottomMargin = Math.max(lineWidth / 2, shadowOffsetY + shadowBlurSize);
  18615. var width = rect.width + leftMargin + rightMargin;
  18616. var height = rect.height + topMargin + bottomMargin;
  18617. canvas.width = width * dpr;
  18618. canvas.height = height * dpr;
  18619. ctx.scale(dpr, dpr);
  18620. ctx.clearRect(0, 0, width, height);
  18621. ctx.dpr = dpr;
  18622. var pathTransform = {
  18623. position: path.position,
  18624. rotation: path.rotation,
  18625. scale: path.scale
  18626. };
  18627. path.position = [leftMargin - rect.x, topMargin - rect.y];
  18628. path.rotation = 0;
  18629. path.scale = [1, 1];
  18630. path.updateTransform();
  18631. if (path) {
  18632. path.brush(ctx);
  18633. }
  18634. var ImageShape = __webpack_require__(49);
  18635. var imgShape = new ImageShape({
  18636. style: {
  18637. x: 0,
  18638. y: 0,
  18639. image: canvas
  18640. }
  18641. });
  18642. if (pathTransform.position != null) {
  18643. imgShape.position = path.position = pathTransform.position;
  18644. }
  18645. if (pathTransform.rotation != null) {
  18646. imgShape.rotation = path.rotation = pathTransform.rotation;
  18647. }
  18648. if (pathTransform.scale != null) {
  18649. imgShape.scale = path.scale = pathTransform.scale;
  18650. }
  18651. return imgShape;
  18652. }
  18653. };
  18654. module.exports = Painter;
  18655. /***/ },
  18656. /* 93 */
  18657. /***/ function(module, exports, __webpack_require__) {
  18658. /**
  18659. * @module zrender/Layer
  18660. * @author pissang(https://www.github.com/pissang)
  18661. */
  18662. var util = __webpack_require__(4);
  18663. var config = __webpack_require__(34);
  18664. var Style = __webpack_require__(22);
  18665. var Pattern = __webpack_require__(46);
  18666. function returnFalse() {
  18667. return false;
  18668. }
  18669. /**
  18670. * 创建dom
  18671. *
  18672. * @inner
  18673. * @param {string} id dom id 待用
  18674. * @param {string} type dom type,such as canvas, div etc.
  18675. * @param {Painter} painter painter instance
  18676. * @param {number} number
  18677. */
  18678. function createDom(id, type, painter, dpr) {
  18679. var newDom = document.createElement(type);
  18680. var width = painter.getWidth();
  18681. var height = painter.getHeight();
  18682. var newDomStyle = newDom.style;
  18683. // 没append呢,请原谅我这样写,清晰~
  18684. newDomStyle.position = 'absolute';
  18685. newDomStyle.left = 0;
  18686. newDomStyle.top = 0;
  18687. newDomStyle.width = width + 'px';
  18688. newDomStyle.height = height + 'px';
  18689. newDom.width = width * dpr;
  18690. newDom.height = height * dpr;
  18691. // id不作为索引用,避免可能造成的重名,定义为私有属性
  18692. newDom.setAttribute('data-zr-dom-id', id);
  18693. return newDom;
  18694. }
  18695. /**
  18696. * @alias module:zrender/Layer
  18697. * @constructor
  18698. * @extends module:zrender/mixin/Transformable
  18699. * @param {string} id
  18700. * @param {module:zrender/Painter} painter
  18701. * @param {number} [dpr]
  18702. */
  18703. var Layer = function(id, painter, dpr) {
  18704. var dom;
  18705. dpr = dpr || config.devicePixelRatio;
  18706. if (typeof id === 'string') {
  18707. dom = createDom(id, 'canvas', painter, dpr);
  18708. }
  18709. // Not using isDom because in node it will return false
  18710. else if (util.isObject(id)) {
  18711. dom = id;
  18712. id = dom.id;
  18713. }
  18714. this.id = id;
  18715. this.dom = dom;
  18716. var domStyle = dom.style;
  18717. if (domStyle) { // Not in node
  18718. dom.onselectstart = returnFalse; // 避免页面选中的尴尬
  18719. domStyle['-webkit-user-select'] = 'none';
  18720. domStyle['user-select'] = 'none';
  18721. domStyle['-webkit-touch-callout'] = 'none';
  18722. domStyle['-webkit-tap-highlight-color'] = 'rgba(0,0,0,0)';
  18723. domStyle['padding'] = 0;
  18724. domStyle['margin'] = 0;
  18725. domStyle['border-width'] = 0;
  18726. }
  18727. this.domBack = null;
  18728. this.ctxBack = null;
  18729. this.painter = painter;
  18730. this.config = null;
  18731. // Configs
  18732. /**
  18733. * 每次清空画布的颜色
  18734. * @type {string}
  18735. * @default 0
  18736. */
  18737. this.clearColor = 0;
  18738. /**
  18739. * 是否开启动态模糊
  18740. * @type {boolean}
  18741. * @default false
  18742. */
  18743. this.motionBlur = false;
  18744. /**
  18745. * 在开启动态模糊的时候使用,与上一帧混合的alpha值,值越大尾迹越明显
  18746. * @type {number}
  18747. * @default 0.7
  18748. */
  18749. this.lastFrameAlpha = 0.7;
  18750. /**
  18751. * Layer dpr
  18752. * @type {number}
  18753. */
  18754. this.dpr = dpr;
  18755. };
  18756. Layer.prototype = {
  18757. constructor: Layer,
  18758. elCount: 0,
  18759. __dirty: true,
  18760. initContext: function () {
  18761. this.ctx = this.dom.getContext('2d');
  18762. this.ctx.dpr = this.dpr;
  18763. },
  18764. createBackBuffer: function () {
  18765. var dpr = this.dpr;
  18766. this.domBack = createDom('back-' + this.id, 'canvas', this.painter, dpr);
  18767. this.ctxBack = this.domBack.getContext('2d');
  18768. if (dpr != 1) {
  18769. this.ctxBack.scale(dpr, dpr);
  18770. }
  18771. },
  18772. /**
  18773. * @param {number} width
  18774. * @param {number} height
  18775. */
  18776. resize: function (width, height) {
  18777. var dpr = this.dpr;
  18778. var dom = this.dom;
  18779. var domStyle = dom.style;
  18780. var domBack = this.domBack;
  18781. domStyle.width = width + 'px';
  18782. domStyle.height = height + 'px';
  18783. dom.width = width * dpr;
  18784. dom.height = height * dpr;
  18785. if (domBack) {
  18786. domBack.width = width * dpr;
  18787. domBack.height = height * dpr;
  18788. if (dpr != 1) {
  18789. this.ctxBack.scale(dpr, dpr);
  18790. }
  18791. }
  18792. },
  18793. /**
  18794. * 清空该层画布
  18795. * @param {boolean} clearAll Clear all with out motion blur
  18796. */
  18797. clear: function (clearAll) {
  18798. var dom = this.dom;
  18799. var ctx = this.ctx;
  18800. var width = dom.width;
  18801. var height = dom.height;
  18802. var clearColor = this.clearColor;
  18803. var haveMotionBLur = this.motionBlur && !clearAll;
  18804. var lastFrameAlpha = this.lastFrameAlpha;
  18805. var dpr = this.dpr;
  18806. if (haveMotionBLur) {
  18807. if (!this.domBack) {
  18808. this.createBackBuffer();
  18809. }
  18810. this.ctxBack.globalCompositeOperation = 'copy';
  18811. this.ctxBack.drawImage(
  18812. dom, 0, 0,
  18813. width / dpr,
  18814. height / dpr
  18815. );
  18816. }
  18817. ctx.clearRect(0, 0, width, height);
  18818. if (clearColor) {
  18819. var clearColorGradientOrPattern;
  18820. // Gradient
  18821. if (clearColor.colorStops) {
  18822. // Cache canvas gradient
  18823. clearColorGradientOrPattern = clearColor.__canvasGradient || Style.getGradient(ctx, clearColor, {
  18824. x: 0,
  18825. y: 0,
  18826. width: width,
  18827. height: height
  18828. });
  18829. clearColor.__canvasGradient = clearColorGradientOrPattern;
  18830. }
  18831. // Pattern
  18832. else if (clearColor.image) {
  18833. clearColorGradientOrPattern = Pattern.prototype.getCanvasPattern.call(clearColor, ctx);
  18834. }
  18835. ctx.save();
  18836. ctx.fillStyle = clearColorGradientOrPattern || clearColor;
  18837. ctx.fillRect(0, 0, width, height);
  18838. ctx.restore();
  18839. }
  18840. if (haveMotionBLur) {
  18841. var domBack = this.domBack;
  18842. ctx.save();
  18843. ctx.globalAlpha = lastFrameAlpha;
  18844. ctx.drawImage(domBack, 0, 0, width, height);
  18845. ctx.restore();
  18846. }
  18847. }
  18848. };
  18849. module.exports = Layer;
  18850. /***/ },
  18851. /* 94 */
  18852. /***/ function(module, exports, __webpack_require__) {
  18853. var Gradient = __webpack_require__(66);
  18854. module.exports = function (ecModel) {
  18855. function encodeColor(seriesModel) {
  18856. var colorAccessPath = (seriesModel.visualColorAccessPath || 'itemStyle.normal.color').split('.');
  18857. var data = seriesModel.getData();
  18858. var color = seriesModel.get(colorAccessPath) // Set in itemStyle
  18859. || seriesModel.getColorFromPalette(seriesModel.get('name')); // Default color
  18860. // FIXME Set color function or use the platte color
  18861. data.setVisual('color', color);
  18862. // Only visible series has each data be visual encoded
  18863. if (!ecModel.isSeriesFiltered(seriesModel)) {
  18864. if (typeof color === 'function' && !(color instanceof Gradient)) {
  18865. data.each(function (idx) {
  18866. data.setItemVisual(
  18867. idx, 'color', color(seriesModel.getDataParams(idx))
  18868. );
  18869. });
  18870. }
  18871. // itemStyle in each data item
  18872. data.each(function (idx) {
  18873. var itemModel = data.getItemModel(idx);
  18874. var color = itemModel.get(colorAccessPath, true);
  18875. if (color != null) {
  18876. data.setItemVisual(idx, 'color', color);
  18877. }
  18878. });
  18879. }
  18880. }
  18881. ecModel.eachRawSeries(encodeColor);
  18882. };
  18883. /***/ },
  18884. /* 95 */
  18885. /***/ function(module, exports, __webpack_require__) {
  18886. // Compatitable with 2.0
  18887. var zrUtil = __webpack_require__(4);
  18888. var compatStyle = __webpack_require__(96);
  18889. function get(opt, path) {
  18890. path = path.split(',');
  18891. var obj = opt;
  18892. for (var i = 0; i < path.length; i++) {
  18893. obj = obj && obj[path[i]];
  18894. if (obj == null) {
  18895. break;
  18896. }
  18897. }
  18898. return obj;
  18899. }
  18900. function set(opt, path, val, overwrite) {
  18901. path = path.split(',');
  18902. var obj = opt;
  18903. var key;
  18904. for (var i = 0; i < path.length - 1; i++) {
  18905. key = path[i];
  18906. if (obj[key] == null) {
  18907. obj[key] = {};
  18908. }
  18909. obj = obj[key];
  18910. }
  18911. if (overwrite || obj[path[i]] == null) {
  18912. obj[path[i]] = val;
  18913. }
  18914. }
  18915. function compatLayoutProperties(option) {
  18916. each(LAYOUT_PROPERTIES, function (prop) {
  18917. if (prop[0] in option && !(prop[1] in option)) {
  18918. option[prop[1]] = option[prop[0]];
  18919. }
  18920. });
  18921. }
  18922. var LAYOUT_PROPERTIES = [
  18923. ['x', 'left'], ['y', 'top'], ['x2', 'right'], ['y2', 'bottom']
  18924. ];
  18925. var COMPATITABLE_COMPONENTS = [
  18926. 'grid', 'geo', 'parallel', 'legend', 'toolbox', 'title', 'visualMap', 'dataZoom', 'timeline'
  18927. ];
  18928. var COMPATITABLE_SERIES = [
  18929. 'bar', 'boxplot', 'candlestick', 'chord', 'effectScatter',
  18930. 'funnel', 'gauge', 'lines', 'graph', 'heatmap', 'line', 'map', 'parallel',
  18931. 'pie', 'radar', 'sankey', 'scatter', 'treemap'
  18932. ];
  18933. var each = zrUtil.each;
  18934. module.exports = function (option) {
  18935. each(option.series, function (seriesOpt) {
  18936. if (!zrUtil.isObject(seriesOpt)) {
  18937. return;
  18938. }
  18939. var seriesType = seriesOpt.type;
  18940. compatStyle(seriesOpt);
  18941. if (seriesType === 'pie' || seriesType === 'gauge') {
  18942. if (seriesOpt.clockWise != null) {
  18943. seriesOpt.clockwise = seriesOpt.clockWise;
  18944. }
  18945. }
  18946. if (seriesType === 'gauge') {
  18947. var pointerColor = get(seriesOpt, 'pointer.color');
  18948. pointerColor != null
  18949. && set(seriesOpt, 'itemStyle.normal.color', pointerColor);
  18950. }
  18951. for (var i = 0; i < COMPATITABLE_SERIES.length; i++) {
  18952. if (COMPATITABLE_SERIES[i] === seriesOpt.type) {
  18953. compatLayoutProperties(seriesOpt);
  18954. break;
  18955. }
  18956. }
  18957. });
  18958. // dataRange has changed to visualMap
  18959. if (option.dataRange) {
  18960. option.visualMap = option.dataRange;
  18961. }
  18962. each(COMPATITABLE_COMPONENTS, function (componentName) {
  18963. var options = option[componentName];
  18964. if (options) {
  18965. if (!zrUtil.isArray(options)) {
  18966. options = [options];
  18967. }
  18968. each(options, function (option) {
  18969. compatLayoutProperties(option);
  18970. });
  18971. }
  18972. });
  18973. };
  18974. /***/ },
  18975. /* 96 */
  18976. /***/ function(module, exports, __webpack_require__) {
  18977. var zrUtil = __webpack_require__(4);
  18978. var POSSIBLE_STYLES = [
  18979. 'areaStyle', 'lineStyle', 'nodeStyle', 'linkStyle',
  18980. 'chordStyle', 'label', 'labelLine'
  18981. ];
  18982. function compatItemStyle(opt) {
  18983. var itemStyleOpt = opt && opt.itemStyle;
  18984. if (itemStyleOpt) {
  18985. zrUtil.each(POSSIBLE_STYLES, function (styleName) {
  18986. var normalItemStyleOpt = itemStyleOpt.normal;
  18987. var emphasisItemStyleOpt = itemStyleOpt.emphasis;
  18988. if (normalItemStyleOpt && normalItemStyleOpt[styleName]) {
  18989. opt[styleName] = opt[styleName] || {};
  18990. if (!opt[styleName].normal) {
  18991. opt[styleName].normal = normalItemStyleOpt[styleName];
  18992. }
  18993. else {
  18994. zrUtil.merge(opt[styleName].normal, normalItemStyleOpt[styleName]);
  18995. }
  18996. normalItemStyleOpt[styleName] = null;
  18997. }
  18998. if (emphasisItemStyleOpt && emphasisItemStyleOpt[styleName]) {
  18999. opt[styleName] = opt[styleName] || {};
  19000. if (!opt[styleName].emphasis) {
  19001. opt[styleName].emphasis = emphasisItemStyleOpt[styleName];
  19002. }
  19003. else {
  19004. zrUtil.merge(opt[styleName].emphasis, emphasisItemStyleOpt[styleName]);
  19005. }
  19006. emphasisItemStyleOpt[styleName] = null;
  19007. }
  19008. });
  19009. }
  19010. }
  19011. module.exports = function (seriesOpt) {
  19012. if (!seriesOpt) {
  19013. return;
  19014. }
  19015. compatItemStyle(seriesOpt);
  19016. compatItemStyle(seriesOpt.markPoint);
  19017. compatItemStyle(seriesOpt.markLine);
  19018. var data = seriesOpt.data;
  19019. if (data) {
  19020. for (var i = 0; i < data.length; i++) {
  19021. compatItemStyle(data[i]);
  19022. }
  19023. // mark point data
  19024. var markPoint = seriesOpt.markPoint;
  19025. if (markPoint && markPoint.data) {
  19026. var mpData = markPoint.data;
  19027. for (var i = 0; i < mpData.length; i++) {
  19028. compatItemStyle(mpData[i]);
  19029. }
  19030. }
  19031. // mark line data
  19032. var markLine = seriesOpt.markLine;
  19033. if (markLine && markLine.data) {
  19034. var mlData = markLine.data;
  19035. for (var i = 0; i < mlData.length; i++) {
  19036. if (zrUtil.isArray(mlData[i])) {
  19037. compatItemStyle(mlData[i][0]);
  19038. compatItemStyle(mlData[i][1]);
  19039. }
  19040. else {
  19041. compatItemStyle(mlData[i]);
  19042. }
  19043. }
  19044. }
  19045. }
  19046. };
  19047. /***/ },
  19048. /* 97 */
  19049. /***/ function(module, exports, __webpack_require__) {
  19050. var graphic = __webpack_require__(18);
  19051. var zrUtil = __webpack_require__(4);
  19052. var PI = Math.PI;
  19053. /**
  19054. * @param {module:echarts/ExtensionAPI} api
  19055. * @param {Object} [opts]
  19056. * @param {string} [opts.text]
  19057. * @param {string} [opts.color]
  19058. * @param {string} [opts.textColor]
  19059. * @return {module:zrender/Element}
  19060. */
  19061. module.exports = function (api, opts) {
  19062. opts = opts || {};
  19063. zrUtil.defaults(opts, {
  19064. text: 'loading',
  19065. color: '#c23531',
  19066. textColor: '#000',
  19067. maskColor: 'rgba(255, 255, 255, 0.8)',
  19068. zlevel: 0
  19069. });
  19070. var mask = new graphic.Rect({
  19071. style: {
  19072. fill: opts.maskColor
  19073. },
  19074. zlevel: opts.zlevel,
  19075. z: 10000
  19076. });
  19077. var arc = new graphic.Arc({
  19078. shape: {
  19079. startAngle: -PI / 2,
  19080. endAngle: -PI / 2 + 0.1,
  19081. r: 10
  19082. },
  19083. style: {
  19084. stroke: opts.color,
  19085. lineCap: 'round',
  19086. lineWidth: 5
  19087. },
  19088. zlevel: opts.zlevel,
  19089. z: 10001
  19090. });
  19091. var labelRect = new graphic.Rect({
  19092. style: {
  19093. fill: 'none',
  19094. text: opts.text,
  19095. textPosition: 'right',
  19096. textDistance: 10,
  19097. textFill: opts.textColor
  19098. },
  19099. zlevel: opts.zlevel,
  19100. z: 10001
  19101. });
  19102. arc.animateShape(true)
  19103. .when(1000, {
  19104. endAngle: PI * 3 / 2
  19105. })
  19106. .start('circularInOut');
  19107. arc.animateShape(true)
  19108. .when(1000, {
  19109. startAngle: PI * 3 / 2
  19110. })
  19111. .delay(300)
  19112. .start('circularInOut');
  19113. var group = new graphic.Group();
  19114. group.add(arc);
  19115. group.add(labelRect);
  19116. group.add(mask);
  19117. // Inject resize
  19118. group.resize = function () {
  19119. var cx = api.getWidth() / 2;
  19120. var cy = api.getHeight() / 2;
  19121. arc.setShape({
  19122. cx: cx,
  19123. cy: cy
  19124. });
  19125. var r = arc.shape.r;
  19126. labelRect.setShape({
  19127. x: cx - r,
  19128. y: cy - r,
  19129. width: r * 2,
  19130. height: r * 2
  19131. });
  19132. mask.setShape({
  19133. x: 0,
  19134. y: 0,
  19135. width: api.getWidth(),
  19136. height: api.getHeight()
  19137. });
  19138. };
  19139. group.resize();
  19140. return group;
  19141. };
  19142. /***/ },
  19143. /* 98 */
  19144. /***/ function(module, exports, __webpack_require__) {
  19145. /* WEBPACK VAR INJECTION */(function(global) {/**
  19146. * List for data storage
  19147. * @module echarts/data/List
  19148. */
  19149. var UNDEFINED = 'undefined';
  19150. var globalObj = typeof window === 'undefined' ? global : window;
  19151. var Float64Array = typeof globalObj.Float64Array === UNDEFINED
  19152. ? Array : globalObj.Float64Array;
  19153. var Int32Array = typeof globalObj.Int32Array === UNDEFINED
  19154. ? Array : globalObj.Int32Array;
  19155. var dataCtors = {
  19156. 'float': Float64Array,
  19157. 'int': Int32Array,
  19158. // Ordinal data type can be string or int
  19159. 'ordinal': Array,
  19160. 'number': Array,
  19161. 'time': Array
  19162. };
  19163. var Model = __webpack_require__(12);
  19164. var DataDiffer = __webpack_require__(99);
  19165. var zrUtil = __webpack_require__(4);
  19166. var modelUtil = __webpack_require__(5);
  19167. var isObject = zrUtil.isObject;
  19168. var TRANSFERABLE_PROPERTIES = [
  19169. 'stackedOn', 'hasItemOption', '_nameList', '_idList', '_rawData'
  19170. ];
  19171. function transferProperties(a, b) {
  19172. zrUtil.each(TRANSFERABLE_PROPERTIES.concat(b.__wrappedMethods || []), function (propName) {
  19173. if (b.hasOwnProperty(propName)) {
  19174. a[propName] = b[propName];
  19175. }
  19176. });
  19177. a.__wrappedMethods = b.__wrappedMethods;
  19178. }
  19179. function DefaultDataProvider(dataArray) {
  19180. this._array = dataArray || [];
  19181. }
  19182. DefaultDataProvider.prototype.pure = false;
  19183. DefaultDataProvider.prototype.count = function () {
  19184. return this._array.length;
  19185. };
  19186. DefaultDataProvider.prototype.getItem = function (idx) {
  19187. return this._array[idx];
  19188. };
  19189. /**
  19190. * @constructor
  19191. * @alias module:echarts/data/List
  19192. *
  19193. * @param {Array.<string|Object>} dimensions
  19194. * For example, ['someDimName', {name: 'someDimName', type: 'someDimType'}, ...].
  19195. * Dimensions should be concrete names like x, y, z, lng, lat, angle, radius
  19196. * @param {module:echarts/model/Model} hostModel
  19197. */
  19198. var List = function (dimensions, hostModel) {
  19199. dimensions = dimensions || ['x', 'y'];
  19200. var dimensionInfos = {};
  19201. var dimensionNames = [];
  19202. for (var i = 0; i < dimensions.length; i++) {
  19203. var dimensionName;
  19204. var dimensionInfo = {};
  19205. if (typeof dimensions[i] === 'string') {
  19206. dimensionName = dimensions[i];
  19207. dimensionInfo = {
  19208. name: dimensionName,
  19209. coordDim: dimensionName,
  19210. coordDimIndex: 0,
  19211. stackable: false,
  19212. // Type can be 'float', 'int', 'number'
  19213. // Default is number, Precision of float may not enough
  19214. type: 'number'
  19215. };
  19216. }
  19217. else {
  19218. dimensionInfo = dimensions[i];
  19219. dimensionName = dimensionInfo.name;
  19220. dimensionInfo.type = dimensionInfo.type || 'number';
  19221. if (!dimensionInfo.coordDim) {
  19222. dimensionInfo.coordDim = dimensionName;
  19223. dimensionInfo.coordDimIndex = 0;
  19224. }
  19225. }
  19226. dimensionInfo.otherDims = dimensionInfo.otherDims || {};
  19227. dimensionNames.push(dimensionName);
  19228. dimensionInfos[dimensionName] = dimensionInfo;
  19229. }
  19230. /**
  19231. * @readOnly
  19232. * @type {Array.<string>}
  19233. */
  19234. this.dimensions = dimensionNames;
  19235. /**
  19236. * Infomation of each data dimension, like data type.
  19237. * @type {Object}
  19238. */
  19239. this._dimensionInfos = dimensionInfos;
  19240. /**
  19241. * @type {module:echarts/model/Model}
  19242. */
  19243. this.hostModel = hostModel;
  19244. /**
  19245. * @type {module:echarts/model/Model}
  19246. */
  19247. this.dataType;
  19248. /**
  19249. * Indices stores the indices of data subset after filtered.
  19250. * This data subset will be used in chart.
  19251. * @type {Array.<number>}
  19252. * @readOnly
  19253. */
  19254. this.indices = [];
  19255. /**
  19256. * Data storage
  19257. * @type {Object.<key, TypedArray|Array>}
  19258. * @private
  19259. */
  19260. this._storage = {};
  19261. /**
  19262. * @type {Array.<string>}
  19263. */
  19264. this._nameList = [];
  19265. /**
  19266. * @type {Array.<string>}
  19267. */
  19268. this._idList = [];
  19269. /**
  19270. * Models of data option is stored sparse for optimizing memory cost
  19271. * @type {Array.<module:echarts/model/Model>}
  19272. * @private
  19273. */
  19274. this._optionModels = [];
  19275. /**
  19276. * @param {module:echarts/data/List}
  19277. */
  19278. this.stackedOn = null;
  19279. /**
  19280. * Global visual properties after visual coding
  19281. * @type {Object}
  19282. * @private
  19283. */
  19284. this._visual = {};
  19285. /**
  19286. * Globel layout properties.
  19287. * @type {Object}
  19288. * @private
  19289. */
  19290. this._layout = {};
  19291. /**
  19292. * Item visual properties after visual coding
  19293. * @type {Array.<Object>}
  19294. * @private
  19295. */
  19296. this._itemVisuals = [];
  19297. /**
  19298. * Item layout properties after layout
  19299. * @type {Array.<Object>}
  19300. * @private
  19301. */
  19302. this._itemLayouts = [];
  19303. /**
  19304. * Graphic elemnents
  19305. * @type {Array.<module:zrender/Element>}
  19306. * @private
  19307. */
  19308. this._graphicEls = [];
  19309. /**
  19310. * @type {Array.<Array|Object>}
  19311. * @private
  19312. */
  19313. this._rawData;
  19314. /**
  19315. * @type {Object}
  19316. * @private
  19317. */
  19318. this._extent;
  19319. };
  19320. var listProto = List.prototype;
  19321. listProto.type = 'list';
  19322. /**
  19323. * If each data item has it's own option
  19324. * @type {boolean}
  19325. */
  19326. listProto.hasItemOption = true;
  19327. /**
  19328. * Get dimension name
  19329. * @param {string|number} dim
  19330. * Dimension can be concrete names like x, y, z, lng, lat, angle, radius
  19331. * Or a ordinal number. For example getDimensionInfo(0) will return 'x' or 'lng' or 'radius'
  19332. * @return {string} Concrete dim name.
  19333. */
  19334. listProto.getDimension = function (dim) {
  19335. if (!isNaN(dim)) {
  19336. dim = this.dimensions[dim] || dim;
  19337. }
  19338. return dim;
  19339. };
  19340. /**
  19341. * Get type and stackable info of particular dimension
  19342. * @param {string|number} dim
  19343. * Dimension can be concrete names like x, y, z, lng, lat, angle, radius
  19344. * Or a ordinal number. For example getDimensionInfo(0) will return 'x' or 'lng' or 'radius'
  19345. */
  19346. listProto.getDimensionInfo = function (dim) {
  19347. return zrUtil.clone(this._dimensionInfos[this.getDimension(dim)]);
  19348. };
  19349. /**
  19350. * Initialize from data
  19351. * @param {Array.<Object|number|Array>} data
  19352. * @param {Array.<string>} [nameList]
  19353. * @param {Function} [dimValueGetter] (dataItem, dimName, dataIndex, dimIndex) => number
  19354. */
  19355. listProto.initData = function (data, nameList, dimValueGetter) {
  19356. data = data || [];
  19357. var isDataArray = zrUtil.isArray(data);
  19358. if (isDataArray) {
  19359. data = new DefaultDataProvider(data);
  19360. }
  19361. if (true) {
  19362. if (!isDataArray && (typeof data.getItem != 'function' || typeof data.count != 'function')) {
  19363. throw new Error('Inavlid data provider.');
  19364. }
  19365. }
  19366. this._rawData = data;
  19367. // Clear
  19368. var storage = this._storage = {};
  19369. var indices = this.indices = [];
  19370. var dimensions = this.dimensions;
  19371. var dimensionInfoMap = this._dimensionInfos;
  19372. var size = data.count();
  19373. var idList = [];
  19374. var nameRepeatCount = {};
  19375. var nameDimIdx;
  19376. nameList = nameList || [];
  19377. // Init storage
  19378. for (var i = 0; i < dimensions.length; i++) {
  19379. var dimInfo = dimensionInfoMap[dimensions[i]];
  19380. dimInfo.otherDims.itemName === 0 && (nameDimIdx = i);
  19381. var DataCtor = dataCtors[dimInfo.type];
  19382. storage[dimensions[i]] = new DataCtor(size);
  19383. }
  19384. var self = this;
  19385. if (!dimValueGetter) {
  19386. self.hasItemOption = false;
  19387. }
  19388. // Default dim value getter
  19389. dimValueGetter = dimValueGetter || function (dataItem, dimName, dataIndex, dimIndex) {
  19390. var value = modelUtil.getDataItemValue(dataItem);
  19391. // If any dataItem is like { value: 10 }
  19392. if (modelUtil.isDataItemOption(dataItem)) {
  19393. self.hasItemOption = true;
  19394. }
  19395. return modelUtil.converDataValue(
  19396. (value instanceof Array)
  19397. ? value[dimIndex]
  19398. // If value is a single number or something else not array.
  19399. : value,
  19400. dimensionInfoMap[dimName]
  19401. );
  19402. };
  19403. for (var i = 0; i < size; i++) {
  19404. // NOTICE: Try not to write things into dataItem
  19405. var dataItem = data.getItem(i);
  19406. // Each data item is value
  19407. // [1, 2]
  19408. // 2
  19409. // Bar chart, line chart which uses category axis
  19410. // only gives the 'y' value. 'x' value is the indices of cateogry
  19411. // Use a tempValue to normalize the value to be a (x, y) value
  19412. // Store the data by dimensions
  19413. for (var k = 0; k < dimensions.length; k++) {
  19414. var dim = dimensions[k];
  19415. var dimStorage = storage[dim];
  19416. // PENDING NULL is empty or zero
  19417. dimStorage[i] = dimValueGetter(dataItem, dim, i, k);
  19418. }
  19419. indices.push(i);
  19420. }
  19421. // Use the name in option and create id
  19422. for (var i = 0; i < size; i++) {
  19423. var dataItem = data.getItem(i);
  19424. if (!nameList[i] && dataItem) {
  19425. if (dataItem.name != null) {
  19426. nameList[i] = dataItem.name;
  19427. }
  19428. else if (nameDimIdx != null) {
  19429. nameList[i] = storage[dimensions[nameDimIdx]][i];
  19430. }
  19431. }
  19432. var name = nameList[i] || '';
  19433. // Try using the id in option
  19434. var id = dataItem && dataItem.id;
  19435. if (!id && name) {
  19436. // Use name as id and add counter to avoid same name
  19437. nameRepeatCount[name] = nameRepeatCount[name] || 0;
  19438. id = name;
  19439. if (nameRepeatCount[name] > 0) {
  19440. id += '__ec__' + nameRepeatCount[name];
  19441. }
  19442. nameRepeatCount[name]++;
  19443. }
  19444. id && (idList[i] = id);
  19445. }
  19446. this._nameList = nameList;
  19447. this._idList = idList;
  19448. };
  19449. /**
  19450. * @return {number}
  19451. */
  19452. listProto.count = function () {
  19453. return this.indices.length;
  19454. };
  19455. /**
  19456. * Get value. Return NaN if idx is out of range.
  19457. * @param {string} dim Dim must be concrete name.
  19458. * @param {number} idx
  19459. * @param {boolean} stack
  19460. * @return {number}
  19461. */
  19462. listProto.get = function (dim, idx, stack) {
  19463. var storage = this._storage;
  19464. var dataIndex = this.indices[idx];
  19465. // If value not exists
  19466. if (dataIndex == null || !storage[dim]) {
  19467. return NaN;
  19468. }
  19469. var value = storage[dim][dataIndex];
  19470. // FIXME ordinal data type is not stackable
  19471. if (stack) {
  19472. var dimensionInfo = this._dimensionInfos[dim];
  19473. if (dimensionInfo && dimensionInfo.stackable) {
  19474. var stackedOn = this.stackedOn;
  19475. while (stackedOn) {
  19476. // Get no stacked data of stacked on
  19477. var stackedValue = stackedOn.get(dim, idx);
  19478. // Considering positive stack, negative stack and empty data
  19479. if ((value >= 0 && stackedValue > 0) // Positive stack
  19480. || (value <= 0 && stackedValue < 0) // Negative stack
  19481. ) {
  19482. value += stackedValue;
  19483. }
  19484. stackedOn = stackedOn.stackedOn;
  19485. }
  19486. }
  19487. }
  19488. return value;
  19489. };
  19490. /**
  19491. * Get value for multi dimensions.
  19492. * @param {Array.<string>} [dimensions] If ignored, using all dimensions.
  19493. * @param {number} idx
  19494. * @param {boolean} stack
  19495. * @return {number}
  19496. */
  19497. listProto.getValues = function (dimensions, idx, stack) {
  19498. var values = [];
  19499. if (!zrUtil.isArray(dimensions)) {
  19500. stack = idx;
  19501. idx = dimensions;
  19502. dimensions = this.dimensions;
  19503. }
  19504. for (var i = 0, len = dimensions.length; i < len; i++) {
  19505. values.push(this.get(dimensions[i], idx, stack));
  19506. }
  19507. return values;
  19508. };
  19509. /**
  19510. * If value is NaN. Inlcuding '-'
  19511. * @param {string} dim
  19512. * @param {number} idx
  19513. * @return {number}
  19514. */
  19515. listProto.hasValue = function (idx) {
  19516. var dimensions = this.dimensions;
  19517. var dimensionInfos = this._dimensionInfos;
  19518. for (var i = 0, len = dimensions.length; i < len; i++) {
  19519. if (
  19520. // Ordinal type can be string or number
  19521. dimensionInfos[dimensions[i]].type !== 'ordinal'
  19522. && isNaN(this.get(dimensions[i], idx))
  19523. ) {
  19524. return false;
  19525. }
  19526. }
  19527. return true;
  19528. };
  19529. /**
  19530. * Get extent of data in one dimension
  19531. * @param {string} dim
  19532. * @param {boolean} stack
  19533. * @param {Function} filter
  19534. */
  19535. listProto.getDataExtent = function (dim, stack, filter) {
  19536. dim = this.getDimension(dim);
  19537. var dimData = this._storage[dim];
  19538. var dimInfo = this.getDimensionInfo(dim);
  19539. stack = (dimInfo && dimInfo.stackable) && stack;
  19540. var dimExtent = (this._extent || (this._extent = {}))[dim + (!!stack)];
  19541. var value;
  19542. if (dimExtent) {
  19543. return dimExtent;
  19544. }
  19545. // var dimInfo = this._dimensionInfos[dim];
  19546. if (dimData) {
  19547. var min = Infinity;
  19548. var max = -Infinity;
  19549. // var isOrdinal = dimInfo.type === 'ordinal';
  19550. for (var i = 0, len = this.count(); i < len; i++) {
  19551. value = this.get(dim, i, stack);
  19552. // FIXME
  19553. // if (isOrdinal && typeof value === 'string') {
  19554. // value = zrUtil.indexOf(dimData, value);
  19555. // }
  19556. if (!filter || filter(value, dim, i)) {
  19557. value < min && (min = value);
  19558. value > max && (max = value);
  19559. }
  19560. }
  19561. return (this._extent[dim + !!stack] = [min, max]);
  19562. }
  19563. else {
  19564. return [Infinity, -Infinity];
  19565. }
  19566. };
  19567. /**
  19568. * Get sum of data in one dimension
  19569. * @param {string} dim
  19570. * @param {boolean} stack
  19571. */
  19572. listProto.getSum = function (dim, stack) {
  19573. var dimData = this._storage[dim];
  19574. var sum = 0;
  19575. if (dimData) {
  19576. for (var i = 0, len = this.count(); i < len; i++) {
  19577. var value = this.get(dim, i, stack);
  19578. if (!isNaN(value)) {
  19579. sum += value;
  19580. }
  19581. }
  19582. }
  19583. return sum;
  19584. };
  19585. /**
  19586. * Retreive the index with given value
  19587. * @param {number} idx
  19588. * @param {number} value
  19589. * @return {number}
  19590. */
  19591. // FIXME Precision of float value
  19592. listProto.indexOf = function (dim, value) {
  19593. var storage = this._storage;
  19594. var dimData = storage[dim];
  19595. var indices = this.indices;
  19596. if (dimData) {
  19597. for (var i = 0, len = indices.length; i < len; i++) {
  19598. var rawIndex = indices[i];
  19599. if (dimData[rawIndex] === value) {
  19600. return i;
  19601. }
  19602. }
  19603. }
  19604. return -1;
  19605. };
  19606. /**
  19607. * Retreive the index with given name
  19608. * @param {number} idx
  19609. * @param {number} name
  19610. * @return {number}
  19611. */
  19612. listProto.indexOfName = function (name) {
  19613. var indices = this.indices;
  19614. var nameList = this._nameList;
  19615. for (var i = 0, len = indices.length; i < len; i++) {
  19616. var rawIndex = indices[i];
  19617. if (nameList[rawIndex] === name) {
  19618. return i;
  19619. }
  19620. }
  19621. return -1;
  19622. };
  19623. /**
  19624. * Retreive the index with given raw data index
  19625. * @param {number} idx
  19626. * @param {number} name
  19627. * @return {number}
  19628. */
  19629. listProto.indexOfRawIndex = function (rawIndex) {
  19630. // Indices are ascending
  19631. var indices = this.indices;
  19632. // If rawIndex === dataIndex
  19633. var rawDataIndex = indices[rawIndex];
  19634. if (rawDataIndex != null && rawDataIndex === rawIndex) {
  19635. return rawIndex;
  19636. }
  19637. var left = 0;
  19638. var right = indices.length - 1;
  19639. while (left <= right) {
  19640. var mid = (left + right) / 2 | 0;
  19641. if (indices[mid] < rawIndex) {
  19642. left = mid + 1;
  19643. }
  19644. else if (indices[mid] > rawIndex) {
  19645. right = mid - 1;
  19646. }
  19647. else {
  19648. return mid;
  19649. }
  19650. }
  19651. return -1;
  19652. };
  19653. /**
  19654. * Retreive the index of nearest value
  19655. * @param {string} dim
  19656. * @param {number} value
  19657. * @param {boolean} stack If given value is after stacked
  19658. * @param {number} [maxDistance=Infinity]
  19659. * @return {Array.<number>} Considere multiple points has the same value.
  19660. */
  19661. listProto.indicesOfNearest = function (dim, value, stack, maxDistance) {
  19662. var storage = this._storage;
  19663. var dimData = storage[dim];
  19664. var nearestIndices = [];
  19665. if (!dimData) {
  19666. return nearestIndices;
  19667. }
  19668. if (maxDistance == null) {
  19669. maxDistance = Infinity;
  19670. }
  19671. var minDist = Number.MAX_VALUE;
  19672. var minDiff = -1;
  19673. for (var i = 0, len = this.count(); i < len; i++) {
  19674. var diff = value - this.get(dim, i, stack);
  19675. var dist = Math.abs(diff);
  19676. if (diff <= maxDistance && dist <= minDist) {
  19677. // For the case of two data are same on xAxis, which has sequence data.
  19678. // Show the nearest index
  19679. // https://github.com/ecomfe/echarts/issues/2869
  19680. if (dist < minDist || (diff >= 0 && minDiff < 0)) {
  19681. minDist = dist;
  19682. minDiff = diff;
  19683. nearestIndices.length = 0;
  19684. }
  19685. nearestIndices.push(i);
  19686. }
  19687. }
  19688. return nearestIndices;
  19689. };
  19690. /**
  19691. * Get raw data index
  19692. * @param {number} idx
  19693. * @return {number}
  19694. */
  19695. listProto.getRawIndex = function (idx) {
  19696. var rawIdx = this.indices[idx];
  19697. return rawIdx == null ? -1 : rawIdx;
  19698. };
  19699. /**
  19700. * Get raw data item
  19701. * @param {number} idx
  19702. * @return {number}
  19703. */
  19704. listProto.getRawDataItem = function (idx) {
  19705. return this._rawData.getItem(this.getRawIndex(idx));
  19706. };
  19707. /**
  19708. * @param {number} idx
  19709. * @param {boolean} [notDefaultIdx=false]
  19710. * @return {string}
  19711. */
  19712. listProto.getName = function (idx) {
  19713. return this._nameList[this.indices[idx]] || '';
  19714. };
  19715. /**
  19716. * @param {number} idx
  19717. * @param {boolean} [notDefaultIdx=false]
  19718. * @return {string}
  19719. */
  19720. listProto.getId = function (idx) {
  19721. return this._idList[this.indices[idx]] || (this.getRawIndex(idx) + '');
  19722. };
  19723. function normalizeDimensions(dimensions) {
  19724. if (!zrUtil.isArray(dimensions)) {
  19725. dimensions = [dimensions];
  19726. }
  19727. return dimensions;
  19728. }
  19729. /**
  19730. * Data iteration
  19731. * @param {string|Array.<string>}
  19732. * @param {Function} cb
  19733. * @param {boolean} [stack=false]
  19734. * @param {*} [context=this]
  19735. *
  19736. * @example
  19737. * list.each('x', function (x, idx) {});
  19738. * list.each(['x', 'y'], function (x, y, idx) {});
  19739. * list.each(function (idx) {})
  19740. */
  19741. listProto.each = function (dims, cb, stack, context) {
  19742. if (typeof dims === 'function') {
  19743. context = stack;
  19744. stack = cb;
  19745. cb = dims;
  19746. dims = [];
  19747. }
  19748. dims = zrUtil.map(normalizeDimensions(dims), this.getDimension, this);
  19749. var value = [];
  19750. var dimSize = dims.length;
  19751. var indices = this.indices;
  19752. context = context || this;
  19753. for (var i = 0; i < indices.length; i++) {
  19754. // Simple optimization
  19755. switch (dimSize) {
  19756. case 0:
  19757. cb.call(context, i);
  19758. break;
  19759. case 1:
  19760. cb.call(context, this.get(dims[0], i, stack), i);
  19761. break;
  19762. case 2:
  19763. cb.call(context, this.get(dims[0], i, stack), this.get(dims[1], i, stack), i);
  19764. break;
  19765. default:
  19766. for (var k = 0; k < dimSize; k++) {
  19767. value[k] = this.get(dims[k], i, stack);
  19768. }
  19769. // Index
  19770. value[k] = i;
  19771. cb.apply(context, value);
  19772. }
  19773. }
  19774. };
  19775. /**
  19776. * Data filter
  19777. * @param {string|Array.<string>}
  19778. * @param {Function} cb
  19779. * @param {boolean} [stack=false]
  19780. * @param {*} [context=this]
  19781. */
  19782. listProto.filterSelf = function (dimensions, cb, stack, context) {
  19783. if (typeof dimensions === 'function') {
  19784. context = stack;
  19785. stack = cb;
  19786. cb = dimensions;
  19787. dimensions = [];
  19788. }
  19789. dimensions = zrUtil.map(
  19790. normalizeDimensions(dimensions), this.getDimension, this
  19791. );
  19792. var newIndices = [];
  19793. var value = [];
  19794. var dimSize = dimensions.length;
  19795. var indices = this.indices;
  19796. context = context || this;
  19797. for (var i = 0; i < indices.length; i++) {
  19798. var keep;
  19799. // Simple optimization
  19800. if (!dimSize) {
  19801. keep = cb.call(context, i);
  19802. }
  19803. else if (dimSize === 1) {
  19804. keep = cb.call(
  19805. context, this.get(dimensions[0], i, stack), i
  19806. );
  19807. }
  19808. else {
  19809. for (var k = 0; k < dimSize; k++) {
  19810. value[k] = this.get(dimensions[k], i, stack);
  19811. }
  19812. value[k] = i;
  19813. keep = cb.apply(context, value);
  19814. }
  19815. if (keep) {
  19816. newIndices.push(indices[i]);
  19817. }
  19818. }
  19819. this.indices = newIndices;
  19820. // Reset data extent
  19821. this._extent = {};
  19822. return this;
  19823. };
  19824. /**
  19825. * Data mapping to a plain array
  19826. * @param {string|Array.<string>} [dimensions]
  19827. * @param {Function} cb
  19828. * @param {boolean} [stack=false]
  19829. * @param {*} [context=this]
  19830. * @return {Array}
  19831. */
  19832. listProto.mapArray = function (dimensions, cb, stack, context) {
  19833. if (typeof dimensions === 'function') {
  19834. context = stack;
  19835. stack = cb;
  19836. cb = dimensions;
  19837. dimensions = [];
  19838. }
  19839. var result = [];
  19840. this.each(dimensions, function () {
  19841. result.push(cb && cb.apply(this, arguments));
  19842. }, stack, context);
  19843. return result;
  19844. };
  19845. function cloneListForMapAndSample(original, excludeDimensions) {
  19846. var allDimensions = original.dimensions;
  19847. var list = new List(
  19848. zrUtil.map(allDimensions, original.getDimensionInfo, original),
  19849. original.hostModel
  19850. );
  19851. // FIXME If needs stackedOn, value may already been stacked
  19852. transferProperties(list, original);
  19853. var storage = list._storage = {};
  19854. var originalStorage = original._storage;
  19855. // Init storage
  19856. for (var i = 0; i < allDimensions.length; i++) {
  19857. var dim = allDimensions[i];
  19858. var dimStore = originalStorage[dim];
  19859. if (zrUtil.indexOf(excludeDimensions, dim) >= 0) {
  19860. storage[dim] = new dimStore.constructor(
  19861. originalStorage[dim].length
  19862. );
  19863. }
  19864. else {
  19865. // Direct reference for other dimensions
  19866. storage[dim] = originalStorage[dim];
  19867. }
  19868. }
  19869. return list;
  19870. }
  19871. /**
  19872. * Data mapping to a new List with given dimensions
  19873. * @param {string|Array.<string>} dimensions
  19874. * @param {Function} cb
  19875. * @param {boolean} [stack=false]
  19876. * @param {*} [context=this]
  19877. * @return {Array}
  19878. */
  19879. listProto.map = function (dimensions, cb, stack, context) {
  19880. dimensions = zrUtil.map(
  19881. normalizeDimensions(dimensions), this.getDimension, this
  19882. );
  19883. var list = cloneListForMapAndSample(this, dimensions);
  19884. // Following properties are all immutable.
  19885. // So we can reference to the same value
  19886. var indices = list.indices = this.indices;
  19887. var storage = list._storage;
  19888. var tmpRetValue = [];
  19889. this.each(dimensions, function () {
  19890. var idx = arguments[arguments.length - 1];
  19891. var retValue = cb && cb.apply(this, arguments);
  19892. if (retValue != null) {
  19893. // a number
  19894. if (typeof retValue === 'number') {
  19895. tmpRetValue[0] = retValue;
  19896. retValue = tmpRetValue;
  19897. }
  19898. for (var i = 0; i < retValue.length; i++) {
  19899. var dim = dimensions[i];
  19900. var dimStore = storage[dim];
  19901. var rawIdx = indices[idx];
  19902. if (dimStore) {
  19903. dimStore[rawIdx] = retValue[i];
  19904. }
  19905. }
  19906. }
  19907. }, stack, context);
  19908. return list;
  19909. };
  19910. /**
  19911. * Large data down sampling on given dimension
  19912. * @param {string} dimension
  19913. * @param {number} rate
  19914. * @param {Function} sampleValue
  19915. * @param {Function} sampleIndex Sample index for name and id
  19916. */
  19917. listProto.downSample = function (dimension, rate, sampleValue, sampleIndex) {
  19918. var list = cloneListForMapAndSample(this, [dimension]);
  19919. var storage = this._storage;
  19920. var targetStorage = list._storage;
  19921. var originalIndices = this.indices;
  19922. var indices = list.indices = [];
  19923. var frameValues = [];
  19924. var frameIndices = [];
  19925. var frameSize = Math.floor(1 / rate);
  19926. var dimStore = targetStorage[dimension];
  19927. var len = this.count();
  19928. // Copy data from original data
  19929. for (var i = 0; i < storage[dimension].length; i++) {
  19930. targetStorage[dimension][i] = storage[dimension][i];
  19931. }
  19932. for (var i = 0; i < len; i += frameSize) {
  19933. // Last frame
  19934. if (frameSize > len - i) {
  19935. frameSize = len - i;
  19936. frameValues.length = frameSize;
  19937. }
  19938. for (var k = 0; k < frameSize; k++) {
  19939. var idx = originalIndices[i + k];
  19940. frameValues[k] = dimStore[idx];
  19941. frameIndices[k] = idx;
  19942. }
  19943. var value = sampleValue(frameValues);
  19944. var idx = frameIndices[sampleIndex(frameValues, value) || 0];
  19945. // Only write value on the filtered data
  19946. dimStore[idx] = value;
  19947. indices.push(idx);
  19948. }
  19949. return list;
  19950. };
  19951. /**
  19952. * Get model of one data item.
  19953. *
  19954. * @param {number} idx
  19955. */
  19956. // FIXME Model proxy ?
  19957. listProto.getItemModel = function (idx) {
  19958. var hostModel = this.hostModel;
  19959. idx = this.indices[idx];
  19960. return new Model(this._rawData.getItem(idx), hostModel, hostModel && hostModel.ecModel);
  19961. };
  19962. /**
  19963. * Create a data differ
  19964. * @param {module:echarts/data/List} otherList
  19965. * @return {module:echarts/data/DataDiffer}
  19966. */
  19967. listProto.diff = function (otherList) {
  19968. var idList = this._idList;
  19969. var otherIdList = otherList && otherList._idList;
  19970. var val;
  19971. // Use prefix to avoid index to be the same as otherIdList[idx],
  19972. // which will cause weird udpate animation.
  19973. var prefix = 'e\0\0';
  19974. return new DataDiffer(
  19975. otherList ? otherList.indices : [],
  19976. this.indices,
  19977. function (idx) {
  19978. return (val = otherIdList[idx]) != null ? val : prefix + idx;
  19979. },
  19980. function (idx) {
  19981. return (val = idList[idx]) != null ? val : prefix + idx;
  19982. }
  19983. );
  19984. };
  19985. /**
  19986. * Get visual property.
  19987. * @param {string} key
  19988. */
  19989. listProto.getVisual = function (key) {
  19990. var visual = this._visual;
  19991. return visual && visual[key];
  19992. };
  19993. /**
  19994. * Set visual property
  19995. * @param {string|Object} key
  19996. * @param {*} [value]
  19997. *
  19998. * @example
  19999. * setVisual('color', color);
  20000. * setVisual({
  20001. * 'color': color
  20002. * });
  20003. */
  20004. listProto.setVisual = function (key, val) {
  20005. if (isObject(key)) {
  20006. for (var name in key) {
  20007. if (key.hasOwnProperty(name)) {
  20008. this.setVisual(name, key[name]);
  20009. }
  20010. }
  20011. return;
  20012. }
  20013. this._visual = this._visual || {};
  20014. this._visual[key] = val;
  20015. };
  20016. /**
  20017. * Set layout property.
  20018. * @param {string} key
  20019. * @param {*} [val]
  20020. */
  20021. listProto.setLayout = function (key, val) {
  20022. if (isObject(key)) {
  20023. for (var name in key) {
  20024. if (key.hasOwnProperty(name)) {
  20025. this.setLayout(name, key[name]);
  20026. }
  20027. }
  20028. return;
  20029. }
  20030. this._layout[key] = val;
  20031. };
  20032. /**
  20033. * Get layout property.
  20034. * @param {string} key.
  20035. * @return {*}
  20036. */
  20037. listProto.getLayout = function (key) {
  20038. return this._layout[key];
  20039. };
  20040. /**
  20041. * Get layout of single data item
  20042. * @param {number} idx
  20043. */
  20044. listProto.getItemLayout = function (idx) {
  20045. return this._itemLayouts[idx];
  20046. };
  20047. /**
  20048. * Set layout of single data item
  20049. * @param {number} idx
  20050. * @param {Object} layout
  20051. * @param {boolean=} [merge=false]
  20052. */
  20053. listProto.setItemLayout = function (idx, layout, merge) {
  20054. this._itemLayouts[idx] = merge
  20055. ? zrUtil.extend(this._itemLayouts[idx] || {}, layout)
  20056. : layout;
  20057. };
  20058. /**
  20059. * Clear all layout of single data item
  20060. */
  20061. listProto.clearItemLayouts = function () {
  20062. this._itemLayouts.length = 0;
  20063. };
  20064. /**
  20065. * Get visual property of single data item
  20066. * @param {number} idx
  20067. * @param {string} key
  20068. * @param {boolean} [ignoreParent=false]
  20069. */
  20070. listProto.getItemVisual = function (idx, key, ignoreParent) {
  20071. var itemVisual = this._itemVisuals[idx];
  20072. var val = itemVisual && itemVisual[key];
  20073. if (val == null && !ignoreParent) {
  20074. // Use global visual property
  20075. return this.getVisual(key);
  20076. }
  20077. return val;
  20078. };
  20079. /**
  20080. * Set visual property of single data item
  20081. *
  20082. * @param {number} idx
  20083. * @param {string|Object} key
  20084. * @param {*} [value]
  20085. *
  20086. * @example
  20087. * setItemVisual(0, 'color', color);
  20088. * setItemVisual(0, {
  20089. * 'color': color
  20090. * });
  20091. */
  20092. listProto.setItemVisual = function (idx, key, value) {
  20093. var itemVisual = this._itemVisuals[idx] || {};
  20094. this._itemVisuals[idx] = itemVisual;
  20095. if (isObject(key)) {
  20096. for (var name in key) {
  20097. if (key.hasOwnProperty(name)) {
  20098. itemVisual[name] = key[name];
  20099. }
  20100. }
  20101. return;
  20102. }
  20103. itemVisual[key] = value;
  20104. };
  20105. /**
  20106. * Clear itemVisuals and list visual.
  20107. */
  20108. listProto.clearAllVisual = function () {
  20109. this._visual = {};
  20110. this._itemVisuals = [];
  20111. };
  20112. var setItemDataAndSeriesIndex = function (child) {
  20113. child.seriesIndex = this.seriesIndex;
  20114. child.dataIndex = this.dataIndex;
  20115. child.dataType = this.dataType;
  20116. };
  20117. /**
  20118. * Set graphic element relative to data. It can be set as null
  20119. * @param {number} idx
  20120. * @param {module:zrender/Element} [el]
  20121. */
  20122. listProto.setItemGraphicEl = function (idx, el) {
  20123. var hostModel = this.hostModel;
  20124. if (el) {
  20125. // Add data index and series index for indexing the data by element
  20126. // Useful in tooltip
  20127. el.dataIndex = idx;
  20128. el.dataType = this.dataType;
  20129. el.seriesIndex = hostModel && hostModel.seriesIndex;
  20130. if (el.type === 'group') {
  20131. el.traverse(setItemDataAndSeriesIndex, el);
  20132. }
  20133. }
  20134. this._graphicEls[idx] = el;
  20135. };
  20136. /**
  20137. * @param {number} idx
  20138. * @return {module:zrender/Element}
  20139. */
  20140. listProto.getItemGraphicEl = function (idx) {
  20141. return this._graphicEls[idx];
  20142. };
  20143. /**
  20144. * @param {Function} cb
  20145. * @param {*} context
  20146. */
  20147. listProto.eachItemGraphicEl = function (cb, context) {
  20148. zrUtil.each(this._graphicEls, function (el, idx) {
  20149. if (el) {
  20150. cb && cb.call(context, el, idx);
  20151. }
  20152. });
  20153. };
  20154. /**
  20155. * Shallow clone a new list except visual and layout properties, and graph elements.
  20156. * New list only change the indices.
  20157. */
  20158. listProto.cloneShallow = function () {
  20159. var dimensionInfoList = zrUtil.map(this.dimensions, this.getDimensionInfo, this);
  20160. var list = new List(dimensionInfoList, this.hostModel);
  20161. // FIXME
  20162. list._storage = this._storage;
  20163. transferProperties(list, this);
  20164. // Clone will not change the data extent and indices
  20165. list.indices = this.indices.slice();
  20166. if (this._extent) {
  20167. list._extent = zrUtil.extend({}, this._extent);
  20168. }
  20169. return list;
  20170. };
  20171. /**
  20172. * Wrap some method to add more feature
  20173. * @param {string} methodName
  20174. * @param {Function} injectFunction
  20175. */
  20176. listProto.wrapMethod = function (methodName, injectFunction) {
  20177. var originalMethod = this[methodName];
  20178. if (typeof originalMethod !== 'function') {
  20179. return;
  20180. }
  20181. this.__wrappedMethods = this.__wrappedMethods || [];
  20182. this.__wrappedMethods.push(methodName);
  20183. this[methodName] = function () {
  20184. var res = originalMethod.apply(this, arguments);
  20185. return injectFunction.apply(this, [res].concat(zrUtil.slice(arguments)));
  20186. };
  20187. };
  20188. // Methods that create a new list based on this list should be listed here.
  20189. // Notice that those method should `RETURN` the new list.
  20190. listProto.TRANSFERABLE_METHODS = ['cloneShallow', 'downSample', 'map'];
  20191. // Methods that change indices of this list should be listed here.
  20192. listProto.CHANGABLE_METHODS = ['filterSelf'];
  20193. module.exports = List;
  20194. /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  20195. /***/ },
  20196. /* 99 */
  20197. /***/ function(module, exports) {
  20198. 'use strict';
  20199. function defaultKeyGetter(item) {
  20200. return item;
  20201. }
  20202. function DataDiffer(oldArr, newArr, oldKeyGetter, newKeyGetter) {
  20203. this._old = oldArr;
  20204. this._new = newArr;
  20205. this._oldKeyGetter = oldKeyGetter || defaultKeyGetter;
  20206. this._newKeyGetter = newKeyGetter || defaultKeyGetter;
  20207. }
  20208. DataDiffer.prototype = {
  20209. constructor: DataDiffer,
  20210. /**
  20211. * Callback function when add a data
  20212. */
  20213. add: function (func) {
  20214. this._add = func;
  20215. return this;
  20216. },
  20217. /**
  20218. * Callback function when update a data
  20219. */
  20220. update: function (func) {
  20221. this._update = func;
  20222. return this;
  20223. },
  20224. /**
  20225. * Callback function when remove a data
  20226. */
  20227. remove: function (func) {
  20228. this._remove = func;
  20229. return this;
  20230. },
  20231. execute: function () {
  20232. var oldArr = this._old;
  20233. var newArr = this._new;
  20234. var oldKeyGetter = this._oldKeyGetter;
  20235. var newKeyGetter = this._newKeyGetter;
  20236. var oldDataIndexMap = {};
  20237. var newDataIndexMap = {};
  20238. var oldDataKeyArr = [];
  20239. var newDataKeyArr = [];
  20240. var i;
  20241. initIndexMap(oldArr, oldDataIndexMap, oldDataKeyArr, oldKeyGetter);
  20242. initIndexMap(newArr, newDataIndexMap, newDataKeyArr, newKeyGetter);
  20243. // Travel by inverted order to make sure order consistency
  20244. // when duplicate keys exists (consider newDataIndex.pop() below).
  20245. // For performance consideration, these code below do not look neat.
  20246. for (i = 0; i < oldArr.length; i++) {
  20247. var key = oldDataKeyArr[i];
  20248. var idx = newDataIndexMap[key];
  20249. // idx can never be empty array here. see 'set null' logic below.
  20250. if (idx != null) {
  20251. // Consider there is duplicate key (for example, use dataItem.name as key).
  20252. // We should make sure every item in newArr and oldArr can be visited.
  20253. var len = idx.length;
  20254. if (len) {
  20255. len === 1 && (newDataIndexMap[key] = null);
  20256. idx = idx.unshift();
  20257. }
  20258. else {
  20259. newDataIndexMap[key] = null;
  20260. }
  20261. this._update && this._update(idx, i);
  20262. }
  20263. else {
  20264. this._remove && this._remove(i);
  20265. }
  20266. }
  20267. for (var i = 0; i < newDataKeyArr.length; i++) {
  20268. var key = newDataKeyArr[i];
  20269. if (newDataIndexMap.hasOwnProperty(key)) {
  20270. var idx = newDataIndexMap[key];
  20271. if (idx == null) {
  20272. continue;
  20273. }
  20274. // idx can never be empty array here. see 'set null' logic above.
  20275. if (!idx.length) {
  20276. this._add && this._add(idx);
  20277. }
  20278. else {
  20279. for (var j = 0, len = idx.length; j < len; j++) {
  20280. this._add && this._add(idx[j]);
  20281. }
  20282. }
  20283. }
  20284. }
  20285. }
  20286. };
  20287. function initIndexMap(arr, map, keyArr, keyGetter) {
  20288. for (var i = 0; i < arr.length; i++) {
  20289. // Add prefix to avoid conflict with Object.prototype.
  20290. var key = '_ec_' + keyGetter(arr[i], i);
  20291. var existence = map[key];
  20292. if (existence == null) {
  20293. keyArr.push(key);
  20294. map[key] = i;
  20295. }
  20296. else {
  20297. if (!existence.length) {
  20298. map[key] = existence = [existence];
  20299. }
  20300. existence.push(i);
  20301. }
  20302. }
  20303. }
  20304. module.exports = DataDiffer;
  20305. /***/ },
  20306. /* 100 */
  20307. /***/ function(module, exports, __webpack_require__) {
  20308. var numberUtil = __webpack_require__(7);
  20309. var linearMap = numberUtil.linearMap;
  20310. var zrUtil = __webpack_require__(4);
  20311. var axisHelper = __webpack_require__(101);
  20312. function fixExtentWithBands(extent, nTick) {
  20313. var size = extent[1] - extent[0];
  20314. var len = nTick;
  20315. var margin = size / len / 2;
  20316. extent[0] += margin;
  20317. extent[1] -= margin;
  20318. }
  20319. var normalizedExtent = [0, 1];
  20320. /**
  20321. * @name module:echarts/coord/CartesianAxis
  20322. * @constructor
  20323. */
  20324. var Axis = function (dim, scale, extent) {
  20325. /**
  20326. * Axis dimension. Such as 'x', 'y', 'z', 'angle', 'radius'
  20327. * @type {string}
  20328. */
  20329. this.dim = dim;
  20330. /**
  20331. * Axis scale
  20332. * @type {module:echarts/coord/scale/*}
  20333. */
  20334. this.scale = scale;
  20335. /**
  20336. * @type {Array.<number>}
  20337. * @private
  20338. */
  20339. this._extent = extent || [0, 0];
  20340. /**
  20341. * @type {boolean}
  20342. */
  20343. this.inverse = false;
  20344. /**
  20345. * Usually true when axis has a ordinal scale
  20346. * @type {boolean}
  20347. */
  20348. this.onBand = false;
  20349. /**
  20350. * @private
  20351. * @type {number}
  20352. */
  20353. this._labelInterval;
  20354. };
  20355. Axis.prototype = {
  20356. constructor: Axis,
  20357. /**
  20358. * If axis extent contain given coord
  20359. * @param {number} coord
  20360. * @return {boolean}
  20361. */
  20362. contain: function (coord) {
  20363. var extent = this._extent;
  20364. var min = Math.min(extent[0], extent[1]);
  20365. var max = Math.max(extent[0], extent[1]);
  20366. return coord >= min && coord <= max;
  20367. },
  20368. /**
  20369. * If axis extent contain given data
  20370. * @param {number} data
  20371. * @return {boolean}
  20372. */
  20373. containData: function (data) {
  20374. return this.contain(this.dataToCoord(data));
  20375. },
  20376. /**
  20377. * Get coord extent.
  20378. * @return {Array.<number>}
  20379. */
  20380. getExtent: function () {
  20381. return this._extent.slice();
  20382. },
  20383. /**
  20384. * Get precision used for formatting
  20385. * @param {Array.<number>} [dataExtent]
  20386. * @return {number}
  20387. */
  20388. getPixelPrecision: function (dataExtent) {
  20389. return numberUtil.getPixelPrecision(
  20390. dataExtent || this.scale.getExtent(),
  20391. this._extent
  20392. );
  20393. },
  20394. /**
  20395. * Set coord extent
  20396. * @param {number} start
  20397. * @param {number} end
  20398. */
  20399. setExtent: function (start, end) {
  20400. var extent = this._extent;
  20401. extent[0] = start;
  20402. extent[1] = end;
  20403. },
  20404. /**
  20405. * Convert data to coord. Data is the rank if it has a ordinal scale
  20406. * @param {number} data
  20407. * @param {boolean} clamp
  20408. * @return {number}
  20409. */
  20410. dataToCoord: function (data, clamp) {
  20411. var extent = this._extent;
  20412. var scale = this.scale;
  20413. data = scale.normalize(data);
  20414. if (this.onBand && scale.type === 'ordinal') {
  20415. extent = extent.slice();
  20416. fixExtentWithBands(extent, scale.count());
  20417. }
  20418. return linearMap(data, normalizedExtent, extent, clamp);
  20419. },
  20420. /**
  20421. * Convert coord to data. Data is the rank if it has a ordinal scale
  20422. * @param {number} coord
  20423. * @param {boolean} clamp
  20424. * @return {number}
  20425. */
  20426. coordToData: function (coord, clamp) {
  20427. var extent = this._extent;
  20428. var scale = this.scale;
  20429. if (this.onBand && scale.type === 'ordinal') {
  20430. extent = extent.slice();
  20431. fixExtentWithBands(extent, scale.count());
  20432. }
  20433. var t = linearMap(coord, extent, normalizedExtent, clamp);
  20434. return this.scale.scale(t);
  20435. },
  20436. /**
  20437. * Convert pixel point to data in axis
  20438. * @param {Array.<number>} point
  20439. * @param {boolean} clamp
  20440. * @return {number} data
  20441. */
  20442. pointToData: function (point, clamp) {
  20443. // Should be implemented in derived class if necessary.
  20444. },
  20445. /**
  20446. * @return {Array.<number>}
  20447. */
  20448. getTicksCoords: function (alignWithLabel) {
  20449. if (this.onBand && !alignWithLabel) {
  20450. var bands = this.getBands();
  20451. var coords = [];
  20452. for (var i = 0; i < bands.length; i++) {
  20453. coords.push(bands[i][0]);
  20454. }
  20455. if (bands[i - 1]) {
  20456. coords.push(bands[i - 1][1]);
  20457. }
  20458. return coords;
  20459. }
  20460. else {
  20461. return zrUtil.map(this.scale.getTicks(), this.dataToCoord, this);
  20462. }
  20463. },
  20464. /**
  20465. * Coords of labels are on the ticks or on the middle of bands
  20466. * @return {Array.<number>}
  20467. */
  20468. getLabelsCoords: function () {
  20469. return zrUtil.map(this.scale.getTicks(), this.dataToCoord, this);
  20470. },
  20471. /**
  20472. * Get bands.
  20473. *
  20474. * If axis has labels [1, 2, 3, 4]. Bands on the axis are
  20475. * |---1---|---2---|---3---|---4---|.
  20476. *
  20477. * @return {Array}
  20478. */
  20479. // FIXME Situation when labels is on ticks
  20480. getBands: function () {
  20481. var extent = this.getExtent();
  20482. var bands = [];
  20483. var len = this.scale.count();
  20484. var start = extent[0];
  20485. var end = extent[1];
  20486. var span = end - start;
  20487. for (var i = 0; i < len; i++) {
  20488. bands.push([
  20489. span * i / len + start,
  20490. span * (i + 1) / len + start
  20491. ]);
  20492. }
  20493. return bands;
  20494. },
  20495. /**
  20496. * Get width of band
  20497. * @return {number}
  20498. */
  20499. getBandWidth: function () {
  20500. var axisExtent = this._extent;
  20501. var dataExtent = this.scale.getExtent();
  20502. var len = dataExtent[1] - dataExtent[0] + (this.onBand ? 1 : 0);
  20503. // Fix #2728, avoid NaN when only one data.
  20504. len === 0 && (len = 1);
  20505. var size = Math.abs(axisExtent[1] - axisExtent[0]);
  20506. return Math.abs(size) / len;
  20507. },
  20508. /**
  20509. * Get interval of the axis label.
  20510. * @return {number}
  20511. */
  20512. getLabelInterval: function () {
  20513. var labelInterval = this._labelInterval;
  20514. if (!labelInterval) {
  20515. var axisModel = this.model;
  20516. var labelModel = axisModel.getModel('axisLabel');
  20517. var interval = labelModel.get('interval');
  20518. if (!(this.type === 'category' && interval === 'auto')) {
  20519. labelInterval = interval === 'auto' ? 0 : interval;
  20520. }
  20521. else if (this.isHorizontal){
  20522. labelInterval = axisHelper.getAxisLabelInterval(
  20523. zrUtil.map(this.scale.getTicks(), this.dataToCoord, this),
  20524. axisModel.getFormattedLabels(),
  20525. labelModel.getModel('textStyle').getFont(),
  20526. this.isHorizontal()
  20527. );
  20528. }
  20529. this._labelInterval = labelInterval;
  20530. }
  20531. return labelInterval;
  20532. }
  20533. };
  20534. module.exports = Axis;
  20535. /***/ },
  20536. /* 101 */
  20537. /***/ function(module, exports, __webpack_require__) {
  20538. var OrdinalScale = __webpack_require__(102);
  20539. var IntervalScale = __webpack_require__(104);
  20540. __webpack_require__(106);
  20541. __webpack_require__(107);
  20542. var Scale = __webpack_require__(103);
  20543. var numberUtil = __webpack_require__(7);
  20544. var zrUtil = __webpack_require__(4);
  20545. var textContain = __webpack_require__(8);
  20546. var axisHelper = {};
  20547. /**
  20548. * Get axis scale extent before niced.
  20549. * Item of returned array can only be number (including Infinity and NaN).
  20550. */
  20551. axisHelper.getScaleExtent = function (scale, model) {
  20552. var scaleType = scale.type;
  20553. var min = model.getMin();
  20554. var max = model.getMax();
  20555. var fixMin = min != null;
  20556. var fixMax = max != null;
  20557. var originalExtent = scale.getExtent();
  20558. var axisDataLen;
  20559. var boundaryGap;
  20560. var span;
  20561. if (scaleType === 'ordinal') {
  20562. axisDataLen = (model.get('data') || []).length;
  20563. }
  20564. else {
  20565. boundaryGap = model.get('boundaryGap');
  20566. if (!zrUtil.isArray(boundaryGap)) {
  20567. boundaryGap = [boundaryGap || 0, boundaryGap || 0];
  20568. }
  20569. if (typeof boundaryGap[0] === 'boolean') {
  20570. if (true) {
  20571. console.warn('Boolean type for boundaryGap is only '
  20572. + 'allowed for ordinal axis. Please use string in '
  20573. + 'percentage instead, e.g., "20%". Currently, '
  20574. + 'boundaryGap is set to be 0.');
  20575. }
  20576. boundaryGap = [0, 0];
  20577. }
  20578. boundaryGap[0] = numberUtil.parsePercent(boundaryGap[0], 1);
  20579. boundaryGap[1] = numberUtil.parsePercent(boundaryGap[1], 1);
  20580. span = (originalExtent[1] - originalExtent[0])
  20581. || Math.abs(originalExtent[0]);
  20582. }
  20583. // Notice: When min/max is not set (that is, when there are null/undefined,
  20584. // which is the most common case), these cases should be ensured:
  20585. // (1) For 'ordinal', show all axis.data.
  20586. // (2) For others:
  20587. // + `boundaryGap` is applied (if min/max set, boundaryGap is
  20588. // disabled).
  20589. // + If `needCrossZero`, min/max should be zero, otherwise, min/max should
  20590. // be the result that originalExtent enlarged by boundaryGap.
  20591. // (3) If no data, it should be ensured that `scale.setBlank` is set.
  20592. // FIXME
  20593. // (1) When min/max is 'dataMin' or 'dataMax', should boundaryGap be able to used?
  20594. // (2) When `needCrossZero` and all data is positive/negative, should it be ensured
  20595. // that the results processed by boundaryGap are positive/negative?
  20596. if (min == null) {
  20597. min = scaleType === 'ordinal'
  20598. ? (axisDataLen ? 0 : NaN)
  20599. : originalExtent[0] - boundaryGap[0] * span;
  20600. }
  20601. if (max == null) {
  20602. max = scaleType === 'ordinal'
  20603. ? (axisDataLen ? axisDataLen - 1 : NaN)
  20604. : originalExtent[1] + boundaryGap[1] * span;
  20605. }
  20606. if (min === 'dataMin') {
  20607. min = originalExtent[0];
  20608. }
  20609. if (max === 'dataMax') {
  20610. max = originalExtent[1];
  20611. }
  20612. (min == null || !isFinite(min)) && (min = NaN);
  20613. (max == null || !isFinite(max)) && (max = NaN);
  20614. scale.setBlank(zrUtil.eqNaN(min) || zrUtil.eqNaN(max));
  20615. // Evaluate if axis needs cross zero
  20616. if (model.getNeedCrossZero()) {
  20617. // Axis is over zero and min is not set
  20618. if (min > 0 && max > 0 && !fixMin) {
  20619. min = 0;
  20620. }
  20621. // Axis is under zero and max is not set
  20622. if (min < 0 && max < 0 && !fixMax) {
  20623. max = 0;
  20624. }
  20625. }
  20626. return [min, max];
  20627. };
  20628. axisHelper.niceScaleExtent = function (scale, model) {
  20629. var extent = axisHelper.getScaleExtent(scale, model);
  20630. var fixMin = model.getMin() != null;
  20631. var fixMax = model.getMax() != null;
  20632. var splitNumber = model.get('splitNumber');
  20633. if (scale.type === 'log') {
  20634. scale.base = model.get('logBase');
  20635. }
  20636. scale.setExtent(extent[0], extent[1]);
  20637. scale.niceExtent({
  20638. splitNumber: splitNumber,
  20639. fixMin: fixMin,
  20640. fixMax: fixMax,
  20641. minInterval: scale.type === 'interval' ? model.get('minInterval') : null
  20642. });
  20643. // If some one specified the min, max. And the default calculated interval
  20644. // is not good enough. He can specify the interval. It is often appeared
  20645. // in angle axis with angle 0 - 360. Interval calculated in interval scale is hard
  20646. // to be 60.
  20647. // FIXME
  20648. var interval = model.get('interval');
  20649. if (interval != null) {
  20650. scale.setInterval && scale.setInterval(interval);
  20651. }
  20652. };
  20653. /**
  20654. * @param {module:echarts/model/Model} model
  20655. * @param {string} [axisType] Default retrieve from model.type
  20656. * @return {module:echarts/scale/*}
  20657. */
  20658. axisHelper.createScaleByModel = function(model, axisType) {
  20659. axisType = axisType || model.get('type');
  20660. if (axisType) {
  20661. switch (axisType) {
  20662. // Buildin scale
  20663. case 'category':
  20664. return new OrdinalScale(
  20665. model.getCategories(), [Infinity, -Infinity]
  20666. );
  20667. case 'value':
  20668. return new IntervalScale();
  20669. // Extended scale, like time and log
  20670. default:
  20671. return (Scale.getClass(axisType) || IntervalScale).create(model);
  20672. }
  20673. }
  20674. };
  20675. /**
  20676. * Check if the axis corss 0
  20677. */
  20678. axisHelper.ifAxisCrossZero = function (axis) {
  20679. var dataExtent = axis.scale.getExtent();
  20680. var min = dataExtent[0];
  20681. var max = dataExtent[1];
  20682. return !((min > 0 && max > 0) || (min < 0 && max < 0));
  20683. };
  20684. /**
  20685. * @param {Array.<number>} tickCoords In axis self coordinate.
  20686. * @param {Array.<string>} labels
  20687. * @param {string} font
  20688. * @param {boolean} isAxisHorizontal
  20689. * @return {number}
  20690. */
  20691. axisHelper.getAxisLabelInterval = function (tickCoords, labels, font, isAxisHorizontal) {
  20692. // FIXME
  20693. // 不同角的axis和label,不只是horizontal和vertical.
  20694. var textSpaceTakenRect;
  20695. var autoLabelInterval = 0;
  20696. var accumulatedLabelInterval = 0;
  20697. var step = 1;
  20698. if (labels.length > 40) {
  20699. // Simple optimization for large amount of labels
  20700. step = Math.floor(labels.length / 40);
  20701. }
  20702. for (var i = 0; i < tickCoords.length; i += step) {
  20703. var tickCoord = tickCoords[i];
  20704. var rect = textContain.getBoundingRect(
  20705. labels[i], font, 'center', 'top'
  20706. );
  20707. rect[isAxisHorizontal ? 'x' : 'y'] += tickCoord;
  20708. // FIXME Magic number 1.5
  20709. rect[isAxisHorizontal ? 'width' : 'height'] *= 1.3;
  20710. if (!textSpaceTakenRect) {
  20711. textSpaceTakenRect = rect.clone();
  20712. }
  20713. // There is no space for current label;
  20714. else if (textSpaceTakenRect.intersect(rect)) {
  20715. accumulatedLabelInterval++;
  20716. autoLabelInterval = Math.max(autoLabelInterval, accumulatedLabelInterval);
  20717. }
  20718. else {
  20719. textSpaceTakenRect.union(rect);
  20720. // Reset
  20721. accumulatedLabelInterval = 0;
  20722. }
  20723. }
  20724. if (autoLabelInterval === 0 && step > 1) {
  20725. return step;
  20726. }
  20727. return (autoLabelInterval + 1) * step - 1;
  20728. };
  20729. /**
  20730. * @param {Object} axis
  20731. * @param {Function} labelFormatter
  20732. * @return {Array.<string>}
  20733. */
  20734. axisHelper.getFormattedLabels = function (axis, labelFormatter) {
  20735. var scale = axis.scale;
  20736. var labels = scale.getTicksLabels();
  20737. var ticks = scale.getTicks();
  20738. if (typeof labelFormatter === 'string') {
  20739. labelFormatter = (function (tpl) {
  20740. return function (val) {
  20741. return tpl.replace('{value}', val != null ? val : '');
  20742. };
  20743. })(labelFormatter);
  20744. // Consider empty array
  20745. return zrUtil.map(labels, labelFormatter);
  20746. }
  20747. else if (typeof labelFormatter === 'function') {
  20748. return zrUtil.map(ticks, function (tick, idx) {
  20749. return labelFormatter(
  20750. axisHelper.getAxisRawValue(axis, tick),
  20751. idx
  20752. );
  20753. }, this);
  20754. }
  20755. else {
  20756. return labels;
  20757. }
  20758. };
  20759. axisHelper.getAxisRawValue = function (axis, value) {
  20760. // In category axis with data zoom, tick is not the original
  20761. // index of axis.data. So tick should not be exposed to user
  20762. // in category axis.
  20763. return axis.type === 'category' ? axis.scale.getLabel(value) : value;
  20764. };
  20765. module.exports = axisHelper;
  20766. /***/ },
  20767. /* 102 */
  20768. /***/ function(module, exports, __webpack_require__) {
  20769. /**
  20770. * Linear continuous scale
  20771. * @module echarts/coord/scale/Ordinal
  20772. *
  20773. * http://en.wikipedia.org/wiki/Level_of_measurement
  20774. */
  20775. // FIXME only one data
  20776. var zrUtil = __webpack_require__(4);
  20777. var Scale = __webpack_require__(103);
  20778. var scaleProto = Scale.prototype;
  20779. var OrdinalScale = Scale.extend({
  20780. type: 'ordinal',
  20781. init: function (data, extent) {
  20782. this._data = data;
  20783. this._extent = extent || [0, data.length - 1];
  20784. },
  20785. parse: function (val) {
  20786. return typeof val === 'string'
  20787. ? zrUtil.indexOf(this._data, val)
  20788. // val might be float.
  20789. : Math.round(val);
  20790. },
  20791. contain: function (rank) {
  20792. rank = this.parse(rank);
  20793. return scaleProto.contain.call(this, rank)
  20794. && this._data[rank] != null;
  20795. },
  20796. /**
  20797. * Normalize given rank or name to linear [0, 1]
  20798. * @param {number|string} [val]
  20799. * @return {number}
  20800. */
  20801. normalize: function (val) {
  20802. return scaleProto.normalize.call(this, this.parse(val));
  20803. },
  20804. scale: function (val) {
  20805. return Math.round(scaleProto.scale.call(this, val));
  20806. },
  20807. /**
  20808. * @return {Array}
  20809. */
  20810. getTicks: function () {
  20811. var ticks = [];
  20812. var extent = this._extent;
  20813. var rank = extent[0];
  20814. while (rank <= extent[1]) {
  20815. ticks.push(rank);
  20816. rank++;
  20817. }
  20818. return ticks;
  20819. },
  20820. /**
  20821. * Get item on rank n
  20822. * @param {number} n
  20823. * @return {string}
  20824. */
  20825. getLabel: function (n) {
  20826. return this._data[n];
  20827. },
  20828. /**
  20829. * @return {number}
  20830. */
  20831. count: function () {
  20832. return this._extent[1] - this._extent[0] + 1;
  20833. },
  20834. /**
  20835. * @override
  20836. */
  20837. unionExtentFromData: function (data, dim) {
  20838. this.unionExtent(data.getDataExtent(dim, false));
  20839. },
  20840. niceTicks: zrUtil.noop,
  20841. niceExtent: zrUtil.noop
  20842. });
  20843. /**
  20844. * @return {module:echarts/scale/Time}
  20845. */
  20846. OrdinalScale.create = function () {
  20847. return new OrdinalScale();
  20848. };
  20849. module.exports = OrdinalScale;
  20850. /***/ },
  20851. /* 103 */
  20852. /***/ function(module, exports, __webpack_require__) {
  20853. /**
  20854. * // Scale class management
  20855. * @module echarts/scale/Scale
  20856. */
  20857. var clazzUtil = __webpack_require__(13);
  20858. /**
  20859. * @param {Object} [setting]
  20860. */
  20861. function Scale(setting) {
  20862. this._setting = setting || {};
  20863. /**
  20864. * Extent
  20865. * @type {Array.<number>}
  20866. * @protected
  20867. */
  20868. this._extent = [Infinity, -Infinity];
  20869. /**
  20870. * Step is calculated in adjustExtent
  20871. * @type {Array.<number>}
  20872. * @protected
  20873. */
  20874. this._interval = 0;
  20875. this.init && this.init.apply(this, arguments);
  20876. }
  20877. var scaleProto = Scale.prototype;
  20878. /**
  20879. * Parse input val to valid inner number.
  20880. * @param {*} val
  20881. * @return {number}
  20882. */
  20883. scaleProto.parse = function (val) {
  20884. // Notice: This would be a trap here, If the implementation
  20885. // of this method depends on extent, and this method is used
  20886. // before extent set (like in dataZoom), it would be wrong.
  20887. // Nevertheless, parse does not depend on extent generally.
  20888. return val;
  20889. };
  20890. scaleProto.getSetting = function (name) {
  20891. return this._setting[name];
  20892. };
  20893. scaleProto.contain = function (val) {
  20894. var extent = this._extent;
  20895. return val >= extent[0] && val <= extent[1];
  20896. };
  20897. /**
  20898. * Normalize value to linear [0, 1], return 0.5 if extent span is 0
  20899. * @param {number} val
  20900. * @return {number}
  20901. */
  20902. scaleProto.normalize = function (val) {
  20903. var extent = this._extent;
  20904. if (extent[1] === extent[0]) {
  20905. return 0.5;
  20906. }
  20907. return (val - extent[0]) / (extent[1] - extent[0]);
  20908. };
  20909. /**
  20910. * Scale normalized value
  20911. * @param {number} val
  20912. * @return {number}
  20913. */
  20914. scaleProto.scale = function (val) {
  20915. var extent = this._extent;
  20916. return val * (extent[1] - extent[0]) + extent[0];
  20917. };
  20918. /**
  20919. * Set extent from data
  20920. * @param {Array.<number>} other
  20921. */
  20922. scaleProto.unionExtent = function (other) {
  20923. var extent = this._extent;
  20924. other[0] < extent[0] && (extent[0] = other[0]);
  20925. other[1] > extent[1] && (extent[1] = other[1]);
  20926. // not setExtent because in log axis it may transformed to power
  20927. // this.setExtent(extent[0], extent[1]);
  20928. };
  20929. /**
  20930. * Set extent from data
  20931. * @param {module:echarts/data/List} data
  20932. * @param {string} dim
  20933. */
  20934. scaleProto.unionExtentFromData = function (data, dim) {
  20935. this.unionExtent(data.getDataExtent(dim, true));
  20936. };
  20937. /**
  20938. * Get extent
  20939. * @return {Array.<number>}
  20940. */
  20941. scaleProto.getExtent = function () {
  20942. return this._extent.slice();
  20943. };
  20944. /**
  20945. * Set extent
  20946. * @param {number} start
  20947. * @param {number} end
  20948. */
  20949. scaleProto.setExtent = function (start, end) {
  20950. var thisExtent = this._extent;
  20951. if (!isNaN(start)) {
  20952. thisExtent[0] = start;
  20953. }
  20954. if (!isNaN(end)) {
  20955. thisExtent[1] = end;
  20956. }
  20957. };
  20958. /**
  20959. * @return {Array.<string>}
  20960. */
  20961. scaleProto.getTicksLabels = function () {
  20962. var labels = [];
  20963. var ticks = this.getTicks();
  20964. for (var i = 0; i < ticks.length; i++) {
  20965. labels.push(this.getLabel(ticks[i]));
  20966. }
  20967. return labels;
  20968. };
  20969. /**
  20970. * When axis extent depends on data and no data exists,
  20971. * axis ticks should not be drawn, which is named 'blank'.
  20972. */
  20973. scaleProto.isBlank = function () {
  20974. return this._isBlank;
  20975. },
  20976. /**
  20977. * When axis extent depends on data and no data exists,
  20978. * axis ticks should not be drawn, which is named 'blank'.
  20979. */
  20980. scaleProto.setBlank = function (isBlank) {
  20981. this._isBlank = isBlank;
  20982. };
  20983. clazzUtil.enableClassExtend(Scale);
  20984. clazzUtil.enableClassManagement(Scale, {
  20985. registerWhenExtend: true
  20986. });
  20987. module.exports = Scale;
  20988. /***/ },
  20989. /* 104 */
  20990. /***/ function(module, exports, __webpack_require__) {
  20991. /**
  20992. * Interval scale
  20993. * @module echarts/scale/Interval
  20994. */
  20995. var numberUtil = __webpack_require__(7);
  20996. var formatUtil = __webpack_require__(6);
  20997. var Scale = __webpack_require__(103);
  20998. var helper = __webpack_require__(105);
  20999. var roundNumber = numberUtil.round;
  21000. /**
  21001. * @alias module:echarts/coord/scale/Interval
  21002. * @constructor
  21003. */
  21004. var IntervalScale = Scale.extend({
  21005. type: 'interval',
  21006. _interval: 0,
  21007. _intervalPrecision: 2,
  21008. setExtent: function (start, end) {
  21009. var thisExtent = this._extent;
  21010. //start,end may be a Number like '25',so...
  21011. if (!isNaN(start)) {
  21012. thisExtent[0] = parseFloat(start);
  21013. }
  21014. if (!isNaN(end)) {
  21015. thisExtent[1] = parseFloat(end);
  21016. }
  21017. },
  21018. unionExtent: function (other) {
  21019. var extent = this._extent;
  21020. other[0] < extent[0] && (extent[0] = other[0]);
  21021. other[1] > extent[1] && (extent[1] = other[1]);
  21022. // unionExtent may called by it's sub classes
  21023. IntervalScale.prototype.setExtent.call(this, extent[0], extent[1]);
  21024. },
  21025. /**
  21026. * Get interval
  21027. */
  21028. getInterval: function () {
  21029. if (true) {
  21030. if (this._interval == null) {
  21031. throw new Error('`nice` should be called firstly' );
  21032. }
  21033. }
  21034. return this._interval;
  21035. },
  21036. /**
  21037. * Set interval
  21038. */
  21039. setInterval: function (interval) {
  21040. this._interval = interval;
  21041. // Dropped auto calculated niceExtent and use user setted extent
  21042. // We assume user wan't to set both interval, min, max to get a better result
  21043. this._niceExtent = this._extent.slice();
  21044. },
  21045. /**
  21046. * @return {Array.<number>}
  21047. */
  21048. getTicks: function () {
  21049. if (true) {
  21050. if (this._interval == null) {
  21051. throw new Error('`nice` should be called firstly' );
  21052. }
  21053. }
  21054. return helper.intervalScaleGetTicks(
  21055. this._interval, this._extent, this._niceExtent, this._intervalPrecision
  21056. );
  21057. },
  21058. /**
  21059. * @return {Array.<string>}
  21060. */
  21061. getTicksLabels: function () {
  21062. var labels = [];
  21063. var ticks = this.getTicks();
  21064. for (var i = 0; i < ticks.length; i++) {
  21065. labels.push(this.getLabel(ticks[i]));
  21066. }
  21067. return labels;
  21068. },
  21069. /**
  21070. * @param {number} data
  21071. * @param {Object} [opt]
  21072. * @param {number|string} [opt.precision] If 'auto', use nice presision.
  21073. * @param {boolean} [opt.pad] returns 1.50 but not 1.5 if precision is 2.
  21074. * @return {string}
  21075. */
  21076. getLabel: function (data, opt) {
  21077. if (data == null) {
  21078. return '';
  21079. }
  21080. var precision = opt && opt.precision;
  21081. if (precision == null) {
  21082. precision = numberUtil.getPrecisionSafe(data) || 0;
  21083. }
  21084. else if (precision === 'auto') {
  21085. // Should be more precise then tick.
  21086. precision = this._intervalPrecision;
  21087. }
  21088. // (1) If `precision` is set, 12.005 should be display as '12.00500'.
  21089. // (2) Use roundNumber (toFixed) to avoid scientific notation like '3.5e-7'.
  21090. data = roundNumber(data, precision, true);
  21091. return formatUtil.addCommas(data);
  21092. },
  21093. /**
  21094. * Update interval and extent of intervals for nice ticks
  21095. *
  21096. * @param {number} [splitNumber = 5] Desired number of ticks
  21097. * @param {number} [minInterval]
  21098. */
  21099. niceTicks: function (splitNumber, minInterval) {
  21100. splitNumber = splitNumber || 5;
  21101. var extent = this._extent;
  21102. var span = extent[1] - extent[0];
  21103. if (!isFinite(span)) {
  21104. return;
  21105. }
  21106. // User may set axis min 0 and data are all negative
  21107. // FIXME If it needs to reverse ?
  21108. if (span < 0) {
  21109. span = -span;
  21110. extent.reverse();
  21111. }
  21112. var result = helper.intervalScaleNiceTicks(extent, splitNumber, minInterval);
  21113. this._intervalPrecision = result.intervalPrecision;
  21114. this._interval = result.interval;
  21115. this._niceExtent = result.niceTickExtent;
  21116. },
  21117. /**
  21118. * Nice extent.
  21119. * @param {Object} opt
  21120. * @param {number} [opt.splitNumber = 5] Given approx tick number
  21121. * @param {boolean} [opt.fixMin=false]
  21122. * @param {boolean} [opt.fixMax=false]
  21123. * @param {boolean} [opt.minInterval=false]
  21124. */
  21125. niceExtent: function (opt) {
  21126. var extent = this._extent;
  21127. // If extent start and end are same, expand them
  21128. if (extent[0] === extent[1]) {
  21129. if (extent[0] !== 0) {
  21130. // Expand extent
  21131. var expandSize = extent[0];
  21132. // In the fowllowing case
  21133. // Axis has been fixed max 100
  21134. // Plus data are all 100 and axis extent are [100, 100].
  21135. // Extend to the both side will cause expanded max is larger than fixed max.
  21136. // So only expand to the smaller side.
  21137. if (!opt.fixMax) {
  21138. extent[1] += expandSize / 2;
  21139. extent[0] -= expandSize / 2;
  21140. }
  21141. else {
  21142. extent[0] -= expandSize / 2;
  21143. }
  21144. }
  21145. else {
  21146. extent[1] = 1;
  21147. }
  21148. }
  21149. var span = extent[1] - extent[0];
  21150. // If there are no data and extent are [Infinity, -Infinity]
  21151. if (!isFinite(span)) {
  21152. extent[0] = 0;
  21153. extent[1] = 1;
  21154. }
  21155. this.niceTicks(opt.splitNumber, opt.minInterval);
  21156. // var extent = this._extent;
  21157. var interval = this._interval;
  21158. if (!opt.fixMin) {
  21159. extent[0] = roundNumber(Math.floor(extent[0] / interval) * interval);
  21160. }
  21161. if (!opt.fixMax) {
  21162. extent[1] = roundNumber(Math.ceil(extent[1] / interval) * interval);
  21163. }
  21164. }
  21165. });
  21166. /**
  21167. * @return {module:echarts/scale/Time}
  21168. */
  21169. IntervalScale.create = function () {
  21170. return new IntervalScale();
  21171. };
  21172. module.exports = IntervalScale;
  21173. /***/ },
  21174. /* 105 */
  21175. /***/ function(module, exports, __webpack_require__) {
  21176. /**
  21177. * For testable.
  21178. */
  21179. var numberUtil = __webpack_require__(7);
  21180. var roundNumber = numberUtil.round;
  21181. var helper = {};
  21182. /**
  21183. * @param {Array.<number>} extent Both extent[0] and extent[1] should be valid number.
  21184. * Should be extent[0] < extent[1].
  21185. * @param {number} splitNumber splitNumber should be >= 1.
  21186. * @param {number} [minInterval]
  21187. * @return {Object} {interval, intervalPrecision, niceTickExtent}
  21188. */
  21189. helper.intervalScaleNiceTicks = function (extent, splitNumber, minInterval) {
  21190. var result = {};
  21191. var span = extent[1] - extent[0];
  21192. var interval = result.interval = numberUtil.nice(span / splitNumber, true);
  21193. if (minInterval != null && interval < minInterval) {
  21194. interval = result.interval = minInterval;
  21195. }
  21196. // Tow more digital for tick.
  21197. var precision = result.intervalPrecision = numberUtil.getPrecisionSafe(interval) + 2;
  21198. // Niced extent inside original extent
  21199. var niceTickExtent = result.niceTickExtent = [
  21200. roundNumber(Math.ceil(extent[0] / interval) * interval, precision),
  21201. roundNumber(Math.floor(extent[1] / interval) * interval, precision)
  21202. ];
  21203. helper.fixExtent(niceTickExtent, extent);
  21204. return result;
  21205. };
  21206. function clamp(niceTickExtent, idx, extent) {
  21207. niceTickExtent[idx] = Math.max(Math.min(niceTickExtent[idx], extent[1]), extent[0]);
  21208. }
  21209. // In some cases (e.g., splitNumber is 1), niceTickExtent may be out of extent.
  21210. helper.fixExtent = function (niceTickExtent, extent) {
  21211. !isFinite(niceTickExtent[0]) && (niceTickExtent[0] = extent[0]);
  21212. !isFinite(niceTickExtent[1]) && (niceTickExtent[1] = extent[1]);
  21213. clamp(niceTickExtent, 0, extent);
  21214. clamp(niceTickExtent, 1, extent);
  21215. if (niceTickExtent[0] > niceTickExtent[1]) {
  21216. niceTickExtent[0] = niceTickExtent[1];
  21217. }
  21218. };
  21219. helper.intervalScaleGetTicks = function (interval, extent, niceTickExtent, intervalPrecision) {
  21220. var ticks = [];
  21221. // If interval is 0, return [];
  21222. if (!interval) {
  21223. return ticks;
  21224. }
  21225. // Consider this case: using dataZoom toolbox, zoom and zoom.
  21226. var safeLimit = 10000;
  21227. if (extent[0] < niceTickExtent[0]) {
  21228. ticks.push(extent[0]);
  21229. }
  21230. var tick = niceTickExtent[0];
  21231. while (tick <= niceTickExtent[1]) {
  21232. ticks.push(tick);
  21233. // Avoid rounding error
  21234. tick = roundNumber(tick + interval, intervalPrecision);
  21235. if (tick === ticks[ticks.length - 1]) {
  21236. // Consider out of safe float point, e.g.,
  21237. // -3711126.9907707 + 2e-10 === -3711126.9907707
  21238. break;
  21239. }
  21240. if (ticks.length > safeLimit) {
  21241. return [];
  21242. }
  21243. }
  21244. // Consider this case: the last item of ticks is smaller
  21245. // than niceTickExtent[1] and niceTickExtent[1] === extent[1].
  21246. if (extent[1] > (ticks.length ? ticks[ticks.length - 1] : niceTickExtent[1])) {
  21247. ticks.push(extent[1]);
  21248. }
  21249. return ticks;
  21250. };
  21251. module.exports = helper;
  21252. /***/ },
  21253. /* 106 */
  21254. /***/ function(module, exports, __webpack_require__) {
  21255. /**
  21256. * Interval scale
  21257. * @module echarts/coord/scale/Time
  21258. */
  21259. // [About UTC and local time zone]:
  21260. // In most cases, `number.parseDate` will treat input data string as local time
  21261. // (except time zone is specified in time string). And `format.formateTime` returns
  21262. // local time by default. option.useUTC is false by default. This design have
  21263. // concidered these common case:
  21264. // (1) Time that is persistent in server is in UTC, but it is needed to be diplayed
  21265. // in local time by default.
  21266. // (2) By default, the input data string (e.g., '2011-01-02') should be displayed
  21267. // as its original time, without any time difference.
  21268. var zrUtil = __webpack_require__(4);
  21269. var numberUtil = __webpack_require__(7);
  21270. var formatUtil = __webpack_require__(6);
  21271. var scaleHelper = __webpack_require__(105);
  21272. var IntervalScale = __webpack_require__(104);
  21273. var intervalScaleProto = IntervalScale.prototype;
  21274. var mathCeil = Math.ceil;
  21275. var mathFloor = Math.floor;
  21276. var ONE_SECOND = 1000;
  21277. var ONE_MINUTE = ONE_SECOND * 60;
  21278. var ONE_HOUR = ONE_MINUTE * 60;
  21279. var ONE_DAY = ONE_HOUR * 24;
  21280. // FIXME 公用?
  21281. var bisect = function (a, x, lo, hi) {
  21282. while (lo < hi) {
  21283. var mid = lo + hi >>> 1;
  21284. if (a[mid][2] < x) {
  21285. lo = mid + 1;
  21286. }
  21287. else {
  21288. hi = mid;
  21289. }
  21290. }
  21291. return lo;
  21292. };
  21293. /**
  21294. * @alias module:echarts/coord/scale/Time
  21295. * @constructor
  21296. */
  21297. var TimeScale = IntervalScale.extend({
  21298. type: 'time',
  21299. /**
  21300. * @override
  21301. */
  21302. getLabel: function (val) {
  21303. var stepLvl = this._stepLvl;
  21304. var date = new Date(val);
  21305. return formatUtil.formatTime(stepLvl[0], date, this.getSetting('useUTC'));
  21306. },
  21307. /**
  21308. * @override
  21309. */
  21310. niceExtent: function (opt) {
  21311. var extent = this._extent;
  21312. // If extent start and end are same, expand them
  21313. if (extent[0] === extent[1]) {
  21314. // Expand extent
  21315. extent[0] -= ONE_DAY;
  21316. extent[1] += ONE_DAY;
  21317. }
  21318. // If there are no data and extent are [Infinity, -Infinity]
  21319. if (extent[1] === -Infinity && extent[0] === Infinity) {
  21320. var d = new Date();
  21321. extent[1] = new Date(d.getFullYear(), d.getMonth(), d.getDate());
  21322. extent[0] = extent[1] - ONE_DAY;
  21323. }
  21324. this.niceTicks(opt.splitNumber);
  21325. // var extent = this._extent;
  21326. var interval = this._interval;
  21327. if (!opt.fixMin) {
  21328. extent[0] = numberUtil.round(mathFloor(extent[0] / interval) * interval);
  21329. }
  21330. if (!opt.fixMax) {
  21331. extent[1] = numberUtil.round(mathCeil(extent[1] / interval) * interval);
  21332. }
  21333. },
  21334. /**
  21335. * @override
  21336. */
  21337. niceTicks: function (approxTickNum) {
  21338. var timezoneOffset = this.getSetting('useUTC')
  21339. ? 0 : numberUtil.getTimezoneOffset() * 60 * 1000;
  21340. approxTickNum = approxTickNum || 10;
  21341. var extent = this._extent;
  21342. var span = extent[1] - extent[0];
  21343. var approxInterval = span / approxTickNum;
  21344. var scaleLevelsLen = scaleLevels.length;
  21345. var idx = bisect(scaleLevels, approxInterval, 0, scaleLevelsLen);
  21346. var level = scaleLevels[Math.min(idx, scaleLevelsLen - 1)];
  21347. var interval = level[2];
  21348. // Same with interval scale if span is much larger than 1 year
  21349. if (level[0] === 'year') {
  21350. var yearSpan = span / interval;
  21351. // From "Nice Numbers for Graph Labels" of Graphic Gems
  21352. // var niceYearSpan = numberUtil.nice(yearSpan, false);
  21353. var yearStep = numberUtil.nice(yearSpan / approxTickNum, true);
  21354. interval *= yearStep;
  21355. }
  21356. var niceExtent = [
  21357. Math.round(mathCeil((extent[0] - timezoneOffset) / interval) * interval + timezoneOffset),
  21358. Math.round(mathFloor((extent[1] - timezoneOffset)/ interval) * interval + timezoneOffset)
  21359. ];
  21360. scaleHelper.fixExtent(niceExtent, extent);
  21361. this._stepLvl = level;
  21362. // Interval will be used in getTicks
  21363. this._interval = interval;
  21364. this._niceExtent = niceExtent;
  21365. },
  21366. parse: function (val) {
  21367. // val might be float.
  21368. return +numberUtil.parseDate(val);
  21369. }
  21370. });
  21371. zrUtil.each(['contain', 'normalize'], function (methodName) {
  21372. TimeScale.prototype[methodName] = function (val) {
  21373. return intervalScaleProto[methodName].call(this, this.parse(val));
  21374. };
  21375. });
  21376. // Steps from d3
  21377. var scaleLevels = [
  21378. // Format step interval
  21379. ['hh:mm:ss', 1, ONE_SECOND], // 1s
  21380. ['hh:mm:ss', 5, ONE_SECOND * 5], // 5s
  21381. ['hh:mm:ss', 10, ONE_SECOND * 10], // 10s
  21382. ['hh:mm:ss', 15, ONE_SECOND * 15], // 15s
  21383. ['hh:mm:ss', 30, ONE_SECOND * 30], // 30s
  21384. ['hh:mm\nMM-dd',1, ONE_MINUTE], // 1m
  21385. ['hh:mm\nMM-dd',5, ONE_MINUTE * 5], // 5m
  21386. ['hh:mm\nMM-dd',10, ONE_MINUTE * 10], // 10m
  21387. ['hh:mm\nMM-dd',15, ONE_MINUTE * 15], // 15m
  21388. ['hh:mm\nMM-dd',30, ONE_MINUTE * 30], // 30m
  21389. ['hh:mm\nMM-dd',1, ONE_HOUR], // 1h
  21390. ['hh:mm\nMM-dd',2, ONE_HOUR * 2], // 2h
  21391. ['hh:mm\nMM-dd',6, ONE_HOUR * 6], // 6h
  21392. ['hh:mm\nMM-dd',12, ONE_HOUR * 12], // 12h
  21393. ['MM-dd\nyyyy', 1, ONE_DAY], // 1d
  21394. ['week', 7, ONE_DAY * 7], // 7d
  21395. ['month', 1, ONE_DAY * 31], // 1M
  21396. ['quarter', 3, ONE_DAY * 380 / 4], // 3M
  21397. ['half-year', 6, ONE_DAY * 380 / 2], // 6M
  21398. ['year', 1, ONE_DAY * 380] // 1Y
  21399. ];
  21400. /**
  21401. * @param {module:echarts/model/Model}
  21402. * @return {module:echarts/scale/Time}
  21403. */
  21404. TimeScale.create = function (model) {
  21405. return new TimeScale({useUTC: model.ecModel.get('useUTC')});
  21406. };
  21407. module.exports = TimeScale;
  21408. /***/ },
  21409. /* 107 */
  21410. /***/ function(module, exports, __webpack_require__) {
  21411. /**
  21412. * Log scale
  21413. * @module echarts/scale/Log
  21414. */
  21415. var zrUtil = __webpack_require__(4);
  21416. var Scale = __webpack_require__(103);
  21417. var numberUtil = __webpack_require__(7);
  21418. // Use some method of IntervalScale
  21419. var IntervalScale = __webpack_require__(104);
  21420. var scaleProto = Scale.prototype;
  21421. var intervalScaleProto = IntervalScale.prototype;
  21422. var getPrecisionSafe = numberUtil.getPrecisionSafe;
  21423. var roundingErrorFix = numberUtil.round;
  21424. var mathFloor = Math.floor;
  21425. var mathCeil = Math.ceil;
  21426. var mathPow = Math.pow;
  21427. var mathLog = Math.log;
  21428. var LogScale = Scale.extend({
  21429. type: 'log',
  21430. base: 10,
  21431. $constructor: function () {
  21432. Scale.apply(this, arguments);
  21433. this._originalScale = new IntervalScale();
  21434. },
  21435. /**
  21436. * @return {Array.<number>}
  21437. */
  21438. getTicks: function () {
  21439. var originalScale = this._originalScale;
  21440. var extent = this._extent;
  21441. var originalExtent = originalScale.getExtent();
  21442. return zrUtil.map(intervalScaleProto.getTicks.call(this), function (val) {
  21443. var powVal = numberUtil.round(mathPow(this.base, val));
  21444. // Fix #4158
  21445. powVal = (val === extent[0] && originalScale.__fixMin)
  21446. ? fixRoundingError(powVal, originalExtent[0])
  21447. : powVal;
  21448. powVal = (val === extent[1] && originalScale.__fixMax)
  21449. ? fixRoundingError(powVal, originalExtent[1])
  21450. : powVal;
  21451. return powVal;
  21452. }, this);
  21453. },
  21454. /**
  21455. * @param {number} val
  21456. * @return {string}
  21457. */
  21458. getLabel: intervalScaleProto.getLabel,
  21459. /**
  21460. * @param {number} val
  21461. * @return {number}
  21462. */
  21463. scale: function (val) {
  21464. val = scaleProto.scale.call(this, val);
  21465. return mathPow(this.base, val);
  21466. },
  21467. /**
  21468. * @param {number} start
  21469. * @param {number} end
  21470. */
  21471. setExtent: function (start, end) {
  21472. var base = this.base;
  21473. start = mathLog(start) / mathLog(base);
  21474. end = mathLog(end) / mathLog(base);
  21475. intervalScaleProto.setExtent.call(this, start, end);
  21476. },
  21477. /**
  21478. * @return {number} end
  21479. */
  21480. getExtent: function () {
  21481. var base = this.base;
  21482. var extent = scaleProto.getExtent.call(this);
  21483. extent[0] = mathPow(base, extent[0]);
  21484. extent[1] = mathPow(base, extent[1]);
  21485. // Fix #4158
  21486. var originalScale = this._originalScale;
  21487. var originalExtent = originalScale.getExtent();
  21488. originalScale.__fixMin && (extent[0] = fixRoundingError(extent[0], originalExtent[0]));
  21489. originalScale.__fixMax && (extent[1] = fixRoundingError(extent[1], originalExtent[1]));
  21490. return extent;
  21491. },
  21492. /**
  21493. * @param {Array.<number>} extent
  21494. */
  21495. unionExtent: function (extent) {
  21496. this._originalScale.unionExtent(extent);
  21497. var base = this.base;
  21498. extent[0] = mathLog(extent[0]) / mathLog(base);
  21499. extent[1] = mathLog(extent[1]) / mathLog(base);
  21500. scaleProto.unionExtent.call(this, extent);
  21501. },
  21502. /**
  21503. * @override
  21504. */
  21505. unionExtentFromData: function (data, dim) {
  21506. this.unionExtent(data.getDataExtent(dim, true, function (val) {
  21507. return val > 0;
  21508. }));
  21509. },
  21510. /**
  21511. * Update interval and extent of intervals for nice ticks
  21512. * @param {number} [approxTickNum = 10] Given approx tick number
  21513. */
  21514. niceTicks: function (approxTickNum) {
  21515. approxTickNum = approxTickNum || 10;
  21516. var extent = this._extent;
  21517. var span = extent[1] - extent[0];
  21518. if (span === Infinity || span <= 0) {
  21519. return;
  21520. }
  21521. var interval = numberUtil.quantity(span);
  21522. var err = approxTickNum / span * interval;
  21523. // Filter ticks to get closer to the desired count.
  21524. if (err <= 0.5) {
  21525. interval *= 10;
  21526. }
  21527. // Interval should be integer
  21528. while (!isNaN(interval) && Math.abs(interval) < 1 && Math.abs(interval) > 0) {
  21529. interval *= 10;
  21530. }
  21531. var niceExtent = [
  21532. numberUtil.round(mathCeil(extent[0] / interval) * interval),
  21533. numberUtil.round(mathFloor(extent[1] / interval) * interval)
  21534. ];
  21535. this._interval = interval;
  21536. this._niceExtent = niceExtent;
  21537. },
  21538. /**
  21539. * Nice extent.
  21540. * @override
  21541. */
  21542. niceExtent: function (opt) {
  21543. intervalScaleProto.niceExtent.call(this, opt);
  21544. var originalScale = this._originalScale;
  21545. originalScale.__fixMin = opt.fixMin;
  21546. originalScale.__fixMax = opt.fixMax;
  21547. }
  21548. });
  21549. zrUtil.each(['contain', 'normalize'], function (methodName) {
  21550. LogScale.prototype[methodName] = function (val) {
  21551. val = mathLog(val) / mathLog(this.base);
  21552. return scaleProto[methodName].call(this, val);
  21553. };
  21554. });
  21555. LogScale.create = function () {
  21556. return new LogScale();
  21557. };
  21558. function fixRoundingError(val, originalVal) {
  21559. return roundingErrorFix(val, getPrecisionSafe(originalVal));
  21560. }
  21561. module.exports = LogScale;
  21562. /***/ },
  21563. /* 108 */
  21564. /***/ function(module, exports, __webpack_require__) {
  21565. var createListFromArray = __webpack_require__(109);
  21566. var symbolUtil = __webpack_require__(111);
  21567. var axisHelper = __webpack_require__(101);
  21568. var axisModelCommonMixin = __webpack_require__(112);
  21569. var Model = __webpack_require__(12);
  21570. var util = __webpack_require__(4);
  21571. module.exports = {
  21572. /**
  21573. * Create a muti dimension List structure from seriesModel.
  21574. * @param {module:echarts/model/Model} seriesModel
  21575. * @return {module:echarts/data/List} list
  21576. */
  21577. createList: function (seriesModel) {
  21578. var data = seriesModel.get('data');
  21579. return createListFromArray(data, seriesModel, seriesModel.ecModel);
  21580. },
  21581. /**
  21582. * @see {module:echarts/data/helper/completeDimensions}
  21583. */
  21584. completeDimensions: __webpack_require__(110),
  21585. /**
  21586. * Create a symbol element with given symbol configuration: shape, x, y, width, height, color
  21587. * @see http://echarts.baidu.com/option.html#series-scatter.symbol
  21588. * @param {string} symbolDesc
  21589. * @param {number} x
  21590. * @param {number} y
  21591. * @param {number} w
  21592. * @param {number} h
  21593. * @param {string} color
  21594. */
  21595. createSymbol: symbolUtil.createSymbol,
  21596. /**
  21597. * Create scale
  21598. * @param {Array.<number>} dataExtent
  21599. * @param {Object|module:echarts/Model} option
  21600. */
  21601. createScale: function (dataExtent, option) {
  21602. var axisModel = option;
  21603. if (!(option instanceof Model)) {
  21604. axisModel = new Model(option);
  21605. util.mixin(axisModel, axisModelCommonMixin);
  21606. }
  21607. var scale = axisHelper.createScaleByModel(axisModel);
  21608. scale.setExtent(dataExtent[0], dataExtent[1]);
  21609. axisHelper.niceScaleExtent(scale, axisModel);
  21610. return scale;
  21611. },
  21612. /**
  21613. * Mixin common methods to axis model,
  21614. *
  21615. * Inlcude methods
  21616. * `getFormattedLabels() => Array.<string>`
  21617. * `getCategories() => Array.<string>`
  21618. * `getMin(origin: boolean) => number`
  21619. * `getMax(origin: boolean) => number`
  21620. * `getNeedCrossZero() => boolean`
  21621. * `setRange(start: number, end: number)`
  21622. * `resetRange()`
  21623. */
  21624. mixinAxisModelCommonMethods: function (Model) {
  21625. util.mixin(Model, axisModelCommonMixin);
  21626. }
  21627. };
  21628. /***/ },
  21629. /* 109 */
  21630. /***/ function(module, exports, __webpack_require__) {
  21631. 'use strict';
  21632. var List = __webpack_require__(98);
  21633. var completeDimensions = __webpack_require__(110);
  21634. var zrUtil = __webpack_require__(4);
  21635. var modelUtil = __webpack_require__(5);
  21636. var CoordinateSystem = __webpack_require__(76);
  21637. var getDataItemValue = modelUtil.getDataItemValue;
  21638. var converDataValue = modelUtil.converDataValue;
  21639. function firstDataNotNull(data) {
  21640. var i = 0;
  21641. while (i < data.length && data[i] == null) {
  21642. i++;
  21643. }
  21644. return data[i];
  21645. }
  21646. function ifNeedCompleteOrdinalData(data) {
  21647. var sampleItem = firstDataNotNull(data);
  21648. return sampleItem != null
  21649. && !zrUtil.isArray(getDataItemValue(sampleItem));
  21650. }
  21651. /**
  21652. * Helper function to create a list from option data
  21653. */
  21654. function createListFromArray(data, seriesModel, ecModel) {
  21655. // If data is undefined
  21656. data = data || [];
  21657. if (true) {
  21658. if (!zrUtil.isArray(data)) {
  21659. throw new Error('Invalid data.');
  21660. }
  21661. }
  21662. var coordSysName = seriesModel.get('coordinateSystem');
  21663. var creator = creators[coordSysName];
  21664. var registeredCoordSys = CoordinateSystem.get(coordSysName);
  21665. var completeDimOpt = {
  21666. encodeDef: seriesModel.get('encode'),
  21667. dimsDef: seriesModel.get('dimensions')
  21668. };
  21669. // FIXME
  21670. var axesInfo = creator && creator(data, seriesModel, ecModel, completeDimOpt);
  21671. var dimensions = axesInfo && axesInfo.dimensions;
  21672. if (!dimensions) {
  21673. // Get dimensions from registered coordinate system
  21674. dimensions = (registeredCoordSys && (
  21675. registeredCoordSys.getDimensionsInfo
  21676. ? registeredCoordSys.getDimensionsInfo()
  21677. : registeredCoordSys.dimensions.slice()
  21678. )) || ['x', 'y'];
  21679. dimensions = completeDimensions(dimensions, data, completeDimOpt);
  21680. }
  21681. var categoryIndex = axesInfo ? axesInfo.categoryIndex : -1;
  21682. var list = new List(dimensions, seriesModel);
  21683. var nameList = createNameList(axesInfo, data);
  21684. var categories = {};
  21685. var dimValueGetter = (categoryIndex >= 0 && ifNeedCompleteOrdinalData(data))
  21686. ? function (itemOpt, dimName, dataIndex, dimIndex) {
  21687. // If any dataItem is like { value: 10 }
  21688. if (modelUtil.isDataItemOption(itemOpt)) {
  21689. list.hasItemOption = true;
  21690. }
  21691. // Use dataIndex as ordinal value in categoryAxis
  21692. return dimIndex === categoryIndex
  21693. ? dataIndex
  21694. : converDataValue(getDataItemValue(itemOpt), dimensions[dimIndex]);
  21695. }
  21696. : function (itemOpt, dimName, dataIndex, dimIndex) {
  21697. var value = getDataItemValue(itemOpt);
  21698. var val = converDataValue(value && value[dimIndex], dimensions[dimIndex]);
  21699. // If any dataItem is like { value: 10 }
  21700. if (modelUtil.isDataItemOption(itemOpt)) {
  21701. list.hasItemOption = true;
  21702. }
  21703. var categoryAxesModels = axesInfo && axesInfo.categoryAxesModels;
  21704. if (categoryAxesModels && categoryAxesModels[dimName]) {
  21705. // If given value is a category string
  21706. if (typeof val === 'string') {
  21707. // Lazy get categories
  21708. categories[dimName] = categories[dimName]
  21709. || categoryAxesModels[dimName].getCategories();
  21710. val = zrUtil.indexOf(categories[dimName], val);
  21711. if (val < 0 && !isNaN(val)) {
  21712. // In case some one write '1', '2' istead of 1, 2
  21713. val = +val;
  21714. }
  21715. }
  21716. }
  21717. return val;
  21718. };
  21719. list.hasItemOption = false;
  21720. list.initData(data, nameList, dimValueGetter);
  21721. return list;
  21722. }
  21723. function isStackable(axisType) {
  21724. return axisType !== 'category' && axisType !== 'time';
  21725. }
  21726. function getDimTypeByAxis(axisType) {
  21727. return axisType === 'category'
  21728. ? 'ordinal'
  21729. : axisType === 'time'
  21730. ? 'time'
  21731. : 'float';
  21732. }
  21733. /**
  21734. * Creaters for each coord system.
  21735. */
  21736. var creators = {
  21737. cartesian2d: function (data, seriesModel, ecModel, completeDimOpt) {
  21738. var axesModels = zrUtil.map(['xAxis', 'yAxis'], function (name) {
  21739. return ecModel.queryComponents({
  21740. mainType: name,
  21741. index: seriesModel.get(name + 'Index'),
  21742. id: seriesModel.get(name + 'Id')
  21743. })[0];
  21744. });
  21745. var xAxisModel = axesModels[0];
  21746. var yAxisModel = axesModels[1];
  21747. if (true) {
  21748. if (!xAxisModel) {
  21749. throw new Error('xAxis "' + zrUtil.retrieve(
  21750. seriesModel.get('xAxisIndex'),
  21751. seriesModel.get('xAxisId'),
  21752. 0
  21753. ) + '" not found');
  21754. }
  21755. if (!yAxisModel) {
  21756. throw new Error('yAxis "' + zrUtil.retrieve(
  21757. seriesModel.get('xAxisIndex'),
  21758. seriesModel.get('yAxisId'),
  21759. 0
  21760. ) + '" not found');
  21761. }
  21762. }
  21763. var xAxisType = xAxisModel.get('type');
  21764. var yAxisType = yAxisModel.get('type');
  21765. var dimensions = [
  21766. {
  21767. name: 'x',
  21768. type: getDimTypeByAxis(xAxisType),
  21769. stackable: isStackable(xAxisType)
  21770. },
  21771. {
  21772. name: 'y',
  21773. // If two category axes
  21774. type: getDimTypeByAxis(yAxisType),
  21775. stackable: isStackable(yAxisType)
  21776. }
  21777. ];
  21778. var isXAxisCateogry = xAxisType === 'category';
  21779. var isYAxisCategory = yAxisType === 'category';
  21780. dimensions = completeDimensions(dimensions, data, completeDimOpt);
  21781. var categoryAxesModels = {};
  21782. if (isXAxisCateogry) {
  21783. categoryAxesModels.x = xAxisModel;
  21784. }
  21785. if (isYAxisCategory) {
  21786. categoryAxesModels.y = yAxisModel;
  21787. }
  21788. return {
  21789. dimensions: dimensions,
  21790. categoryIndex: isXAxisCateogry ? 0 : (isYAxisCategory ? 1 : -1),
  21791. categoryAxesModels: categoryAxesModels
  21792. };
  21793. },
  21794. singleAxis: function (data, seriesModel, ecModel, completeDimOpt) {
  21795. var singleAxisModel = ecModel.queryComponents({
  21796. mainType: 'singleAxis',
  21797. index: seriesModel.get('singleAxisIndex'),
  21798. id: seriesModel.get('singleAxisId')
  21799. })[0];
  21800. if (true) {
  21801. if (!singleAxisModel) {
  21802. throw new Error('singleAxis should be specified.');
  21803. }
  21804. }
  21805. var singleAxisType = singleAxisModel.get('type');
  21806. var isCategory = singleAxisType === 'category';
  21807. var dimensions = [{
  21808. name: 'single',
  21809. type: getDimTypeByAxis(singleAxisType),
  21810. stackable: isStackable(singleAxisType)
  21811. }];
  21812. dimensions = completeDimensions(dimensions, data, completeDimOpt);
  21813. var categoryAxesModels = {};
  21814. if (isCategory) {
  21815. categoryAxesModels.single = singleAxisModel;
  21816. }
  21817. return {
  21818. dimensions: dimensions,
  21819. categoryIndex: isCategory ? 0 : -1,
  21820. categoryAxesModels: categoryAxesModels
  21821. };
  21822. },
  21823. polar: function (data, seriesModel, ecModel, completeDimOpt) {
  21824. var polarModel = ecModel.queryComponents({
  21825. mainType: 'polar',
  21826. index: seriesModel.get('polarIndex'),
  21827. id: seriesModel.get('polarId')
  21828. })[0];
  21829. var angleAxisModel = polarModel.findAxisModel('angleAxis');
  21830. var radiusAxisModel = polarModel.findAxisModel('radiusAxis');
  21831. if (true) {
  21832. if (!angleAxisModel) {
  21833. throw new Error('angleAxis option not found');
  21834. }
  21835. if (!radiusAxisModel) {
  21836. throw new Error('radiusAxis option not found');
  21837. }
  21838. }
  21839. var radiusAxisType = radiusAxisModel.get('type');
  21840. var angleAxisType = angleAxisModel.get('type');
  21841. var dimensions = [
  21842. {
  21843. name: 'radius',
  21844. type: getDimTypeByAxis(radiusAxisType),
  21845. stackable: isStackable(radiusAxisType)
  21846. },
  21847. {
  21848. name: 'angle',
  21849. type: getDimTypeByAxis(angleAxisType),
  21850. stackable: isStackable(angleAxisType)
  21851. }
  21852. ];
  21853. var isAngleAxisCateogry = angleAxisType === 'category';
  21854. var isRadiusAxisCateogry = radiusAxisType === 'category';
  21855. dimensions = completeDimensions(dimensions, data, completeDimOpt);
  21856. var categoryAxesModels = {};
  21857. if (isRadiusAxisCateogry) {
  21858. categoryAxesModels.radius = radiusAxisModel;
  21859. }
  21860. if (isAngleAxisCateogry) {
  21861. categoryAxesModels.angle = angleAxisModel;
  21862. }
  21863. return {
  21864. dimensions: dimensions,
  21865. categoryIndex: isAngleAxisCateogry ? 1 : (isRadiusAxisCateogry ? 0 : -1),
  21866. categoryAxesModels: categoryAxesModels
  21867. };
  21868. },
  21869. geo: function (data, seriesModel, ecModel, completeDimOpt) {
  21870. // TODO Region
  21871. // 多个散点图系列在同一个地区的时候
  21872. return {
  21873. dimensions: completeDimensions([
  21874. {name: 'lng'},
  21875. {name: 'lat'}
  21876. ], data, completeDimOpt)
  21877. };
  21878. }
  21879. };
  21880. function createNameList(result, data) {
  21881. var nameList = [];
  21882. var categoryDim = result && result.dimensions[result.categoryIndex];
  21883. var categoryAxisModel;
  21884. if (categoryDim) {
  21885. categoryAxisModel = result.categoryAxesModels[categoryDim.name];
  21886. }
  21887. if (categoryAxisModel) {
  21888. // FIXME Two category axis
  21889. var categories = categoryAxisModel.getCategories();
  21890. if (categories) {
  21891. var dataLen = data.length;
  21892. // Ordered data is given explicitly like
  21893. // [[3, 0.2], [1, 0.3], [2, 0.15]]
  21894. // or given scatter data,
  21895. // pick the category
  21896. if (zrUtil.isArray(data[0]) && data[0].length > 1) {
  21897. nameList = [];
  21898. for (var i = 0; i < dataLen; i++) {
  21899. nameList[i] = categories[data[i][result.categoryIndex || 0]];
  21900. }
  21901. }
  21902. else {
  21903. nameList = categories.slice(0);
  21904. }
  21905. }
  21906. }
  21907. return nameList;
  21908. }
  21909. module.exports = createListFromArray;
  21910. /***/ },
  21911. /* 110 */
  21912. /***/ function(module, exports, __webpack_require__) {
  21913. /**
  21914. * Complete dimensions by data (guess dimension).
  21915. */
  21916. var zrUtil = __webpack_require__(4);
  21917. var modelUtil = __webpack_require__(5);
  21918. var each = zrUtil.each;
  21919. var isString = zrUtil.isString;
  21920. var defaults = zrUtil.defaults;
  21921. var normalizeToArray = modelUtil.normalizeToArray;
  21922. var OTHER_DIMS = {tooltip: 1, label: 1, itemName: 1};
  21923. /**
  21924. * Complete the dimensions array, by user defined `dimension` and `encode`,
  21925. * and guessing from the data structure.
  21926. * If no 'value' dimension specified, the first no-named dimension will be
  21927. * named as 'value'.
  21928. *
  21929. * @param {Array.<string>} sysDims Necessary dimensions, like ['x', 'y'], which
  21930. * provides not only dim template, but also default order.
  21931. * `name` of each item provides default coord name.
  21932. * [{dimsDef: []}, ...] can be specified to give names.
  21933. * @param {Array} data Data list. [[1, 2, 3], [2, 3, 4]].
  21934. * @param {Object} [opt]
  21935. * @param {Array.<Object|string>} [opt.dimsDef] option.series.dimensions User defined dimensions
  21936. * For example: ['asdf', {name, type}, ...].
  21937. * @param {Object} [opt.encodeDef] option.series.encode {x: 2, y: [3, 1], tooltip: [1, 2], label: 3}
  21938. * @param {string} [opt.extraPrefix] Prefix of name when filling the left dimensions.
  21939. * @param {string} [opt.extraFromZero] If specified, extra dim names will be:
  21940. * extraPrefix + 0, extraPrefix + extraBaseIndex + 1 ...
  21941. * If not specified, extra dim names will be:
  21942. * extraPrefix, extraPrefix + 0, extraPrefix + 1 ...
  21943. * @param {number} [opt.dimCount] If not specified, guess by the first data item.
  21944. * @return {Array.<Object>} [{
  21945. * name: string mandatory,
  21946. * coordDim: string mandatory,
  21947. * coordDimIndex: number mandatory,
  21948. * type: string optional,
  21949. * tooltipName: string optional,
  21950. * otherDims: {
  21951. * tooltip: number optional,
  21952. * label: number optional
  21953. * },
  21954. * isExtraCoord: boolean true or undefined.
  21955. * other props ...
  21956. * }]
  21957. */
  21958. function completeDimensions(sysDims, data, opt) {
  21959. data = data || [];
  21960. opt = opt || {};
  21961. sysDims = (sysDims || []).slice();
  21962. var dimsDef = (opt.dimsDef || []).slice();
  21963. var encodeDef = zrUtil.createHashMap(opt.encodeDef);
  21964. var dataDimNameMap = zrUtil.createHashMap();
  21965. var coordDimNameMap = zrUtil.createHashMap();
  21966. // var valueCandidate;
  21967. var result = [];
  21968. var dimCount = opt.dimCount;
  21969. if (dimCount == null) {
  21970. var value0 = retrieveValue(data[0]);
  21971. dimCount = Math.max(
  21972. zrUtil.isArray(value0) && value0.length || 1,
  21973. sysDims.length,
  21974. dimsDef.length
  21975. );
  21976. each(sysDims, function (sysDimItem) {
  21977. var sysDimItemDimsDef = sysDimItem.dimsDef;
  21978. sysDimItemDimsDef && (dimCount = Math.max(dimCount, sysDimItemDimsDef.length));
  21979. });
  21980. }
  21981. // Apply user defined dims (`name` and `type`) and init result.
  21982. for (var i = 0; i < dimCount; i++) {
  21983. var dimDefItem = isString(dimsDef[i]) ? {name: dimsDef[i]} : (dimsDef[i] || {});
  21984. var userDimName = dimDefItem.name;
  21985. var resultItem = result[i] = {otherDims: {}};
  21986. // Name will be applied later for avoiding duplication.
  21987. if (userDimName != null && dataDimNameMap.get(userDimName) == null) {
  21988. // Only if `series.dimensions` is defined in option, tooltipName
  21989. // will be set, and dimension will be diplayed vertically in
  21990. // tooltip by default.
  21991. resultItem.name = resultItem.tooltipName = userDimName;
  21992. dataDimNameMap.set(userDimName, i);
  21993. }
  21994. dimDefItem.type != null && (resultItem.type = dimDefItem.type);
  21995. }
  21996. // Set `coordDim` and `coordDimIndex` by `encodeDef` and normalize `encodeDef`.
  21997. encodeDef.each(function (dataDims, coordDim) {
  21998. dataDims = encodeDef.set(coordDim, normalizeToArray(dataDims).slice());
  21999. each(dataDims, function (resultDimIdx, coordDimIndex) {
  22000. // The input resultDimIdx can be dim name or index.
  22001. isString(resultDimIdx) && (resultDimIdx = dataDimNameMap.get(resultDimIdx));
  22002. if (resultDimIdx != null && resultDimIdx < dimCount) {
  22003. dataDims[coordDimIndex] = resultDimIdx;
  22004. applyDim(result[resultDimIdx], coordDim, coordDimIndex);
  22005. // coordDim === 'value' && valueCandidate == null && (valueCandidate = resultDimIdx);
  22006. }
  22007. });
  22008. });
  22009. // Apply templetes and default order from `sysDims`.
  22010. var availDimIdx = 0;
  22011. each(sysDims, function (sysDimItem, sysDimIndex) {
  22012. var coordDim;
  22013. var sysDimItem;
  22014. var sysDimItemDimsDef;
  22015. var sysDimItemOtherDims;
  22016. if (isString(sysDimItem)) {
  22017. coordDim = sysDimItem;
  22018. sysDimItem = {};
  22019. }
  22020. else {
  22021. coordDim = sysDimItem.name;
  22022. sysDimItem = zrUtil.clone(sysDimItem);
  22023. // `coordDimIndex` should not be set directly.
  22024. sysDimItemDimsDef = sysDimItem.dimsDef;
  22025. sysDimItemOtherDims = sysDimItem.otherDims;
  22026. sysDimItem.name = sysDimItem.coordDim = sysDimItem.coordDimIndex
  22027. = sysDimItem.dimsDef = sysDimItem.otherDims = null;
  22028. }
  22029. var dataDims = normalizeToArray(encodeDef.get(coordDim));
  22030. // dimensions provides default dim sequences.
  22031. if (!dataDims.length) {
  22032. for (var i = 0; i < (sysDimItemDimsDef && sysDimItemDimsDef.length || 1); i++) {
  22033. while (availDimIdx < result.length && result[availDimIdx].coordDim != null) {
  22034. availDimIdx++;
  22035. }
  22036. availDimIdx < result.length && dataDims.push(availDimIdx++);
  22037. }
  22038. }
  22039. // Apply templates.
  22040. each(dataDims, function (resultDimIdx, coordDimIndex) {
  22041. var resultItem = result[resultDimIdx];
  22042. applyDim(defaults(resultItem, sysDimItem), coordDim, coordDimIndex);
  22043. // coordDim === 'value' && valueCandidate == null && (valueCandidate = resultDimIdx);
  22044. if (resultItem.name == null && sysDimItemDimsDef) {
  22045. resultItem.name = resultItem.tooltipName = sysDimItemDimsDef[coordDimIndex];
  22046. }
  22047. sysDimItemOtherDims && defaults(resultItem.otherDims, sysDimItemOtherDims);
  22048. });
  22049. });
  22050. // Make sure the first extra dim is 'value'.
  22051. var extra = opt.extraPrefix || 'value';
  22052. // Set dim `name` and other `coordDim` and other props.
  22053. for (var resultDimIdx = 0; resultDimIdx < dimCount; resultDimIdx++) {
  22054. var resultItem = result[resultDimIdx] = result[resultDimIdx] || {};
  22055. var coordDim = resultItem.coordDim;
  22056. coordDim == null && (
  22057. resultItem.coordDim = genName(extra, coordDimNameMap, opt.extraFromZero),
  22058. resultItem.coordDimIndex = 0,
  22059. resultItem.isExtraCoord = true
  22060. );
  22061. resultItem.name == null && (resultItem.name = genName(
  22062. // Ensure At least one value dim.
  22063. // (dataDimNameMap.get('value') == null
  22064. // && (valueCandidate == null || valueCandidate === resultDimIdx)
  22065. // // Try to set as 'value' only if coordDim is not set as 'extra'.
  22066. // && coordDim == null
  22067. // )
  22068. // ? 'value'
  22069. // :
  22070. resultItem.coordDim,
  22071. dataDimNameMap
  22072. ));
  22073. resultItem.type == null && guessOrdinal(data, resultDimIdx)
  22074. && (resultItem.type = 'ordinal');
  22075. }
  22076. return result;
  22077. function applyDim(resultItem, coordDim, coordDimIndex) {
  22078. if (OTHER_DIMS[coordDim]) {
  22079. resultItem.otherDims[coordDim] = coordDimIndex;
  22080. }
  22081. else {
  22082. resultItem.coordDim = coordDim;
  22083. resultItem.coordDimIndex = coordDimIndex;
  22084. coordDimNameMap.set(coordDim, true);
  22085. }
  22086. }
  22087. function genName(name, map, fromZero) {
  22088. if (fromZero || map.get(name) != null) {
  22089. var i = 0;
  22090. while (map.get(name + i) != null) {
  22091. i++;
  22092. }
  22093. name += i;
  22094. }
  22095. map.set(name, true);
  22096. return name;
  22097. }
  22098. }
  22099. // The rule should not be complex, otherwise user might not
  22100. // be able to known where the data is wrong.
  22101. var guessOrdinal = completeDimensions.guessOrdinal = function (data, dimIndex) {
  22102. for (var i = 0, len = data.length; i < len; i++) {
  22103. var value = retrieveValue(data[i]);
  22104. if (!zrUtil.isArray(value)) {
  22105. return false;
  22106. }
  22107. var value = value[dimIndex];
  22108. // Consider usage convenience, '1', '2' will be treated as "number".
  22109. if (value != null && isFinite(value)) {
  22110. return false;
  22111. }
  22112. else if (isString(value) && value !== '-') {
  22113. return true;
  22114. }
  22115. }
  22116. return false;
  22117. };
  22118. function retrieveValue(o) {
  22119. return zrUtil.isArray(o) ? o : zrUtil.isObject(o) ? o.value: o;
  22120. }
  22121. module.exports = completeDimensions;
  22122. /***/ },
  22123. /* 111 */
  22124. /***/ function(module, exports, __webpack_require__) {
  22125. 'use strict';
  22126. // Symbol factory
  22127. var graphic = __webpack_require__(18);
  22128. var BoundingRect = __webpack_require__(9);
  22129. /**
  22130. * Triangle shape
  22131. * @inner
  22132. */
  22133. var Triangle = graphic.extendShape({
  22134. type: 'triangle',
  22135. shape: {
  22136. cx: 0,
  22137. cy: 0,
  22138. width: 0,
  22139. height: 0
  22140. },
  22141. buildPath: function (path, shape) {
  22142. var cx = shape.cx;
  22143. var cy = shape.cy;
  22144. var width = shape.width / 2;
  22145. var height = shape.height / 2;
  22146. path.moveTo(cx, cy - height);
  22147. path.lineTo(cx + width, cy + height);
  22148. path.lineTo(cx - width, cy + height);
  22149. path.closePath();
  22150. }
  22151. });
  22152. /**
  22153. * Diamond shape
  22154. * @inner
  22155. */
  22156. var Diamond = graphic.extendShape({
  22157. type: 'diamond',
  22158. shape: {
  22159. cx: 0,
  22160. cy: 0,
  22161. width: 0,
  22162. height: 0
  22163. },
  22164. buildPath: function (path, shape) {
  22165. var cx = shape.cx;
  22166. var cy = shape.cy;
  22167. var width = shape.width / 2;
  22168. var height = shape.height / 2;
  22169. path.moveTo(cx, cy - height);
  22170. path.lineTo(cx + width, cy);
  22171. path.lineTo(cx, cy + height);
  22172. path.lineTo(cx - width, cy);
  22173. path.closePath();
  22174. }
  22175. });
  22176. /**
  22177. * Pin shape
  22178. * @inner
  22179. */
  22180. var Pin = graphic.extendShape({
  22181. type: 'pin',
  22182. shape: {
  22183. // x, y on the cusp
  22184. x: 0,
  22185. y: 0,
  22186. width: 0,
  22187. height: 0
  22188. },
  22189. buildPath: function (path, shape) {
  22190. var x = shape.x;
  22191. var y = shape.y;
  22192. var w = shape.width / 5 * 3;
  22193. // Height must be larger than width
  22194. var h = Math.max(w, shape.height);
  22195. var r = w / 2;
  22196. // Dist on y with tangent point and circle center
  22197. var dy = r * r / (h - r);
  22198. var cy = y - h + r + dy;
  22199. var angle = Math.asin(dy / r);
  22200. // Dist on x with tangent point and circle center
  22201. var dx = Math.cos(angle) * r;
  22202. var tanX = Math.sin(angle);
  22203. var tanY = Math.cos(angle);
  22204. path.arc(
  22205. x, cy, r,
  22206. Math.PI - angle,
  22207. Math.PI * 2 + angle
  22208. );
  22209. var cpLen = r * 0.6;
  22210. var cpLen2 = r * 0.7;
  22211. path.bezierCurveTo(
  22212. x + dx - tanX * cpLen, cy + dy + tanY * cpLen,
  22213. x, y - cpLen2,
  22214. x, y
  22215. );
  22216. path.bezierCurveTo(
  22217. x, y - cpLen2,
  22218. x - dx + tanX * cpLen, cy + dy + tanY * cpLen,
  22219. x - dx, cy + dy
  22220. );
  22221. path.closePath();
  22222. }
  22223. });
  22224. /**
  22225. * Arrow shape
  22226. * @inner
  22227. */
  22228. var Arrow = graphic.extendShape({
  22229. type: 'arrow',
  22230. shape: {
  22231. x: 0,
  22232. y: 0,
  22233. width: 0,
  22234. height: 0
  22235. },
  22236. buildPath: function (ctx, shape) {
  22237. var height = shape.height;
  22238. var width = shape.width;
  22239. var x = shape.x;
  22240. var y = shape.y;
  22241. var dx = width / 3 * 2;
  22242. ctx.moveTo(x, y);
  22243. ctx.lineTo(x + dx, y + height);
  22244. ctx.lineTo(x, y + height / 4 * 3);
  22245. ctx.lineTo(x - dx, y + height);
  22246. ctx.lineTo(x, y);
  22247. ctx.closePath();
  22248. }
  22249. });
  22250. /**
  22251. * Map of path contructors
  22252. * @type {Object.<string, module:zrender/graphic/Path>}
  22253. */
  22254. var symbolCtors = {
  22255. line: graphic.Line,
  22256. rect: graphic.Rect,
  22257. roundRect: graphic.Rect,
  22258. square: graphic.Rect,
  22259. circle: graphic.Circle,
  22260. diamond: Diamond,
  22261. pin: Pin,
  22262. arrow: Arrow,
  22263. triangle: Triangle
  22264. };
  22265. var symbolShapeMakers = {
  22266. line: function (x, y, w, h, shape) {
  22267. // FIXME
  22268. shape.x1 = x;
  22269. shape.y1 = y + h / 2;
  22270. shape.x2 = x + w;
  22271. shape.y2 = y + h / 2;
  22272. },
  22273. rect: function (x, y, w, h, shape) {
  22274. shape.x = x;
  22275. shape.y = y;
  22276. shape.width = w;
  22277. shape.height = h;
  22278. },
  22279. roundRect: function (x, y, w, h, shape) {
  22280. shape.x = x;
  22281. shape.y = y;
  22282. shape.width = w;
  22283. shape.height = h;
  22284. shape.r = Math.min(w, h) / 4;
  22285. },
  22286. square: function (x, y, w, h, shape) {
  22287. var size = Math.min(w, h);
  22288. shape.x = x;
  22289. shape.y = y;
  22290. shape.width = size;
  22291. shape.height = size;
  22292. },
  22293. circle: function (x, y, w, h, shape) {
  22294. // Put circle in the center of square
  22295. shape.cx = x + w / 2;
  22296. shape.cy = y + h / 2;
  22297. shape.r = Math.min(w, h) / 2;
  22298. },
  22299. diamond: function (x, y, w, h, shape) {
  22300. shape.cx = x + w / 2;
  22301. shape.cy = y + h / 2;
  22302. shape.width = w;
  22303. shape.height = h;
  22304. },
  22305. pin: function (x, y, w, h, shape) {
  22306. shape.x = x + w / 2;
  22307. shape.y = y + h / 2;
  22308. shape.width = w;
  22309. shape.height = h;
  22310. },
  22311. arrow: function (x, y, w, h, shape) {
  22312. shape.x = x + w / 2;
  22313. shape.y = y + h / 2;
  22314. shape.width = w;
  22315. shape.height = h;
  22316. },
  22317. triangle: function (x, y, w, h, shape) {
  22318. shape.cx = x + w / 2;
  22319. shape.cy = y + h / 2;
  22320. shape.width = w;
  22321. shape.height = h;
  22322. }
  22323. };
  22324. var symbolBuildProxies = {};
  22325. for (var name in symbolCtors) {
  22326. if (symbolCtors.hasOwnProperty(name)) {
  22327. symbolBuildProxies[name] = new symbolCtors[name]();
  22328. }
  22329. }
  22330. var Symbol = graphic.extendShape({
  22331. type: 'symbol',
  22332. shape: {
  22333. symbolType: '',
  22334. x: 0,
  22335. y: 0,
  22336. width: 0,
  22337. height: 0
  22338. },
  22339. beforeBrush: function () {
  22340. var style = this.style;
  22341. var shape = this.shape;
  22342. // FIXME
  22343. if (shape.symbolType === 'pin' && style.textPosition === 'inside') {
  22344. style.textPosition = ['50%', '40%'];
  22345. style.textAlign = 'center';
  22346. style.textVerticalAlign = 'middle';
  22347. }
  22348. },
  22349. buildPath: function (ctx, shape, inBundle) {
  22350. var symbolType = shape.symbolType;
  22351. var proxySymbol = symbolBuildProxies[symbolType];
  22352. if (shape.symbolType !== 'none') {
  22353. if (!proxySymbol) {
  22354. // Default rect
  22355. symbolType = 'rect';
  22356. proxySymbol = symbolBuildProxies[symbolType];
  22357. }
  22358. symbolShapeMakers[symbolType](
  22359. shape.x, shape.y, shape.width, shape.height, proxySymbol.shape
  22360. );
  22361. proxySymbol.buildPath(ctx, proxySymbol.shape, inBundle);
  22362. }
  22363. }
  22364. });
  22365. // Provide setColor helper method to avoid determine if set the fill or stroke outside
  22366. var symbolPathSetColor = function (color) {
  22367. if (this.type !== 'image') {
  22368. var symbolStyle = this.style;
  22369. var symbolShape = this.shape;
  22370. if (symbolShape && symbolShape.symbolType === 'line') {
  22371. symbolStyle.stroke = color;
  22372. }
  22373. else if (this.__isEmptyBrush) {
  22374. symbolStyle.stroke = color;
  22375. symbolStyle.fill = '#fff';
  22376. }
  22377. else {
  22378. // FIXME 判断图形默认是填充还是描边,使用 onlyStroke ?
  22379. symbolStyle.fill && (symbolStyle.fill = color);
  22380. symbolStyle.stroke && (symbolStyle.stroke = color);
  22381. }
  22382. this.dirty(false);
  22383. }
  22384. };
  22385. var symbolUtil = {
  22386. /**
  22387. * Create a symbol element with given symbol configuration: shape, x, y, width, height, color
  22388. * @param {string} symbolType
  22389. * @param {number} x
  22390. * @param {number} y
  22391. * @param {number} w
  22392. * @param {number} h
  22393. * @param {string} color
  22394. */
  22395. createSymbol: function (symbolType, x, y, w, h, color) {
  22396. // TODO Support image object, DynamicImage.
  22397. var isEmpty = symbolType.indexOf('empty') === 0;
  22398. if (isEmpty) {
  22399. symbolType = symbolType.substr(5, 1).toLowerCase() + symbolType.substr(6);
  22400. }
  22401. var symbolPath;
  22402. if (symbolType.indexOf('image://') === 0) {
  22403. symbolPath = new graphic.Image({
  22404. style: {
  22405. image: symbolType.slice(8),
  22406. x: x,
  22407. y: y,
  22408. width: w,
  22409. height: h
  22410. }
  22411. });
  22412. }
  22413. else if (symbolType.indexOf('path://') === 0) {
  22414. symbolPath = graphic.makePath(symbolType.slice(7), {}, new BoundingRect(x, y, w, h));
  22415. }
  22416. else {
  22417. symbolPath = new Symbol({
  22418. shape: {
  22419. symbolType: symbolType,
  22420. x: x,
  22421. y: y,
  22422. width: w,
  22423. height: h
  22424. }
  22425. });
  22426. }
  22427. symbolPath.__isEmptyBrush = isEmpty;
  22428. symbolPath.setColor = symbolPathSetColor;
  22429. symbolPath.setColor(color);
  22430. return symbolPath;
  22431. }
  22432. };
  22433. module.exports = symbolUtil;
  22434. /***/ },
  22435. /* 112 */
  22436. /***/ function(module, exports, __webpack_require__) {
  22437. var zrUtil = __webpack_require__(4);
  22438. var axisHelper = __webpack_require__(101);
  22439. function getName(obj) {
  22440. if (zrUtil.isObject(obj) && obj.value != null) {
  22441. return obj.value;
  22442. }
  22443. else {
  22444. return obj + '';
  22445. }
  22446. }
  22447. module.exports = {
  22448. /**
  22449. * Format labels
  22450. * @return {Array.<string>}
  22451. */
  22452. getFormattedLabels: function () {
  22453. return axisHelper.getFormattedLabels(
  22454. this.axis,
  22455. this.get('axisLabel.formatter')
  22456. );
  22457. },
  22458. /**
  22459. * Get categories
  22460. */
  22461. getCategories: function () {
  22462. return this.get('type') === 'category'
  22463. && zrUtil.map(this.get('data'), getName);
  22464. },
  22465. /**
  22466. * @param {boolean} origin
  22467. * @return {number|string} min value or 'dataMin' or null/undefined (means auto) or NaN
  22468. */
  22469. getMin: function (origin) {
  22470. var option = this.option;
  22471. var min = (!origin && option.rangeStart != null)
  22472. ? option.rangeStart : option.min;
  22473. if (this.axis && min != null && min !== 'dataMin' && !zrUtil.eqNaN(min)) {
  22474. min = this.axis.scale.parse(min);
  22475. }
  22476. return min;
  22477. },
  22478. /**
  22479. * @param {boolean} origin
  22480. * @return {number|string} max value or 'dataMax' or null/undefined (means auto) or NaN
  22481. */
  22482. getMax: function (origin) {
  22483. var option = this.option;
  22484. var max = (!origin && option.rangeEnd != null)
  22485. ? option.rangeEnd : option.max;
  22486. if (this.axis && max != null && max !== 'dataMax' && !zrUtil.eqNaN(max)) {
  22487. max = this.axis.scale.parse(max);
  22488. }
  22489. return max;
  22490. },
  22491. /**
  22492. * @return {boolean}
  22493. */
  22494. getNeedCrossZero: function () {
  22495. var option = this.option;
  22496. return (option.rangeStart != null || option.rangeEnd != null)
  22497. ? false : !option.scale;
  22498. },
  22499. /**
  22500. * Should be implemented by each axis model if necessary.
  22501. * @return {module:echarts/model/Component} coordinate system model
  22502. */
  22503. getCoordSysModel: zrUtil.noop,
  22504. /**
  22505. * @param {number} rangeStart Can only be finite number or null/undefined or NaN.
  22506. * @param {number} rangeEnd Can only be finite number or null/undefined or NaN.
  22507. */
  22508. setRange: function (rangeStart, rangeEnd) {
  22509. this.option.rangeStart = rangeStart;
  22510. this.option.rangeEnd = rangeEnd;
  22511. },
  22512. /**
  22513. * Reset range
  22514. */
  22515. resetRange: function () {
  22516. // rangeStart and rangeEnd is readonly.
  22517. this.option.rangeStart = this.option.rangeEnd = null;
  22518. }
  22519. };
  22520. /***/ },
  22521. /* 113 */
  22522. /***/ function(module, exports, __webpack_require__) {
  22523. var zrUtil = __webpack_require__(4);
  22524. var echarts = __webpack_require__(1);
  22525. var PRIORITY = echarts.PRIORITY;
  22526. __webpack_require__(114);
  22527. __webpack_require__(115);
  22528. echarts.registerVisual(zrUtil.curry(
  22529. __webpack_require__(121), 'line', 'circle', 'line'
  22530. ));
  22531. echarts.registerLayout(zrUtil.curry(
  22532. __webpack_require__(122), 'line'
  22533. ));
  22534. // Down sample after filter
  22535. echarts.registerProcessor(PRIORITY.PROCESSOR.STATISTIC, zrUtil.curry(
  22536. __webpack_require__(123), 'line'
  22537. ));
  22538. // In case developer forget to include grid component
  22539. __webpack_require__(124);
  22540. /***/ },
  22541. /* 114 */
  22542. /***/ function(module, exports, __webpack_require__) {
  22543. 'use strict';
  22544. var createListFromArray = __webpack_require__(109);
  22545. var SeriesModel = __webpack_require__(78);
  22546. module.exports = SeriesModel.extend({
  22547. type: 'series.line',
  22548. dependencies: ['grid', 'polar'],
  22549. getInitialData: function (option, ecModel) {
  22550. if (true) {
  22551. var coordSys = option.coordinateSystem;
  22552. if (coordSys !== 'polar' && coordSys !== 'cartesian2d') {
  22553. throw new Error('Line not support coordinateSystem besides cartesian and polar');
  22554. }
  22555. }
  22556. return createListFromArray(option.data, this, ecModel);
  22557. },
  22558. defaultOption: {
  22559. zlevel: 0, // 一级层叠
  22560. z: 2, // 二级层叠
  22561. coordinateSystem: 'cartesian2d',
  22562. legendHoverLink: true,
  22563. hoverAnimation: true,
  22564. // stack: null
  22565. // xAxisIndex: 0,
  22566. // yAxisIndex: 0,
  22567. // polarIndex: 0,
  22568. // If clip the overflow value
  22569. clipOverflow: true,
  22570. label: {
  22571. normal: {
  22572. position: 'top'
  22573. }
  22574. },
  22575. // itemStyle: {
  22576. // normal: {},
  22577. // emphasis: {}
  22578. // },
  22579. lineStyle: {
  22580. normal: {
  22581. width: 2,
  22582. type: 'solid'
  22583. }
  22584. },
  22585. // areaStyle: {},
  22586. // false, 'start', 'end', 'middle'
  22587. step: false,
  22588. // Disabled if step is true
  22589. smooth: false,
  22590. smoothMonotone: null,
  22591. // 拐点图形类型
  22592. symbol: 'emptyCircle',
  22593. // 拐点图形大小
  22594. symbolSize: 4,
  22595. // 拐点图形旋转控制
  22596. symbolRotate: null,
  22597. // 是否显示 symbol, 只有在 tooltip hover 的时候显示
  22598. showSymbol: true,
  22599. // 标志图形默认只有主轴显示(随主轴标签间隔隐藏策略)
  22600. showAllSymbol: false,
  22601. // 是否连接断点
  22602. connectNulls: false,
  22603. // 数据过滤,'average', 'max', 'min', 'sum'
  22604. sampling: 'none',
  22605. animationEasing: 'linear',
  22606. // Disable progressive
  22607. progressive: 0,
  22608. hoverLayerThreshold: Infinity
  22609. }
  22610. });
  22611. /***/ },
  22612. /* 115 */
  22613. /***/ function(module, exports, __webpack_require__) {
  22614. 'use strict';
  22615. // FIXME step not support polar
  22616. var zrUtil = __webpack_require__(4);
  22617. var SymbolDraw = __webpack_require__(116);
  22618. var Symbol = __webpack_require__(117);
  22619. var lineAnimationDiff = __webpack_require__(119);
  22620. var graphic = __webpack_require__(18);
  22621. var modelUtil = __webpack_require__(5);
  22622. var polyHelper = __webpack_require__(120);
  22623. var ChartView = __webpack_require__(80);
  22624. function isPointsSame(points1, points2) {
  22625. if (points1.length !== points2.length) {
  22626. return;
  22627. }
  22628. for (var i = 0; i < points1.length; i++) {
  22629. var p1 = points1[i];
  22630. var p2 = points2[i];
  22631. if (p1[0] !== p2[0] || p1[1] !== p2[1]) {
  22632. return;
  22633. }
  22634. }
  22635. return true;
  22636. }
  22637. function getSmooth(smooth) {
  22638. return typeof (smooth) === 'number' ? smooth : (smooth ? 0.3 : 0);
  22639. }
  22640. function getAxisExtentWithGap(axis) {
  22641. var extent = axis.getGlobalExtent();
  22642. if (axis.onBand) {
  22643. // Remove extra 1px to avoid line miter in clipped edge
  22644. var halfBandWidth = axis.getBandWidth() / 2 - 1;
  22645. var dir = extent[1] > extent[0] ? 1 : -1;
  22646. extent[0] += dir * halfBandWidth;
  22647. extent[1] -= dir * halfBandWidth;
  22648. }
  22649. return extent;
  22650. }
  22651. function sign(val) {
  22652. return val >= 0 ? 1 : -1;
  22653. }
  22654. /**
  22655. * @param {module:echarts/coord/cartesian/Cartesian2D|module:echarts/coord/polar/Polar} coordSys
  22656. * @param {module:echarts/data/List} data
  22657. * @param {Array.<Array.<number>>} points
  22658. * @private
  22659. */
  22660. function getStackedOnPoints(coordSys, data) {
  22661. var baseAxis = coordSys.getBaseAxis();
  22662. var valueAxis = coordSys.getOtherAxis(baseAxis);
  22663. var valueStart = baseAxis.onZero
  22664. ? 0 : valueAxis.scale.getExtent()[0];
  22665. var valueDim = valueAxis.dim;
  22666. var baseDataOffset = valueDim === 'x' || valueDim === 'radius' ? 1 : 0;
  22667. return data.mapArray([valueDim], function (val, idx) {
  22668. var stackedOnSameSign;
  22669. var stackedOn = data.stackedOn;
  22670. // Find first stacked value with same sign
  22671. while (stackedOn &&
  22672. sign(stackedOn.get(valueDim, idx)) === sign(val)
  22673. ) {
  22674. stackedOnSameSign = stackedOn;
  22675. break;
  22676. }
  22677. var stackedData = [];
  22678. stackedData[baseDataOffset] = data.get(baseAxis.dim, idx);
  22679. stackedData[1 - baseDataOffset] = stackedOnSameSign
  22680. ? stackedOnSameSign.get(valueDim, idx, true) : valueStart;
  22681. return coordSys.dataToPoint(stackedData);
  22682. }, true);
  22683. }
  22684. function createGridClipShape(cartesian, hasAnimation, seriesModel) {
  22685. var xExtent = getAxisExtentWithGap(cartesian.getAxis('x'));
  22686. var yExtent = getAxisExtentWithGap(cartesian.getAxis('y'));
  22687. var isHorizontal = cartesian.getBaseAxis().isHorizontal();
  22688. var x = Math.min(xExtent[0], xExtent[1]);
  22689. var y = Math.min(yExtent[0], yExtent[1]);
  22690. var width = Math.max(xExtent[0], xExtent[1]) - x;
  22691. var height = Math.max(yExtent[0], yExtent[1]) - y;
  22692. var lineWidth = seriesModel.get('lineStyle.normal.width') || 2;
  22693. // Expand clip shape to avoid clipping when line value exceeds axis
  22694. var expandSize = seriesModel.get('clipOverflow') ? lineWidth / 2 : Math.max(width, height);
  22695. if (isHorizontal) {
  22696. y -= expandSize;
  22697. height += expandSize * 2;
  22698. }
  22699. else {
  22700. x -= expandSize;
  22701. width += expandSize * 2;
  22702. }
  22703. var clipPath = new graphic.Rect({
  22704. shape: {
  22705. x: x,
  22706. y: y,
  22707. width: width,
  22708. height: height
  22709. }
  22710. });
  22711. if (hasAnimation) {
  22712. clipPath.shape[isHorizontal ? 'width' : 'height'] = 0;
  22713. graphic.initProps(clipPath, {
  22714. shape: {
  22715. width: width,
  22716. height: height
  22717. }
  22718. }, seriesModel);
  22719. }
  22720. return clipPath;
  22721. }
  22722. function createPolarClipShape(polar, hasAnimation, seriesModel) {
  22723. var angleAxis = polar.getAngleAxis();
  22724. var radiusAxis = polar.getRadiusAxis();
  22725. var radiusExtent = radiusAxis.getExtent();
  22726. var angleExtent = angleAxis.getExtent();
  22727. var RADIAN = Math.PI / 180;
  22728. var clipPath = new graphic.Sector({
  22729. shape: {
  22730. cx: polar.cx,
  22731. cy: polar.cy,
  22732. r0: radiusExtent[0],
  22733. r: radiusExtent[1],
  22734. startAngle: -angleExtent[0] * RADIAN,
  22735. endAngle: -angleExtent[1] * RADIAN,
  22736. clockwise: angleAxis.inverse
  22737. }
  22738. });
  22739. if (hasAnimation) {
  22740. clipPath.shape.endAngle = -angleExtent[0] * RADIAN;
  22741. graphic.initProps(clipPath, {
  22742. shape: {
  22743. endAngle: -angleExtent[1] * RADIAN
  22744. }
  22745. }, seriesModel);
  22746. }
  22747. return clipPath;
  22748. }
  22749. function createClipShape(coordSys, hasAnimation, seriesModel) {
  22750. return coordSys.type === 'polar'
  22751. ? createPolarClipShape(coordSys, hasAnimation, seriesModel)
  22752. : createGridClipShape(coordSys, hasAnimation, seriesModel);
  22753. }
  22754. function turnPointsIntoStep(points, coordSys, stepTurnAt) {
  22755. var baseAxis = coordSys.getBaseAxis();
  22756. var baseIndex = baseAxis.dim === 'x' || baseAxis.dim === 'radius' ? 0 : 1;
  22757. var stepPoints = [];
  22758. for (var i = 0; i < points.length - 1; i++) {
  22759. var nextPt = points[i + 1];
  22760. var pt = points[i];
  22761. stepPoints.push(pt);
  22762. var stepPt = [];
  22763. switch (stepTurnAt) {
  22764. case 'end':
  22765. stepPt[baseIndex] = nextPt[baseIndex];
  22766. stepPt[1 - baseIndex] = pt[1 - baseIndex];
  22767. // default is start
  22768. stepPoints.push(stepPt);
  22769. break;
  22770. case 'middle':
  22771. // default is start
  22772. var middle = (pt[baseIndex] + nextPt[baseIndex]) / 2;
  22773. var stepPt2 = [];
  22774. stepPt[baseIndex] = stepPt2[baseIndex] = middle;
  22775. stepPt[1 - baseIndex] = pt[1 - baseIndex];
  22776. stepPt2[1 - baseIndex] = nextPt[1 - baseIndex];
  22777. stepPoints.push(stepPt);
  22778. stepPoints.push(stepPt2);
  22779. break;
  22780. default:
  22781. stepPt[baseIndex] = pt[baseIndex];
  22782. stepPt[1 - baseIndex] = nextPt[1 - baseIndex];
  22783. // default is start
  22784. stepPoints.push(stepPt);
  22785. }
  22786. }
  22787. // Last points
  22788. points[i] && stepPoints.push(points[i]);
  22789. return stepPoints;
  22790. }
  22791. function getVisualGradient(data, coordSys) {
  22792. var visualMetaList = data.getVisual('visualMeta');
  22793. if (!visualMetaList || !visualMetaList.length || !data.count()) {
  22794. // When data.count() is 0, gradient range can not be calculated.
  22795. return;
  22796. }
  22797. var visualMeta;
  22798. for (var i = visualMetaList.length - 1; i >= 0; i--) {
  22799. // Can only be x or y
  22800. if (visualMetaList[i].dimension < 2) {
  22801. visualMeta = visualMetaList[i];
  22802. break;
  22803. }
  22804. }
  22805. if (!visualMeta || coordSys.type !== 'cartesian2d') {
  22806. if (true) {
  22807. console.warn('Visual map on line style only support x or y dimension.');
  22808. }
  22809. return;
  22810. }
  22811. // If the area to be rendered is bigger than area defined by LinearGradient,
  22812. // the canvas spec prescribes that the color of the first stop and the last
  22813. // stop should be used. But if two stops are added at offset 0, in effect
  22814. // browsers use the color of the second stop to render area outside
  22815. // LinearGradient. So we can only infinitesimally extend area defined in
  22816. // LinearGradient to render `outerColors`.
  22817. var dimension = visualMeta.dimension;
  22818. var dimName = data.dimensions[dimension];
  22819. var axis = coordSys.getAxis(dimName);
  22820. // dataToCoor mapping may not be linear, but must be monotonic.
  22821. var colorStops = zrUtil.map(visualMeta.stops, function (stop) {
  22822. return {
  22823. coord: axis.toGlobalCoord(axis.dataToCoord(stop.value)),
  22824. color: stop.color
  22825. };
  22826. });
  22827. var stopLen = colorStops.length;
  22828. var outerColors = visualMeta.outerColors.slice();
  22829. if (stopLen && colorStops[0].coord > colorStops[stopLen - 1].coord) {
  22830. colorStops.reverse();
  22831. outerColors.reverse();
  22832. }
  22833. var tinyExtent = 10; // Arbitrary value: 10px
  22834. var minCoord = colorStops[0].coord - tinyExtent;
  22835. var maxCoord = colorStops[stopLen - 1].coord + tinyExtent;
  22836. var coordSpan = maxCoord - minCoord;
  22837. if (coordSpan < 1e-3) {
  22838. return 'transparent';
  22839. }
  22840. zrUtil.each(colorStops, function (stop) {
  22841. stop.offset = (stop.coord - minCoord) / coordSpan;
  22842. });
  22843. colorStops.push({
  22844. offset: stopLen ? colorStops[stopLen - 1].offset : 0.5,
  22845. color: outerColors[1] || 'transparent'
  22846. });
  22847. colorStops.unshift({ // notice colorStops.length have been changed.
  22848. offset: stopLen ? colorStops[0].offset : 0.5,
  22849. color: outerColors[0] || 'transparent'
  22850. });
  22851. // zrUtil.each(colorStops, function (colorStop) {
  22852. // // Make sure each offset has rounded px to avoid not sharp edge
  22853. // colorStop.offset = (Math.round(colorStop.offset * (end - start) + start) - start) / (end - start);
  22854. // });
  22855. var gradient = new graphic.LinearGradient(0, 0, 0, 0, colorStops, true);
  22856. gradient[dimName] = minCoord;
  22857. gradient[dimName + '2'] = maxCoord;
  22858. return gradient;
  22859. }
  22860. module.exports = ChartView.extend({
  22861. type: 'line',
  22862. init: function () {
  22863. var lineGroup = new graphic.Group();
  22864. var symbolDraw = new SymbolDraw();
  22865. this.group.add(symbolDraw.group);
  22866. this._symbolDraw = symbolDraw;
  22867. this._lineGroup = lineGroup;
  22868. },
  22869. render: function (seriesModel, ecModel, api) {
  22870. var coordSys = seriesModel.coordinateSystem;
  22871. var group = this.group;
  22872. var data = seriesModel.getData();
  22873. var lineStyleModel = seriesModel.getModel('lineStyle.normal');
  22874. var areaStyleModel = seriesModel.getModel('areaStyle.normal');
  22875. var points = data.mapArray(data.getItemLayout, true);
  22876. var isCoordSysPolar = coordSys.type === 'polar';
  22877. var prevCoordSys = this._coordSys;
  22878. var symbolDraw = this._symbolDraw;
  22879. var polyline = this._polyline;
  22880. var polygon = this._polygon;
  22881. var lineGroup = this._lineGroup;
  22882. var hasAnimation = seriesModel.get('animation');
  22883. var isAreaChart = !areaStyleModel.isEmpty();
  22884. var stackedOnPoints = getStackedOnPoints(coordSys, data);
  22885. var showSymbol = seriesModel.get('showSymbol');
  22886. var isSymbolIgnore = showSymbol && !isCoordSysPolar && !seriesModel.get('showAllSymbol')
  22887. && this._getSymbolIgnoreFunc(data, coordSys);
  22888. // Remove temporary symbols
  22889. var oldData = this._data;
  22890. oldData && oldData.eachItemGraphicEl(function (el, idx) {
  22891. if (el.__temp) {
  22892. group.remove(el);
  22893. oldData.setItemGraphicEl(idx, null);
  22894. }
  22895. });
  22896. // Remove previous created symbols if showSymbol changed to false
  22897. if (!showSymbol) {
  22898. symbolDraw.remove();
  22899. }
  22900. group.add(lineGroup);
  22901. // FIXME step not support polar
  22902. var step = !isCoordSysPolar && seriesModel.get('step');
  22903. // Initialization animation or coordinate system changed
  22904. if (
  22905. !(polyline && prevCoordSys.type === coordSys.type && step === this._step)
  22906. ) {
  22907. showSymbol && symbolDraw.updateData(data, isSymbolIgnore);
  22908. if (step) {
  22909. // TODO If stacked series is not step
  22910. points = turnPointsIntoStep(points, coordSys, step);
  22911. stackedOnPoints = turnPointsIntoStep(stackedOnPoints, coordSys, step);
  22912. }
  22913. polyline = this._newPolyline(points, coordSys, hasAnimation);
  22914. if (isAreaChart) {
  22915. polygon = this._newPolygon(
  22916. points, stackedOnPoints,
  22917. coordSys, hasAnimation
  22918. );
  22919. }
  22920. lineGroup.setClipPath(createClipShape(coordSys, true, seriesModel));
  22921. }
  22922. else {
  22923. if (isAreaChart && !polygon) {
  22924. // If areaStyle is added
  22925. polygon = this._newPolygon(
  22926. points, stackedOnPoints,
  22927. coordSys, hasAnimation
  22928. );
  22929. }
  22930. else if (polygon && !isAreaChart) {
  22931. // If areaStyle is removed
  22932. lineGroup.remove(polygon);
  22933. polygon = this._polygon = null;
  22934. }
  22935. // Update clipPath
  22936. lineGroup.setClipPath(createClipShape(coordSys, false, seriesModel));
  22937. // Always update, or it is wrong in the case turning on legend
  22938. // because points are not changed
  22939. showSymbol && symbolDraw.updateData(data, isSymbolIgnore);
  22940. // Stop symbol animation and sync with line points
  22941. // FIXME performance?
  22942. data.eachItemGraphicEl(function (el) {
  22943. el.stopAnimation(true);
  22944. });
  22945. // In the case data zoom triggerred refreshing frequently
  22946. // Data may not change if line has a category axis. So it should animate nothing
  22947. if (!isPointsSame(this._stackedOnPoints, stackedOnPoints)
  22948. || !isPointsSame(this._points, points)
  22949. ) {
  22950. if (hasAnimation) {
  22951. this._updateAnimation(
  22952. data, stackedOnPoints, coordSys, api, step
  22953. );
  22954. }
  22955. else {
  22956. // Not do it in update with animation
  22957. if (step) {
  22958. // TODO If stacked series is not step
  22959. points = turnPointsIntoStep(points, coordSys, step);
  22960. stackedOnPoints = turnPointsIntoStep(stackedOnPoints, coordSys, step);
  22961. }
  22962. polyline.setShape({
  22963. points: points
  22964. });
  22965. polygon && polygon.setShape({
  22966. points: points,
  22967. stackedOnPoints: stackedOnPoints
  22968. });
  22969. }
  22970. }
  22971. }
  22972. var visualColor = getVisualGradient(data, coordSys) || data.getVisual('color');
  22973. polyline.useStyle(zrUtil.defaults(
  22974. // Use color in lineStyle first
  22975. lineStyleModel.getLineStyle(),
  22976. {
  22977. fill: 'none',
  22978. stroke: visualColor,
  22979. lineJoin: 'bevel'
  22980. }
  22981. ));
  22982. var smooth = seriesModel.get('smooth');
  22983. smooth = getSmooth(seriesModel.get('smooth'));
  22984. polyline.setShape({
  22985. smooth: smooth,
  22986. smoothMonotone: seriesModel.get('smoothMonotone'),
  22987. connectNulls: seriesModel.get('connectNulls')
  22988. });
  22989. if (polygon) {
  22990. var stackedOn = data.stackedOn;
  22991. var stackedOnSmooth = 0;
  22992. polygon.useStyle(zrUtil.defaults(
  22993. areaStyleModel.getAreaStyle(),
  22994. {
  22995. fill: visualColor,
  22996. opacity: 0.7,
  22997. lineJoin: 'bevel'
  22998. }
  22999. ));
  23000. if (stackedOn) {
  23001. var stackedOnSeries = stackedOn.hostModel;
  23002. stackedOnSmooth = getSmooth(stackedOnSeries.get('smooth'));
  23003. }
  23004. polygon.setShape({
  23005. smooth: smooth,
  23006. stackedOnSmooth: stackedOnSmooth,
  23007. smoothMonotone: seriesModel.get('smoothMonotone'),
  23008. connectNulls: seriesModel.get('connectNulls')
  23009. });
  23010. }
  23011. this._data = data;
  23012. // Save the coordinate system for transition animation when data changed
  23013. this._coordSys = coordSys;
  23014. this._stackedOnPoints = stackedOnPoints;
  23015. this._points = points;
  23016. this._step = step;
  23017. },
  23018. dispose: function () {},
  23019. highlight: function (seriesModel, ecModel, api, payload) {
  23020. var data = seriesModel.getData();
  23021. var dataIndex = modelUtil.queryDataIndex(data, payload);
  23022. if (!(dataIndex instanceof Array) && dataIndex != null && dataIndex >= 0) {
  23023. var symbol = data.getItemGraphicEl(dataIndex);
  23024. if (!symbol) {
  23025. // Create a temporary symbol if it is not exists
  23026. var pt = data.getItemLayout(dataIndex);
  23027. if (!pt) {
  23028. // Null data
  23029. return;
  23030. }
  23031. symbol = new Symbol(data, dataIndex);
  23032. symbol.position = pt;
  23033. symbol.setZ(
  23034. seriesModel.get('zlevel'),
  23035. seriesModel.get('z')
  23036. );
  23037. symbol.ignore = isNaN(pt[0]) || isNaN(pt[1]);
  23038. symbol.__temp = true;
  23039. data.setItemGraphicEl(dataIndex, symbol);
  23040. // Stop scale animation
  23041. symbol.stopSymbolAnimation(true);
  23042. this.group.add(symbol);
  23043. }
  23044. symbol.highlight();
  23045. }
  23046. else {
  23047. // Highlight whole series
  23048. ChartView.prototype.highlight.call(
  23049. this, seriesModel, ecModel, api, payload
  23050. );
  23051. }
  23052. },
  23053. downplay: function (seriesModel, ecModel, api, payload) {
  23054. var data = seriesModel.getData();
  23055. var dataIndex = modelUtil.queryDataIndex(data, payload);
  23056. if (dataIndex != null && dataIndex >= 0) {
  23057. var symbol = data.getItemGraphicEl(dataIndex);
  23058. if (symbol) {
  23059. if (symbol.__temp) {
  23060. data.setItemGraphicEl(dataIndex, null);
  23061. this.group.remove(symbol);
  23062. }
  23063. else {
  23064. symbol.downplay();
  23065. }
  23066. }
  23067. }
  23068. else {
  23069. // FIXME
  23070. // can not downplay completely.
  23071. // Downplay whole series
  23072. ChartView.prototype.downplay.call(
  23073. this, seriesModel, ecModel, api, payload
  23074. );
  23075. }
  23076. },
  23077. /**
  23078. * @param {module:zrender/container/Group} group
  23079. * @param {Array.<Array.<number>>} points
  23080. * @private
  23081. */
  23082. _newPolyline: function (points) {
  23083. var polyline = this._polyline;
  23084. // Remove previous created polyline
  23085. if (polyline) {
  23086. this._lineGroup.remove(polyline);
  23087. }
  23088. polyline = new polyHelper.Polyline({
  23089. shape: {
  23090. points: points
  23091. },
  23092. silent: true,
  23093. z2: 10
  23094. });
  23095. this._lineGroup.add(polyline);
  23096. this._polyline = polyline;
  23097. return polyline;
  23098. },
  23099. /**
  23100. * @param {module:zrender/container/Group} group
  23101. * @param {Array.<Array.<number>>} stackedOnPoints
  23102. * @param {Array.<Array.<number>>} points
  23103. * @private
  23104. */
  23105. _newPolygon: function (points, stackedOnPoints) {
  23106. var polygon = this._polygon;
  23107. // Remove previous created polygon
  23108. if (polygon) {
  23109. this._lineGroup.remove(polygon);
  23110. }
  23111. polygon = new polyHelper.Polygon({
  23112. shape: {
  23113. points: points,
  23114. stackedOnPoints: stackedOnPoints
  23115. },
  23116. silent: true
  23117. });
  23118. this._lineGroup.add(polygon);
  23119. this._polygon = polygon;
  23120. return polygon;
  23121. },
  23122. /**
  23123. * @private
  23124. */
  23125. _getSymbolIgnoreFunc: function (data, coordSys) {
  23126. var categoryAxis = coordSys.getAxesByScale('ordinal')[0];
  23127. // `getLabelInterval` is provided by echarts/component/axis
  23128. if (categoryAxis && categoryAxis.isLabelIgnored) {
  23129. return zrUtil.bind(categoryAxis.isLabelIgnored, categoryAxis);
  23130. }
  23131. },
  23132. /**
  23133. * @private
  23134. */
  23135. // FIXME Two value axis
  23136. _updateAnimation: function (data, stackedOnPoints, coordSys, api, step) {
  23137. var polyline = this._polyline;
  23138. var polygon = this._polygon;
  23139. var seriesModel = data.hostModel;
  23140. var diff = lineAnimationDiff(
  23141. this._data, data,
  23142. this._stackedOnPoints, stackedOnPoints,
  23143. this._coordSys, coordSys
  23144. );
  23145. var current = diff.current;
  23146. var stackedOnCurrent = diff.stackedOnCurrent;
  23147. var next = diff.next;
  23148. var stackedOnNext = diff.stackedOnNext;
  23149. if (step) {
  23150. // TODO If stacked series is not step
  23151. current = turnPointsIntoStep(diff.current, coordSys, step);
  23152. stackedOnCurrent = turnPointsIntoStep(diff.stackedOnCurrent, coordSys, step);
  23153. next = turnPointsIntoStep(diff.next, coordSys, step);
  23154. stackedOnNext = turnPointsIntoStep(diff.stackedOnNext, coordSys, step);
  23155. }
  23156. // `diff.current` is subset of `current` (which should be ensured by
  23157. // turnPointsIntoStep), so points in `__points` can be updated when
  23158. // points in `current` are update during animation.
  23159. polyline.shape.__points = diff.current;
  23160. polyline.shape.points = current;
  23161. graphic.updateProps(polyline, {
  23162. shape: {
  23163. points: next
  23164. }
  23165. }, seriesModel);
  23166. if (polygon) {
  23167. polygon.setShape({
  23168. points: current,
  23169. stackedOnPoints: stackedOnCurrent
  23170. });
  23171. graphic.updateProps(polygon, {
  23172. shape: {
  23173. points: next,
  23174. stackedOnPoints: stackedOnNext
  23175. }
  23176. }, seriesModel);
  23177. }
  23178. var updatedDataInfo = [];
  23179. var diffStatus = diff.status;
  23180. for (var i = 0; i < diffStatus.length; i++) {
  23181. var cmd = diffStatus[i].cmd;
  23182. if (cmd === '=') {
  23183. var el = data.getItemGraphicEl(diffStatus[i].idx1);
  23184. if (el) {
  23185. updatedDataInfo.push({
  23186. el: el,
  23187. ptIdx: i // Index of points
  23188. });
  23189. }
  23190. }
  23191. }
  23192. if (polyline.animators && polyline.animators.length) {
  23193. polyline.animators[0].during(function () {
  23194. for (var i = 0; i < updatedDataInfo.length; i++) {
  23195. var el = updatedDataInfo[i].el;
  23196. el.attr('position', polyline.shape.__points[updatedDataInfo[i].ptIdx]);
  23197. }
  23198. });
  23199. }
  23200. },
  23201. remove: function (ecModel) {
  23202. var group = this.group;
  23203. var oldData = this._data;
  23204. this._lineGroup.removeAll();
  23205. this._symbolDraw.remove(true);
  23206. // Remove temporary created elements when highlighting
  23207. oldData && oldData.eachItemGraphicEl(function (el, idx) {
  23208. if (el.__temp) {
  23209. group.remove(el);
  23210. oldData.setItemGraphicEl(idx, null);
  23211. }
  23212. });
  23213. this._polyline =
  23214. this._polygon =
  23215. this._coordSys =
  23216. this._points =
  23217. this._stackedOnPoints =
  23218. this._data = null;
  23219. }
  23220. });
  23221. /***/ },
  23222. /* 116 */
  23223. /***/ function(module, exports, __webpack_require__) {
  23224. /**
  23225. * @module echarts/chart/helper/SymbolDraw
  23226. */
  23227. var graphic = __webpack_require__(18);
  23228. var Symbol = __webpack_require__(117);
  23229. /**
  23230. * @constructor
  23231. * @alias module:echarts/chart/helper/SymbolDraw
  23232. * @param {module:zrender/graphic/Group} [symbolCtor]
  23233. */
  23234. function SymbolDraw(symbolCtor) {
  23235. this.group = new graphic.Group();
  23236. this._symbolCtor = symbolCtor || Symbol;
  23237. }
  23238. var symbolDrawProto = SymbolDraw.prototype;
  23239. function symbolNeedsDraw(data, idx, isIgnore) {
  23240. var point = data.getItemLayout(idx);
  23241. // Is an object
  23242. // if (point && point.hasOwnProperty('point')) {
  23243. // point = point.point;
  23244. // }
  23245. return point && !isNaN(point[0]) && !isNaN(point[1]) && !(isIgnore && isIgnore(idx))
  23246. && data.getItemVisual(idx, 'symbol') !== 'none';
  23247. }
  23248. /**
  23249. * Update symbols draw by new data
  23250. * @param {module:echarts/data/List} data
  23251. * @param {Array.<boolean>} [isIgnore]
  23252. */
  23253. symbolDrawProto.updateData = function (data, isIgnore) {
  23254. var group = this.group;
  23255. var seriesModel = data.hostModel;
  23256. var oldData = this._data;
  23257. var SymbolCtor = this._symbolCtor;
  23258. var seriesScope = {
  23259. itemStyle: seriesModel.getModel('itemStyle.normal').getItemStyle(['color']),
  23260. hoverItemStyle: seriesModel.getModel('itemStyle.emphasis').getItemStyle(),
  23261. symbolRotate: seriesModel.get('symbolRotate'),
  23262. symbolOffset: seriesModel.get('symbolOffset'),
  23263. hoverAnimation: seriesModel.get('hoverAnimation'),
  23264. labelModel: seriesModel.getModel('label.normal'),
  23265. hoverLabelModel: seriesModel.getModel('label.emphasis')
  23266. };
  23267. data.diff(oldData)
  23268. .add(function (newIdx) {
  23269. var point = data.getItemLayout(newIdx);
  23270. if (symbolNeedsDraw(data, newIdx, isIgnore)) {
  23271. var symbolEl = new SymbolCtor(data, newIdx, seriesScope);
  23272. symbolEl.attr('position', point);
  23273. data.setItemGraphicEl(newIdx, symbolEl);
  23274. group.add(symbolEl);
  23275. }
  23276. })
  23277. .update(function (newIdx, oldIdx) {
  23278. var symbolEl = oldData.getItemGraphicEl(oldIdx);
  23279. var point = data.getItemLayout(newIdx);
  23280. if (!symbolNeedsDraw(data, newIdx, isIgnore)) {
  23281. group.remove(symbolEl);
  23282. return;
  23283. }
  23284. if (!symbolEl) {
  23285. symbolEl = new SymbolCtor(data, newIdx);
  23286. symbolEl.attr('position', point);
  23287. }
  23288. else {
  23289. symbolEl.updateData(data, newIdx, seriesScope);
  23290. graphic.updateProps(symbolEl, {
  23291. position: point
  23292. }, seriesModel);
  23293. }
  23294. // Add back
  23295. group.add(symbolEl);
  23296. data.setItemGraphicEl(newIdx, symbolEl);
  23297. })
  23298. .remove(function (oldIdx) {
  23299. var el = oldData.getItemGraphicEl(oldIdx);
  23300. el && el.fadeOut(function () {
  23301. group.remove(el);
  23302. });
  23303. })
  23304. .execute();
  23305. this._data = data;
  23306. };
  23307. symbolDrawProto.updateLayout = function () {
  23308. var data = this._data;
  23309. if (data) {
  23310. // Not use animation
  23311. data.eachItemGraphicEl(function (el, idx) {
  23312. var point = data.getItemLayout(idx);
  23313. el.attr('position', point);
  23314. });
  23315. }
  23316. };
  23317. symbolDrawProto.remove = function (enableAnimation) {
  23318. var group = this.group;
  23319. var data = this._data;
  23320. if (data) {
  23321. if (enableAnimation) {
  23322. data.eachItemGraphicEl(function (el) {
  23323. el.fadeOut(function () {
  23324. group.remove(el);
  23325. });
  23326. });
  23327. }
  23328. else {
  23329. group.removeAll();
  23330. }
  23331. }
  23332. };
  23333. module.exports = SymbolDraw;
  23334. /***/ },
  23335. /* 117 */
  23336. /***/ function(module, exports, __webpack_require__) {
  23337. /**
  23338. * @module echarts/chart/helper/Symbol
  23339. */
  23340. var zrUtil = __webpack_require__(4);
  23341. var symbolUtil = __webpack_require__(111);
  23342. var graphic = __webpack_require__(18);
  23343. var numberUtil = __webpack_require__(7);
  23344. var labelHelper = __webpack_require__(118);
  23345. function getSymbolSize(data, idx) {
  23346. var symbolSize = data.getItemVisual(idx, 'symbolSize');
  23347. return symbolSize instanceof Array
  23348. ? symbolSize.slice()
  23349. : [+symbolSize, +symbolSize];
  23350. }
  23351. function getScale(symbolSize) {
  23352. return [symbolSize[0] / 2, symbolSize[1] / 2];
  23353. }
  23354. /**
  23355. * @constructor
  23356. * @alias {module:echarts/chart/helper/Symbol}
  23357. * @param {module:echarts/data/List} data
  23358. * @param {number} idx
  23359. * @extends {module:zrender/graphic/Group}
  23360. */
  23361. function Symbol(data, idx, seriesScope) {
  23362. graphic.Group.call(this);
  23363. this.updateData(data, idx, seriesScope);
  23364. }
  23365. var symbolProto = Symbol.prototype;
  23366. function driftSymbol(dx, dy) {
  23367. this.parent.drift(dx, dy);
  23368. }
  23369. symbolProto._createSymbol = function (symbolType, data, idx, symbolSize) {
  23370. // Remove paths created before
  23371. this.removeAll();
  23372. var seriesModel = data.hostModel;
  23373. var color = data.getItemVisual(idx, 'color');
  23374. // var symbolPath = symbolUtil.createSymbol(
  23375. // symbolType, -0.5, -0.5, 1, 1, color
  23376. // );
  23377. // If width/height are set too small (e.g., set to 1) on ios10
  23378. // and macOS Sierra, a circle stroke become a rect, no matter what
  23379. // the scale is set. So we set width/height as 2. See #4150.
  23380. var symbolPath = symbolUtil.createSymbol(
  23381. symbolType, -1, -1, 2, 2, color
  23382. );
  23383. symbolPath.attr({
  23384. z2: 100,
  23385. culling: true,
  23386. scale: [0, 0]
  23387. });
  23388. // Rewrite drift method
  23389. symbolPath.drift = driftSymbol;
  23390. graphic.initProps(symbolPath, {
  23391. scale: getScale(symbolSize)
  23392. }, seriesModel, idx);
  23393. this._symbolType = symbolType;
  23394. this.add(symbolPath);
  23395. };
  23396. /**
  23397. * Stop animation
  23398. * @param {boolean} toLastFrame
  23399. */
  23400. symbolProto.stopSymbolAnimation = function (toLastFrame) {
  23401. this.childAt(0).stopAnimation(toLastFrame);
  23402. };
  23403. /**
  23404. * Get symbol path element
  23405. */
  23406. symbolProto.getSymbolPath = function () {
  23407. return this.childAt(0);
  23408. };
  23409. /**
  23410. * Get scale(aka, current symbol size).
  23411. * Including the change caused by animation
  23412. */
  23413. symbolProto.getScale = function () {
  23414. return this.childAt(0).scale;
  23415. };
  23416. /**
  23417. * Highlight symbol
  23418. */
  23419. symbolProto.highlight = function () {
  23420. this.childAt(0).trigger('emphasis');
  23421. };
  23422. /**
  23423. * Downplay symbol
  23424. */
  23425. symbolProto.downplay = function () {
  23426. this.childAt(0).trigger('normal');
  23427. };
  23428. /**
  23429. * @param {number} zlevel
  23430. * @param {number} z
  23431. */
  23432. symbolProto.setZ = function (zlevel, z) {
  23433. var symbolPath = this.childAt(0);
  23434. symbolPath.zlevel = zlevel;
  23435. symbolPath.z = z;
  23436. };
  23437. symbolProto.setDraggable = function (draggable) {
  23438. var symbolPath = this.childAt(0);
  23439. symbolPath.draggable = draggable;
  23440. symbolPath.cursor = draggable ? 'move' : 'pointer';
  23441. };
  23442. /**
  23443. * Update symbol properties
  23444. * @param {module:echarts/data/List} data
  23445. * @param {number} idx
  23446. */
  23447. symbolProto.updateData = function (data, idx, seriesScope) {
  23448. this.silent = false;
  23449. var symbolType = data.getItemVisual(idx, 'symbol') || 'circle';
  23450. var seriesModel = data.hostModel;
  23451. var symbolSize = getSymbolSize(data, idx);
  23452. if (symbolType !== this._symbolType) {
  23453. this._createSymbol(symbolType, data, idx, symbolSize);
  23454. }
  23455. else {
  23456. var symbolPath = this.childAt(0);
  23457. symbolPath.silent = false;
  23458. graphic.updateProps(symbolPath, {
  23459. scale: getScale(symbolSize)
  23460. }, seriesModel, idx);
  23461. }
  23462. this._updateCommon(data, idx, symbolSize, seriesScope);
  23463. this._seriesModel = seriesModel;
  23464. };
  23465. // Update common properties
  23466. var normalStyleAccessPath = ['itemStyle', 'normal'];
  23467. var emphasisStyleAccessPath = ['itemStyle', 'emphasis'];
  23468. var normalLabelAccessPath = ['label', 'normal'];
  23469. var emphasisLabelAccessPath = ['label', 'emphasis'];
  23470. symbolProto._updateCommon = function (data, idx, symbolSize, seriesScope) {
  23471. var symbolPath = this.childAt(0);
  23472. var seriesModel = data.hostModel;
  23473. var color = data.getItemVisual(idx, 'color');
  23474. // Reset style
  23475. if (symbolPath.type !== 'image') {
  23476. symbolPath.useStyle({
  23477. strokeNoScale: true
  23478. });
  23479. }
  23480. seriesScope = seriesScope || null;
  23481. var itemStyle = seriesScope && seriesScope.itemStyle;
  23482. var hoverItemStyle = seriesScope && seriesScope.hoverItemStyle;
  23483. var symbolRotate = seriesScope && seriesScope.symbolRotate;
  23484. var symbolOffset = seriesScope && seriesScope.symbolOffset;
  23485. var labelModel = seriesScope && seriesScope.labelModel;
  23486. var hoverLabelModel = seriesScope && seriesScope.hoverLabelModel;
  23487. var hoverAnimation = seriesScope && seriesScope.hoverAnimation;
  23488. if (!seriesScope || data.hasItemOption) {
  23489. var itemModel = data.getItemModel(idx);
  23490. // Color must be excluded.
  23491. // Because symbol provide setColor individually to set fill and stroke
  23492. itemStyle = itemModel.getModel(normalStyleAccessPath).getItemStyle(['color']);
  23493. hoverItemStyle = itemModel.getModel(emphasisStyleAccessPath).getItemStyle();
  23494. symbolRotate = itemModel.getShallow('symbolRotate');
  23495. symbolOffset = itemModel.getShallow('symbolOffset');
  23496. labelModel = itemModel.getModel(normalLabelAccessPath);
  23497. hoverLabelModel = itemModel.getModel(emphasisLabelAccessPath);
  23498. hoverAnimation = itemModel.getShallow('hoverAnimation');
  23499. }
  23500. else {
  23501. hoverItemStyle = zrUtil.extend({}, hoverItemStyle);
  23502. }
  23503. var elStyle = symbolPath.style;
  23504. symbolPath.attr('rotation', (symbolRotate || 0) * Math.PI / 180 || 0);
  23505. if (symbolOffset) {
  23506. symbolPath.attr('position', [
  23507. numberUtil.parsePercent(symbolOffset[0], symbolSize[0]),
  23508. numberUtil.parsePercent(symbolOffset[1], symbolSize[1])
  23509. ]);
  23510. }
  23511. // PENDING setColor before setStyle!!!
  23512. symbolPath.setColor(color);
  23513. symbolPath.setStyle(itemStyle);
  23514. var opacity = data.getItemVisual(idx, 'opacity');
  23515. if (opacity != null) {
  23516. elStyle.opacity = opacity;
  23517. }
  23518. var valueDim = labelHelper.findLabelValueDim(data);
  23519. labelHelper.setTextToStyle(
  23520. data, idx, valueDim, elStyle, seriesModel, labelModel, color
  23521. );
  23522. labelHelper.setTextToStyle(
  23523. data, idx, valueDim, hoverItemStyle, seriesModel, hoverLabelModel, color
  23524. );
  23525. symbolPath.off('mouseover')
  23526. .off('mouseout')
  23527. .off('emphasis')
  23528. .off('normal');
  23529. symbolPath.hoverStyle = hoverItemStyle;
  23530. graphic.setHoverStyle(symbolPath);
  23531. var scale = getScale(symbolSize);
  23532. if (hoverAnimation && seriesModel.isAnimationEnabled()) {
  23533. var onEmphasis = function() {
  23534. var ratio = scale[1] / scale[0];
  23535. this.animateTo({
  23536. scale: [
  23537. Math.max(scale[0] * 1.1, scale[0] + 3),
  23538. Math.max(scale[1] * 1.1, scale[1] + 3 * ratio)
  23539. ]
  23540. }, 400, 'elasticOut');
  23541. };
  23542. var onNormal = function() {
  23543. this.animateTo({
  23544. scale: scale
  23545. }, 400, 'elasticOut');
  23546. };
  23547. symbolPath.on('mouseover', onEmphasis)
  23548. .on('mouseout', onNormal)
  23549. .on('emphasis', onEmphasis)
  23550. .on('normal', onNormal);
  23551. }
  23552. };
  23553. symbolProto.fadeOut = function (cb) {
  23554. var symbolPath = this.childAt(0);
  23555. // Avoid mistaken hover when fading out
  23556. this.silent = symbolPath.silent = true;
  23557. // Not show text when animating
  23558. symbolPath.style.text = '';
  23559. graphic.updateProps(symbolPath, {
  23560. scale: [0, 0]
  23561. }, this._seriesModel, this.dataIndex, cb);
  23562. };
  23563. zrUtil.inherits(Symbol, graphic.Group);
  23564. module.exports = Symbol;
  23565. /***/ },
  23566. /* 118 */
  23567. /***/ function(module, exports, __webpack_require__) {
  23568. /**
  23569. * @module echarts/chart/helper/Symbol
  23570. */
  23571. var graphic = __webpack_require__(18);
  23572. var zrUtil = __webpack_require__(4);
  23573. var modelUtil = __webpack_require__(5);
  23574. var helper = {};
  23575. helper.findLabelValueDim = function (data) {
  23576. var valueDim;
  23577. var labelDims = modelUtil.otherDimToDataDim(data, 'label');
  23578. if (labelDims.length) {
  23579. valueDim = labelDims[0];
  23580. }
  23581. else {
  23582. // Get last value dim
  23583. var dimensions = data.dimensions.slice();
  23584. var dataType;
  23585. while (dimensions.length && (
  23586. valueDim = dimensions.pop(),
  23587. dataType = data.getDimensionInfo(valueDim).type,
  23588. dataType === 'ordinal' || dataType === 'time'
  23589. )) {} // jshint ignore:line
  23590. }
  23591. return valueDim;
  23592. };
  23593. helper.setTextToStyle = function (
  23594. data, dataIndex, valueDim, elStyle, seriesModel, labelModel, color
  23595. ) {
  23596. if (valueDim != null && labelModel.getShallow('show')) {
  23597. graphic.setText(elStyle, labelModel, color);
  23598. elStyle.text = zrUtil.retrieve(
  23599. seriesModel.getFormattedLabel(dataIndex, 'normal'),
  23600. data.get(valueDim, dataIndex)
  23601. );
  23602. }
  23603. else {
  23604. elStyle.text = '';
  23605. }
  23606. };
  23607. module.exports = helper;
  23608. /***/ },
  23609. /* 119 */
  23610. /***/ function(module, exports) {
  23611. // var arrayDiff = require('zrender/lib/core/arrayDiff');
  23612. // 'zrender/core/arrayDiff' has been used before, but it did
  23613. // not do well in performance when roam with fixed dataZoom window.
  23614. function sign(val) {
  23615. return val >= 0 ? 1 : -1;
  23616. }
  23617. function getStackedOnPoint(coordSys, data, idx) {
  23618. var baseAxis = coordSys.getBaseAxis();
  23619. var valueAxis = coordSys.getOtherAxis(baseAxis);
  23620. var valueStart = baseAxis.onZero
  23621. ? 0 : valueAxis.scale.getExtent()[0];
  23622. var valueDim = valueAxis.dim;
  23623. var baseDataOffset = valueDim === 'x' || valueDim === 'radius' ? 1 : 0;
  23624. var stackedOnSameSign;
  23625. var stackedOn = data.stackedOn;
  23626. var val = data.get(valueDim, idx);
  23627. // Find first stacked value with same sign
  23628. while (stackedOn &&
  23629. sign(stackedOn.get(valueDim, idx)) === sign(val)
  23630. ) {
  23631. stackedOnSameSign = stackedOn;
  23632. break;
  23633. }
  23634. var stackedData = [];
  23635. stackedData[baseDataOffset] = data.get(baseAxis.dim, idx);
  23636. stackedData[1 - baseDataOffset] = stackedOnSameSign
  23637. ? stackedOnSameSign.get(valueDim, idx, true) : valueStart;
  23638. return coordSys.dataToPoint(stackedData);
  23639. }
  23640. // function convertToIntId(newIdList, oldIdList) {
  23641. // // Generate int id instead of string id.
  23642. // // Compare string maybe slow in score function of arrDiff
  23643. // // Assume id in idList are all unique
  23644. // var idIndicesMap = {};
  23645. // var idx = 0;
  23646. // for (var i = 0; i < newIdList.length; i++) {
  23647. // idIndicesMap[newIdList[i]] = idx;
  23648. // newIdList[i] = idx++;
  23649. // }
  23650. // for (var i = 0; i < oldIdList.length; i++) {
  23651. // var oldId = oldIdList[i];
  23652. // // Same with newIdList
  23653. // if (idIndicesMap[oldId]) {
  23654. // oldIdList[i] = idIndicesMap[oldId];
  23655. // }
  23656. // else {
  23657. // oldIdList[i] = idx++;
  23658. // }
  23659. // }
  23660. // }
  23661. function diffData(oldData, newData) {
  23662. var diffResult = [];
  23663. newData.diff(oldData)
  23664. .add(function (idx) {
  23665. diffResult.push({cmd: '+', idx: idx});
  23666. })
  23667. .update(function (newIdx, oldIdx) {
  23668. diffResult.push({cmd: '=', idx: oldIdx, idx1: newIdx});
  23669. })
  23670. .remove(function (idx) {
  23671. diffResult.push({cmd: '-', idx: idx});
  23672. })
  23673. .execute();
  23674. return diffResult;
  23675. }
  23676. module.exports = function (
  23677. oldData, newData,
  23678. oldStackedOnPoints, newStackedOnPoints,
  23679. oldCoordSys, newCoordSys
  23680. ) {
  23681. var diff = diffData(oldData, newData);
  23682. // var newIdList = newData.mapArray(newData.getId);
  23683. // var oldIdList = oldData.mapArray(oldData.getId);
  23684. // convertToIntId(newIdList, oldIdList);
  23685. // // FIXME One data ?
  23686. // diff = arrayDiff(oldIdList, newIdList);
  23687. var currPoints = [];
  23688. var nextPoints = [];
  23689. // Points for stacking base line
  23690. var currStackedPoints = [];
  23691. var nextStackedPoints = [];
  23692. var status = [];
  23693. var sortedIndices = [];
  23694. var rawIndices = [];
  23695. var dims = newCoordSys.dimensions;
  23696. for (var i = 0; i < diff.length; i++) {
  23697. var diffItem = diff[i];
  23698. var pointAdded = true;
  23699. // FIXME, animation is not so perfect when dataZoom window moves fast
  23700. // Which is in case remvoing or add more than one data in the tail or head
  23701. switch (diffItem.cmd) {
  23702. case '=':
  23703. var currentPt = oldData.getItemLayout(diffItem.idx);
  23704. var nextPt = newData.getItemLayout(diffItem.idx1);
  23705. // If previous data is NaN, use next point directly
  23706. if (isNaN(currentPt[0]) || isNaN(currentPt[1])) {
  23707. currentPt = nextPt.slice();
  23708. }
  23709. currPoints.push(currentPt);
  23710. nextPoints.push(nextPt);
  23711. currStackedPoints.push(oldStackedOnPoints[diffItem.idx]);
  23712. nextStackedPoints.push(newStackedOnPoints[diffItem.idx1]);
  23713. rawIndices.push(newData.getRawIndex(diffItem.idx1));
  23714. break;
  23715. case '+':
  23716. var idx = diffItem.idx;
  23717. currPoints.push(
  23718. oldCoordSys.dataToPoint([
  23719. newData.get(dims[0], idx, true), newData.get(dims[1], idx, true)
  23720. ])
  23721. );
  23722. nextPoints.push(newData.getItemLayout(idx).slice());
  23723. currStackedPoints.push(
  23724. getStackedOnPoint(oldCoordSys, newData, idx)
  23725. );
  23726. nextStackedPoints.push(newStackedOnPoints[idx]);
  23727. rawIndices.push(newData.getRawIndex(idx));
  23728. break;
  23729. case '-':
  23730. var idx = diffItem.idx;
  23731. var rawIndex = oldData.getRawIndex(idx);
  23732. // Data is replaced. In the case of dynamic data queue
  23733. // FIXME FIXME FIXME
  23734. if (rawIndex !== idx) {
  23735. currPoints.push(oldData.getItemLayout(idx));
  23736. nextPoints.push(newCoordSys.dataToPoint([
  23737. oldData.get(dims[0], idx, true), oldData.get(dims[1], idx, true)
  23738. ]));
  23739. currStackedPoints.push(oldStackedOnPoints[idx]);
  23740. nextStackedPoints.push(
  23741. getStackedOnPoint(
  23742. newCoordSys, oldData, idx
  23743. )
  23744. );
  23745. rawIndices.push(rawIndex);
  23746. }
  23747. else {
  23748. pointAdded = false;
  23749. }
  23750. }
  23751. // Original indices
  23752. if (pointAdded) {
  23753. status.push(diffItem);
  23754. sortedIndices.push(sortedIndices.length);
  23755. }
  23756. }
  23757. // Diff result may be crossed if all items are changed
  23758. // Sort by data index
  23759. sortedIndices.sort(function (a, b) {
  23760. return rawIndices[a] - rawIndices[b];
  23761. });
  23762. var sortedCurrPoints = [];
  23763. var sortedNextPoints = [];
  23764. var sortedCurrStackedPoints = [];
  23765. var sortedNextStackedPoints = [];
  23766. var sortedStatus = [];
  23767. for (var i = 0; i < sortedIndices.length; i++) {
  23768. var idx = sortedIndices[i];
  23769. sortedCurrPoints[i] = currPoints[idx];
  23770. sortedNextPoints[i] = nextPoints[idx];
  23771. sortedCurrStackedPoints[i] = currStackedPoints[idx];
  23772. sortedNextStackedPoints[i] = nextStackedPoints[idx];
  23773. sortedStatus[i] = status[idx];
  23774. }
  23775. return {
  23776. current: sortedCurrPoints,
  23777. next: sortedNextPoints,
  23778. stackedOnCurrent: sortedCurrStackedPoints,
  23779. stackedOnNext: sortedNextStackedPoints,
  23780. status: sortedStatus
  23781. };
  23782. };
  23783. /***/ },
  23784. /* 120 */
  23785. /***/ function(module, exports, __webpack_require__) {
  23786. // Poly path support NaN point
  23787. var Path = __webpack_require__(20);
  23788. var vec2 = __webpack_require__(10);
  23789. var vec2Min = vec2.min;
  23790. var vec2Max = vec2.max;
  23791. var scaleAndAdd = vec2.scaleAndAdd;
  23792. var v2Copy = vec2.copy;
  23793. // Temporary variable
  23794. var v = [];
  23795. var cp0 = [];
  23796. var cp1 = [];
  23797. function isPointNull(p) {
  23798. return isNaN(p[0]) || isNaN(p[1]);
  23799. }
  23800. function drawSegment(
  23801. ctx, points, start, segLen, allLen,
  23802. dir, smoothMin, smoothMax, smooth, smoothMonotone, connectNulls
  23803. ) {
  23804. var prevIdx = 0;
  23805. var idx = start;
  23806. for (var k = 0; k < segLen; k++) {
  23807. var p = points[idx];
  23808. if (idx >= allLen || idx < 0) {
  23809. break;
  23810. }
  23811. if (isPointNull(p)) {
  23812. if (connectNulls) {
  23813. idx += dir;
  23814. continue;
  23815. }
  23816. break;
  23817. }
  23818. if (idx === start) {
  23819. ctx[dir > 0 ? 'moveTo' : 'lineTo'](p[0], p[1]);
  23820. v2Copy(cp0, p);
  23821. }
  23822. else {
  23823. if (smooth > 0) {
  23824. var nextIdx = idx + dir;
  23825. var nextP = points[nextIdx];
  23826. if (connectNulls) {
  23827. // Find next point not null
  23828. while (nextP && isPointNull(points[nextIdx])) {
  23829. nextIdx += dir;
  23830. nextP = points[nextIdx];
  23831. }
  23832. }
  23833. var ratioNextSeg = 0.5;
  23834. var prevP = points[prevIdx];
  23835. var nextP = points[nextIdx];
  23836. // Last point
  23837. if (!nextP || isPointNull(nextP)) {
  23838. v2Copy(cp1, p);
  23839. }
  23840. else {
  23841. // If next data is null in not connect case
  23842. if (isPointNull(nextP) && !connectNulls) {
  23843. nextP = p;
  23844. }
  23845. vec2.sub(v, nextP, prevP);
  23846. var lenPrevSeg;
  23847. var lenNextSeg;
  23848. if (smoothMonotone === 'x' || smoothMonotone === 'y') {
  23849. var dim = smoothMonotone === 'x' ? 0 : 1;
  23850. lenPrevSeg = Math.abs(p[dim] - prevP[dim]);
  23851. lenNextSeg = Math.abs(p[dim] - nextP[dim]);
  23852. }
  23853. else {
  23854. lenPrevSeg = vec2.dist(p, prevP);
  23855. lenNextSeg = vec2.dist(p, nextP);
  23856. }
  23857. // Use ratio of seg length
  23858. ratioNextSeg = lenNextSeg / (lenNextSeg + lenPrevSeg);
  23859. scaleAndAdd(cp1, p, v, -smooth * (1 - ratioNextSeg));
  23860. }
  23861. // Smooth constraint
  23862. vec2Min(cp0, cp0, smoothMax);
  23863. vec2Max(cp0, cp0, smoothMin);
  23864. vec2Min(cp1, cp1, smoothMax);
  23865. vec2Max(cp1, cp1, smoothMin);
  23866. ctx.bezierCurveTo(
  23867. cp0[0], cp0[1],
  23868. cp1[0], cp1[1],
  23869. p[0], p[1]
  23870. );
  23871. // cp0 of next segment
  23872. scaleAndAdd(cp0, p, v, smooth * ratioNextSeg);
  23873. }
  23874. else {
  23875. ctx.lineTo(p[0], p[1]);
  23876. }
  23877. }
  23878. prevIdx = idx;
  23879. idx += dir;
  23880. }
  23881. return k;
  23882. }
  23883. function getBoundingBox(points, smoothConstraint) {
  23884. var ptMin = [Infinity, Infinity];
  23885. var ptMax = [-Infinity, -Infinity];
  23886. if (smoothConstraint) {
  23887. for (var i = 0; i < points.length; i++) {
  23888. var pt = points[i];
  23889. if (pt[0] < ptMin[0]) { ptMin[0] = pt[0]; }
  23890. if (pt[1] < ptMin[1]) { ptMin[1] = pt[1]; }
  23891. if (pt[0] > ptMax[0]) { ptMax[0] = pt[0]; }
  23892. if (pt[1] > ptMax[1]) { ptMax[1] = pt[1]; }
  23893. }
  23894. }
  23895. return {
  23896. min: smoothConstraint ? ptMin : ptMax,
  23897. max: smoothConstraint ? ptMax : ptMin
  23898. };
  23899. }
  23900. module.exports = {
  23901. Polyline: Path.extend({
  23902. type: 'ec-polyline',
  23903. shape: {
  23904. points: [],
  23905. smooth: 0,
  23906. smoothConstraint: true,
  23907. smoothMonotone: null,
  23908. connectNulls: false
  23909. },
  23910. style: {
  23911. fill: null,
  23912. stroke: '#000'
  23913. },
  23914. buildPath: function (ctx, shape) {
  23915. var points = shape.points;
  23916. var i = 0;
  23917. var len = points.length;
  23918. var result = getBoundingBox(points, shape.smoothConstraint);
  23919. if (shape.connectNulls) {
  23920. // Must remove first and last null values avoid draw error in polygon
  23921. for (; len > 0; len--) {
  23922. if (!isPointNull(points[len - 1])) {
  23923. break;
  23924. }
  23925. }
  23926. for (; i < len; i++) {
  23927. if (!isPointNull(points[i])) {
  23928. break;
  23929. }
  23930. }
  23931. }
  23932. while (i < len) {
  23933. i += drawSegment(
  23934. ctx, points, i, len, len,
  23935. 1, result.min, result.max, shape.smooth,
  23936. shape.smoothMonotone, shape.connectNulls
  23937. ) + 1;
  23938. }
  23939. }
  23940. }),
  23941. Polygon: Path.extend({
  23942. type: 'ec-polygon',
  23943. shape: {
  23944. points: [],
  23945. // Offset between stacked base points and points
  23946. stackedOnPoints: [],
  23947. smooth: 0,
  23948. stackedOnSmooth: 0,
  23949. smoothConstraint: true,
  23950. smoothMonotone: null,
  23951. connectNulls: false
  23952. },
  23953. buildPath: function (ctx, shape) {
  23954. var points = shape.points;
  23955. var stackedOnPoints = shape.stackedOnPoints;
  23956. var i = 0;
  23957. var len = points.length;
  23958. var smoothMonotone = shape.smoothMonotone;
  23959. var bbox = getBoundingBox(points, shape.smoothConstraint);
  23960. var stackedOnBBox = getBoundingBox(stackedOnPoints, shape.smoothConstraint);
  23961. if (shape.connectNulls) {
  23962. // Must remove first and last null values avoid draw error in polygon
  23963. for (; len > 0; len--) {
  23964. if (!isPointNull(points[len - 1])) {
  23965. break;
  23966. }
  23967. }
  23968. for (; i < len; i++) {
  23969. if (!isPointNull(points[i])) {
  23970. break;
  23971. }
  23972. }
  23973. }
  23974. while (i < len) {
  23975. var k = drawSegment(
  23976. ctx, points, i, len, len,
  23977. 1, bbox.min, bbox.max, shape.smooth,
  23978. smoothMonotone, shape.connectNulls
  23979. );
  23980. drawSegment(
  23981. ctx, stackedOnPoints, i + k - 1, k, len,
  23982. -1, stackedOnBBox.min, stackedOnBBox.max, shape.stackedOnSmooth,
  23983. smoothMonotone, shape.connectNulls
  23984. );
  23985. i += k + 1;
  23986. ctx.closePath();
  23987. }
  23988. }
  23989. })
  23990. };
  23991. /***/ },
  23992. /* 121 */
  23993. /***/ function(module, exports) {
  23994. module.exports = function (seriesType, defaultSymbolType, legendSymbol, ecModel, api) {
  23995. // Encoding visual for all series include which is filtered for legend drawing
  23996. ecModel.eachRawSeriesByType(seriesType, function (seriesModel) {
  23997. var data = seriesModel.getData();
  23998. var symbolType = seriesModel.get('symbol') || defaultSymbolType;
  23999. var symbolSize = seriesModel.get('symbolSize');
  24000. data.setVisual({
  24001. legendSymbol: legendSymbol || symbolType,
  24002. symbol: symbolType,
  24003. symbolSize: symbolSize
  24004. });
  24005. // Only visible series has each data be visual encoded
  24006. if (!ecModel.isSeriesFiltered(seriesModel)) {
  24007. if (typeof symbolSize === 'function') {
  24008. data.each(function (idx) {
  24009. var rawValue = seriesModel.getRawValue(idx);
  24010. // FIXME
  24011. var params = seriesModel.getDataParams(idx);
  24012. data.setItemVisual(idx, 'symbolSize', symbolSize(rawValue, params));
  24013. });
  24014. }
  24015. data.each(function (idx) {
  24016. var itemModel = data.getItemModel(idx);
  24017. var itemSymbolType = itemModel.getShallow('symbol', true);
  24018. var itemSymbolSize = itemModel.getShallow('symbolSize', true);
  24019. // If has item symbol
  24020. if (itemSymbolType != null) {
  24021. data.setItemVisual(idx, 'symbol', itemSymbolType);
  24022. }
  24023. if (itemSymbolSize != null) {
  24024. // PENDING Transform symbolSize ?
  24025. data.setItemVisual(idx, 'symbolSize', itemSymbolSize);
  24026. }
  24027. });
  24028. }
  24029. });
  24030. };
  24031. /***/ },
  24032. /* 122 */
  24033. /***/ function(module, exports) {
  24034. module.exports = function (seriesType, ecModel) {
  24035. ecModel.eachSeriesByType(seriesType, function (seriesModel) {
  24036. var data = seriesModel.getData();
  24037. var coordSys = seriesModel.coordinateSystem;
  24038. if (!coordSys) {
  24039. return;
  24040. }
  24041. var dims = [];
  24042. var coordDims = coordSys.dimensions;
  24043. for (var i = 0; i < coordDims.length; i++) {
  24044. dims.push(seriesModel.coordDimToDataDim(coordSys.dimensions[i])[0]);
  24045. }
  24046. if (dims.length === 1) {
  24047. data.each(dims[0], function (x, idx) {
  24048. // Also {Array.<number>}, not undefined to avoid if...else... statement
  24049. data.setItemLayout(idx, isNaN(x) ? [NaN, NaN] : coordSys.dataToPoint(x));
  24050. });
  24051. }
  24052. else if (dims.length === 2) {
  24053. data.each(dims, function (x, y, idx) {
  24054. // Also {Array.<number>}, not undefined to avoid if...else... statement
  24055. data.setItemLayout(
  24056. idx, (isNaN(x) || isNaN(y)) ? [NaN, NaN] : coordSys.dataToPoint([x, y])
  24057. );
  24058. }, true);
  24059. }
  24060. });
  24061. };
  24062. /***/ },
  24063. /* 123 */
  24064. /***/ function(module, exports) {
  24065. var samplers = {
  24066. average: function (frame) {
  24067. var sum = 0;
  24068. var count = 0;
  24069. for (var i = 0; i < frame.length; i++) {
  24070. if (!isNaN(frame[i])) {
  24071. sum += frame[i];
  24072. count++;
  24073. }
  24074. }
  24075. // Return NaN if count is 0
  24076. return count === 0 ? NaN : sum / count;
  24077. },
  24078. sum: function (frame) {
  24079. var sum = 0;
  24080. for (var i = 0; i < frame.length; i++) {
  24081. // Ignore NaN
  24082. sum += frame[i] || 0;
  24083. }
  24084. return sum;
  24085. },
  24086. max: function (frame) {
  24087. var max = -Infinity;
  24088. for (var i = 0; i < frame.length; i++) {
  24089. frame[i] > max && (max = frame[i]);
  24090. }
  24091. return max;
  24092. },
  24093. min: function (frame) {
  24094. var min = Infinity;
  24095. for (var i = 0; i < frame.length; i++) {
  24096. frame[i] < min && (min = frame[i]);
  24097. }
  24098. return min;
  24099. },
  24100. // TODO
  24101. // Median
  24102. nearest: function (frame) {
  24103. return frame[0];
  24104. }
  24105. };
  24106. var indexSampler = function (frame, value) {
  24107. return Math.round(frame.length / 2);
  24108. };
  24109. module.exports = function (seriesType, ecModel, api) {
  24110. ecModel.eachSeriesByType(seriesType, function (seriesModel) {
  24111. var data = seriesModel.getData();
  24112. var sampling = seriesModel.get('sampling');
  24113. var coordSys = seriesModel.coordinateSystem;
  24114. // Only cartesian2d support down sampling
  24115. if (coordSys.type === 'cartesian2d' && sampling) {
  24116. var baseAxis = coordSys.getBaseAxis();
  24117. var valueAxis = coordSys.getOtherAxis(baseAxis);
  24118. var extent = baseAxis.getExtent();
  24119. // Coordinste system has been resized
  24120. var size = extent[1] - extent[0];
  24121. var rate = Math.round(data.count() / size);
  24122. if (rate > 1) {
  24123. var sampler;
  24124. if (typeof sampling === 'string') {
  24125. sampler = samplers[sampling];
  24126. }
  24127. else if (typeof sampling === 'function') {
  24128. sampler = sampling;
  24129. }
  24130. if (sampler) {
  24131. data = data.downSample(
  24132. valueAxis.dim, 1 / rate, sampler, indexSampler
  24133. );
  24134. seriesModel.setData(data);
  24135. }
  24136. }
  24137. }
  24138. }, this);
  24139. };
  24140. /***/ },
  24141. /* 124 */
  24142. /***/ function(module, exports, __webpack_require__) {
  24143. 'use strict';
  24144. var graphic = __webpack_require__(18);
  24145. var zrUtil = __webpack_require__(4);
  24146. var echarts = __webpack_require__(1);
  24147. __webpack_require__(125);
  24148. __webpack_require__(133);
  24149. // Grid view
  24150. echarts.extendComponentView({
  24151. type: 'grid',
  24152. render: function (gridModel, ecModel) {
  24153. this.group.removeAll();
  24154. if (gridModel.get('show')) {
  24155. this.group.add(new graphic.Rect({
  24156. shape: gridModel.coordinateSystem.getRect(),
  24157. style: zrUtil.defaults({
  24158. fill: gridModel.get('backgroundColor')
  24159. }, gridModel.getItemStyle()),
  24160. silent: true,
  24161. z2: -1
  24162. }));
  24163. }
  24164. }
  24165. });
  24166. echarts.registerPreprocessor(function (option) {
  24167. // Only create grid when need
  24168. if (option.xAxis && option.yAxis && !option.grid) {
  24169. option.grid = {};
  24170. }
  24171. });
  24172. /***/ },
  24173. /* 125 */
  24174. /***/ function(module, exports, __webpack_require__) {
  24175. /**
  24176. * Grid is a region which contains at most 4 cartesian systems
  24177. *
  24178. * TODO Default cartesian
  24179. */
  24180. var factory = exports;
  24181. var layout = __webpack_require__(71);
  24182. var axisHelper = __webpack_require__(101);
  24183. var zrUtil = __webpack_require__(4);
  24184. var Cartesian2D = __webpack_require__(126);
  24185. var Axis2D = __webpack_require__(128);
  24186. var each = zrUtil.each;
  24187. var ifAxisCrossZero = axisHelper.ifAxisCrossZero;
  24188. var niceScaleExtent = axisHelper.niceScaleExtent;
  24189. // 依赖 GridModel, AxisModel 做预处理
  24190. __webpack_require__(129);
  24191. /**
  24192. * Check if the axis is used in the specified grid
  24193. * @inner
  24194. */
  24195. function isAxisUsedInTheGrid(axisModel, gridModel, ecModel) {
  24196. return axisModel.getCoordSysModel() === gridModel;
  24197. }
  24198. function getLabelUnionRect(axis) {
  24199. var axisModel = axis.model;
  24200. var labels = axisModel.getFormattedLabels();
  24201. var textStyleModel = axisModel.getModel('axisLabel.textStyle');
  24202. var rect;
  24203. var step = 1;
  24204. var labelCount = labels.length;
  24205. if (labelCount > 40) {
  24206. // Simple optimization for large amount of labels
  24207. step = Math.ceil(labelCount / 40);
  24208. }
  24209. for (var i = 0; i < labelCount; i += step) {
  24210. if (!axis.isLabelIgnored(i)) {
  24211. var singleRect = textStyleModel.getTextRect(labels[i]);
  24212. // FIXME consider label rotate
  24213. rect ? rect.union(singleRect) : (rect = singleRect);
  24214. }
  24215. }
  24216. return rect;
  24217. }
  24218. function Grid(gridModel, ecModel, api) {
  24219. /**
  24220. * @type {Object.<string, module:echarts/coord/cartesian/Cartesian2D>}
  24221. * @private
  24222. */
  24223. this._coordsMap = {};
  24224. /**
  24225. * @type {Array.<module:echarts/coord/cartesian/Cartesian>}
  24226. * @private
  24227. */
  24228. this._coordsList = [];
  24229. /**
  24230. * @type {Object.<string, module:echarts/coord/cartesian/Axis2D>}
  24231. * @private
  24232. */
  24233. this._axesMap = {};
  24234. /**
  24235. * @type {Array.<module:echarts/coord/cartesian/Axis2D>}
  24236. * @private
  24237. */
  24238. this._axesList = [];
  24239. this._initCartesian(gridModel, ecModel, api);
  24240. this.model = gridModel;
  24241. }
  24242. var gridProto = Grid.prototype;
  24243. gridProto.type = 'grid';
  24244. gridProto.axisPointerEnabled = true;
  24245. gridProto.getRect = function () {
  24246. return this._rect;
  24247. };
  24248. gridProto.update = function (ecModel, api) {
  24249. var axesMap = this._axesMap;
  24250. this._updateScale(ecModel, this.model);
  24251. function ifAxisCanNotOnZero(otherAxisDim) {
  24252. var axes = axesMap[otherAxisDim];
  24253. for (var idx in axes) {
  24254. if (axes.hasOwnProperty(idx)) {
  24255. var axis = axes[idx];
  24256. if (axis && (
  24257. axis.type === 'category' || axis.type === 'time' || !ifAxisCrossZero(axis)
  24258. )) {
  24259. return true;
  24260. }
  24261. }
  24262. }
  24263. return false;
  24264. }
  24265. each(axesMap.x, function (xAxis) {
  24266. niceScaleExtent(xAxis.scale, xAxis.model);
  24267. });
  24268. each(axesMap.y, function (yAxis) {
  24269. niceScaleExtent(yAxis.scale, yAxis.model);
  24270. });
  24271. // Fix configuration
  24272. each(axesMap.x, function (xAxis) {
  24273. // onZero can not be enabled in these two situations
  24274. // 1. When any other axis is a category axis
  24275. // 2. When any other axis not across 0 point
  24276. if (ifAxisCanNotOnZero('y')) {
  24277. xAxis.onZero = false;
  24278. }
  24279. });
  24280. each(axesMap.y, function (yAxis) {
  24281. if (ifAxisCanNotOnZero('x')) {
  24282. yAxis.onZero = false;
  24283. }
  24284. });
  24285. // Resize again if containLabel is enabled
  24286. // FIXME It may cause getting wrong grid size in data processing stage
  24287. this.resize(this.model, api);
  24288. };
  24289. /**
  24290. * Resize the grid
  24291. * @param {module:echarts/coord/cartesian/GridModel} gridModel
  24292. * @param {module:echarts/ExtensionAPI} api
  24293. */
  24294. gridProto.resize = function (gridModel, api) {
  24295. var gridRect = layout.getLayoutRect(
  24296. gridModel.getBoxLayoutParams(), {
  24297. width: api.getWidth(),
  24298. height: api.getHeight()
  24299. });
  24300. this._rect = gridRect;
  24301. var axesList = this._axesList;
  24302. adjustAxes();
  24303. // Minus label size
  24304. if (gridModel.get('containLabel')) {
  24305. each(axesList, function (axis) {
  24306. if (!axis.model.get('axisLabel.inside')) {
  24307. var labelUnionRect = getLabelUnionRect(axis);
  24308. if (labelUnionRect) {
  24309. var dim = axis.isHorizontal() ? 'height' : 'width';
  24310. var margin = axis.model.get('axisLabel.margin');
  24311. gridRect[dim] -= labelUnionRect[dim] + margin;
  24312. if (axis.position === 'top') {
  24313. gridRect.y += labelUnionRect.height + margin;
  24314. }
  24315. else if (axis.position === 'left') {
  24316. gridRect.x += labelUnionRect.width + margin;
  24317. }
  24318. }
  24319. }
  24320. });
  24321. adjustAxes();
  24322. }
  24323. function adjustAxes() {
  24324. each(axesList, function (axis) {
  24325. var isHorizontal = axis.isHorizontal();
  24326. var extent = isHorizontal ? [0, gridRect.width] : [0, gridRect.height];
  24327. var idx = axis.inverse ? 1 : 0;
  24328. axis.setExtent(extent[idx], extent[1 - idx]);
  24329. updateAxisTransfrom(axis, isHorizontal ? gridRect.x : gridRect.y);
  24330. });
  24331. }
  24332. };
  24333. /**
  24334. * @param {string} axisType
  24335. * @param {ndumber} [axisIndex]
  24336. */
  24337. gridProto.getAxis = function (axisType, axisIndex) {
  24338. var axesMapOnDim = this._axesMap[axisType];
  24339. if (axesMapOnDim != null) {
  24340. if (axisIndex == null) {
  24341. // Find first axis
  24342. for (var name in axesMapOnDim) {
  24343. if (axesMapOnDim.hasOwnProperty(name)) {
  24344. return axesMapOnDim[name];
  24345. }
  24346. }
  24347. }
  24348. return axesMapOnDim[axisIndex];
  24349. }
  24350. };
  24351. /**
  24352. * @return {Array.<module:echarts/coord/Axis>}
  24353. */
  24354. gridProto.getAxes = function () {
  24355. return this._axesList.slice();
  24356. };
  24357. /**
  24358. * Usage:
  24359. * grid.getCartesian(xAxisIndex, yAxisIndex);
  24360. * grid.getCartesian(xAxisIndex);
  24361. * grid.getCartesian(null, yAxisIndex);
  24362. * grid.getCartesian({xAxisIndex: ..., yAxisIndex: ...});
  24363. *
  24364. * @param {number|Object} [xAxisIndex]
  24365. * @param {number} [yAxisIndex]
  24366. */
  24367. gridProto.getCartesian = function (xAxisIndex, yAxisIndex) {
  24368. if (xAxisIndex != null && yAxisIndex != null) {
  24369. var key = 'x' + xAxisIndex + 'y' + yAxisIndex;
  24370. return this._coordsMap[key];
  24371. }
  24372. if (zrUtil.isObject(xAxisIndex)) {
  24373. yAxisIndex = xAxisIndex.yAxisIndex;
  24374. xAxisIndex = xAxisIndex.xAxisIndex;
  24375. }
  24376. // When only xAxisIndex or yAxisIndex given, find its first cartesian.
  24377. for (var i = 0, coordList = this._coordsList; i < coordList.length; i++) {
  24378. if (coordList[i].getAxis('x').index === xAxisIndex
  24379. || coordList[i].getAxis('y').index === yAxisIndex
  24380. ) {
  24381. return coordList[i];
  24382. }
  24383. }
  24384. };
  24385. gridProto.getCartesians = function () {
  24386. return this._coordsList.slice();
  24387. };
  24388. /**
  24389. * @implements
  24390. * see {module:echarts/CoodinateSystem}
  24391. */
  24392. gridProto.convertToPixel = function (ecModel, finder, value) {
  24393. var target = this._findConvertTarget(ecModel, finder);
  24394. return target.cartesian
  24395. ? target.cartesian.dataToPoint(value)
  24396. : target.axis
  24397. ? target.axis.toGlobalCoord(target.axis.dataToCoord(value))
  24398. : null;
  24399. };
  24400. /**
  24401. * @implements
  24402. * see {module:echarts/CoodinateSystem}
  24403. */
  24404. gridProto.convertFromPixel = function (ecModel, finder, value) {
  24405. var target = this._findConvertTarget(ecModel, finder);
  24406. return target.cartesian
  24407. ? target.cartesian.pointToData(value)
  24408. : target.axis
  24409. ? target.axis.coordToData(target.axis.toLocalCoord(value))
  24410. : null;
  24411. };
  24412. /**
  24413. * @inner
  24414. */
  24415. gridProto._findConvertTarget = function (ecModel, finder) {
  24416. var seriesModel = finder.seriesModel;
  24417. var xAxisModel = finder.xAxisModel
  24418. || (seriesModel && seriesModel.getReferringComponents('xAxis')[0]);
  24419. var yAxisModel = finder.yAxisModel
  24420. || (seriesModel && seriesModel.getReferringComponents('yAxis')[0]);
  24421. var gridModel = finder.gridModel;
  24422. var coordsList = this._coordsList;
  24423. var cartesian;
  24424. var axis;
  24425. if (seriesModel) {
  24426. cartesian = seriesModel.coordinateSystem;
  24427. zrUtil.indexOf(coordsList, cartesian) < 0 && (cartesian = null);
  24428. }
  24429. else if (xAxisModel && yAxisModel) {
  24430. cartesian = this.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex);
  24431. }
  24432. else if (xAxisModel) {
  24433. axis = this.getAxis('x', xAxisModel.componentIndex);
  24434. }
  24435. else if (yAxisModel) {
  24436. axis = this.getAxis('y', yAxisModel.componentIndex);
  24437. }
  24438. // Lowest priority.
  24439. else if (gridModel) {
  24440. var grid = gridModel.coordinateSystem;
  24441. if (grid === this) {
  24442. cartesian = this._coordsList[0];
  24443. }
  24444. }
  24445. return {cartesian: cartesian, axis: axis};
  24446. };
  24447. /**
  24448. * @implements
  24449. * see {module:echarts/CoodinateSystem}
  24450. */
  24451. gridProto.containPoint = function (point) {
  24452. var coord = this._coordsList[0];
  24453. if (coord) {
  24454. return coord.containPoint(point);
  24455. }
  24456. };
  24457. /**
  24458. * Initialize cartesian coordinate systems
  24459. * @private
  24460. */
  24461. gridProto._initCartesian = function (gridModel, ecModel, api) {
  24462. var axisPositionUsed = {
  24463. left: false,
  24464. right: false,
  24465. top: false,
  24466. bottom: false
  24467. };
  24468. var axesMap = {
  24469. x: {},
  24470. y: {}
  24471. };
  24472. var axesCount = {
  24473. x: 0,
  24474. y: 0
  24475. };
  24476. /// Create axis
  24477. ecModel.eachComponent('xAxis', createAxisCreator('x'), this);
  24478. ecModel.eachComponent('yAxis', createAxisCreator('y'), this);
  24479. if (!axesCount.x || !axesCount.y) {
  24480. // Roll back when there no either x or y axis
  24481. this._axesMap = {};
  24482. this._axesList = [];
  24483. return;
  24484. }
  24485. this._axesMap = axesMap;
  24486. /// Create cartesian2d
  24487. each(axesMap.x, function (xAxis, xAxisIndex) {
  24488. each(axesMap.y, function (yAxis, yAxisIndex) {
  24489. var key = 'x' + xAxisIndex + 'y' + yAxisIndex;
  24490. var cartesian = new Cartesian2D(key);
  24491. cartesian.grid = this;
  24492. cartesian.model = gridModel;
  24493. this._coordsMap[key] = cartesian;
  24494. this._coordsList.push(cartesian);
  24495. cartesian.addAxis(xAxis);
  24496. cartesian.addAxis(yAxis);
  24497. }, this);
  24498. }, this);
  24499. function createAxisCreator(axisType) {
  24500. return function (axisModel, idx) {
  24501. if (!isAxisUsedInTheGrid(axisModel, gridModel, ecModel)) {
  24502. return;
  24503. }
  24504. var axisPosition = axisModel.get('position');
  24505. if (axisType === 'x') {
  24506. // Fix position
  24507. if (axisPosition !== 'top' && axisPosition !== 'bottom') {
  24508. // Default bottom of X
  24509. axisPosition = 'bottom';
  24510. if (axisPositionUsed[axisPosition]) {
  24511. axisPosition = axisPosition === 'top' ? 'bottom' : 'top';
  24512. }
  24513. }
  24514. }
  24515. else {
  24516. // Fix position
  24517. if (axisPosition !== 'left' && axisPosition !== 'right') {
  24518. // Default left of Y
  24519. axisPosition = 'left';
  24520. if (axisPositionUsed[axisPosition]) {
  24521. axisPosition = axisPosition === 'left' ? 'right' : 'left';
  24522. }
  24523. }
  24524. }
  24525. axisPositionUsed[axisPosition] = true;
  24526. var axis = new Axis2D(
  24527. axisType, axisHelper.createScaleByModel(axisModel),
  24528. [0, 0],
  24529. axisModel.get('type'),
  24530. axisPosition
  24531. );
  24532. var isCategory = axis.type === 'category';
  24533. axis.onBand = isCategory && axisModel.get('boundaryGap');
  24534. axis.inverse = axisModel.get('inverse');
  24535. axis.onZero = axisModel.get('axisLine.onZero');
  24536. // Inject axis into axisModel
  24537. axisModel.axis = axis;
  24538. // Inject axisModel into axis
  24539. axis.model = axisModel;
  24540. // Inject grid info axis
  24541. axis.grid = this;
  24542. // Index of axis, can be used as key
  24543. axis.index = idx;
  24544. this._axesList.push(axis);
  24545. axesMap[axisType][idx] = axis;
  24546. axesCount[axisType]++;
  24547. };
  24548. }
  24549. };
  24550. /**
  24551. * Update cartesian properties from series
  24552. * @param {module:echarts/model/Option} option
  24553. * @private
  24554. */
  24555. gridProto._updateScale = function (ecModel, gridModel) {
  24556. // Reset scale
  24557. zrUtil.each(this._axesList, function (axis) {
  24558. axis.scale.setExtent(Infinity, -Infinity);
  24559. });
  24560. ecModel.eachSeries(function (seriesModel) {
  24561. if (isCartesian2D(seriesModel)) {
  24562. var axesModels = findAxesModels(seriesModel, ecModel);
  24563. var xAxisModel = axesModels[0];
  24564. var yAxisModel = axesModels[1];
  24565. if (!isAxisUsedInTheGrid(xAxisModel, gridModel, ecModel)
  24566. || !isAxisUsedInTheGrid(yAxisModel, gridModel, ecModel)
  24567. ) {
  24568. return;
  24569. }
  24570. var cartesian = this.getCartesian(
  24571. xAxisModel.componentIndex, yAxisModel.componentIndex
  24572. );
  24573. var data = seriesModel.getData();
  24574. var xAxis = cartesian.getAxis('x');
  24575. var yAxis = cartesian.getAxis('y');
  24576. if (data.type === 'list') {
  24577. unionExtent(data, xAxis, seriesModel);
  24578. unionExtent(data, yAxis, seriesModel);
  24579. }
  24580. }
  24581. }, this);
  24582. function unionExtent(data, axis, seriesModel) {
  24583. each(seriesModel.coordDimToDataDim(axis.dim), function (dim) {
  24584. axis.scale.unionExtentFromData(data, dim);
  24585. });
  24586. }
  24587. };
  24588. /**
  24589. * @param {string} [dim] 'x' or 'y' or 'auto' or null/undefined
  24590. * @return {Object} {baseAxes: [], otherAxes: []}
  24591. */
  24592. gridProto.getTooltipAxes = function (dim) {
  24593. var baseAxes = [];
  24594. var otherAxes = [];
  24595. each(this.getCartesians(), function (cartesian) {
  24596. var baseAxis = (dim != null && dim !== 'auto')
  24597. ? cartesian.getAxis(dim) : cartesian.getBaseAxis();
  24598. var otherAxis = cartesian.getOtherAxis(baseAxis);
  24599. zrUtil.indexOf(baseAxes, baseAxis) < 0 && baseAxes.push(baseAxis);
  24600. zrUtil.indexOf(otherAxes, otherAxis) < 0 && otherAxes.push(otherAxis);
  24601. });
  24602. return {baseAxes: baseAxes, otherAxes: otherAxes};
  24603. };
  24604. /**
  24605. * @inner
  24606. */
  24607. function updateAxisTransfrom(axis, coordBase) {
  24608. var axisExtent = axis.getExtent();
  24609. var axisExtentSum = axisExtent[0] + axisExtent[1];
  24610. // Fast transform
  24611. axis.toGlobalCoord = axis.dim === 'x'
  24612. ? function (coord) {
  24613. return coord + coordBase;
  24614. }
  24615. : function (coord) {
  24616. return axisExtentSum - coord + coordBase;
  24617. };
  24618. axis.toLocalCoord = axis.dim === 'x'
  24619. ? function (coord) {
  24620. return coord - coordBase;
  24621. }
  24622. : function (coord) {
  24623. return axisExtentSum - coord + coordBase;
  24624. };
  24625. }
  24626. var axesTypes = ['xAxis', 'yAxis'];
  24627. /**
  24628. * @inner
  24629. */
  24630. function findAxesModels(seriesModel, ecModel) {
  24631. return zrUtil.map(axesTypes, function (axisType) {
  24632. var axisModel = seriesModel.getReferringComponents(axisType)[0];
  24633. if (true) {
  24634. if (!axisModel) {
  24635. throw new Error(axisType + ' "' + zrUtil.retrieve(
  24636. seriesModel.get(axisType + 'Index'),
  24637. seriesModel.get(axisType + 'Id'),
  24638. 0
  24639. ) + '" not found');
  24640. }
  24641. }
  24642. return axisModel;
  24643. });
  24644. }
  24645. /**
  24646. * @inner
  24647. */
  24648. function isCartesian2D(seriesModel) {
  24649. return seriesModel.get('coordinateSystem') === 'cartesian2d';
  24650. }
  24651. Grid.create = function (ecModel, api) {
  24652. var grids = [];
  24653. ecModel.eachComponent('grid', function (gridModel, idx) {
  24654. var grid = new Grid(gridModel, ecModel, api);
  24655. grid.name = 'grid_' + idx;
  24656. // Postpone `resize` to `update`.
  24657. // grid.resize(gridModel, api);
  24658. gridModel.coordinateSystem = grid;
  24659. grids.push(grid);
  24660. });
  24661. // Inject the coordinateSystems into seriesModel
  24662. ecModel.eachSeries(function (seriesModel) {
  24663. if (!isCartesian2D(seriesModel)) {
  24664. return;
  24665. }
  24666. var axesModels = findAxesModels(seriesModel, ecModel);
  24667. var xAxisModel = axesModels[0];
  24668. var yAxisModel = axesModels[1];
  24669. var gridModel = xAxisModel.getCoordSysModel();
  24670. if (true) {
  24671. if (!gridModel) {
  24672. throw new Error(
  24673. 'Grid "' + zrUtil.retrieve(
  24674. xAxisModel.get('gridIndex'),
  24675. xAxisModel.get('gridId'),
  24676. 0
  24677. ) + '" not found'
  24678. );
  24679. }
  24680. if (xAxisModel.getCoordSysModel() !== yAxisModel.getCoordSysModel()) {
  24681. throw new Error('xAxis and yAxis must use the same grid');
  24682. }
  24683. }
  24684. var grid = gridModel.coordinateSystem;
  24685. seriesModel.coordinateSystem = grid.getCartesian(
  24686. xAxisModel.componentIndex, yAxisModel.componentIndex
  24687. );
  24688. });
  24689. return grids;
  24690. };
  24691. // For deciding which dimensions to use when creating list data
  24692. Grid.dimensions = Grid.prototype.dimensions = Cartesian2D.prototype.dimensions;
  24693. __webpack_require__(76).register('cartesian2d', Grid);
  24694. module.exports = Grid;
  24695. /***/ },
  24696. /* 126 */
  24697. /***/ function(module, exports, __webpack_require__) {
  24698. 'use strict';
  24699. var zrUtil = __webpack_require__(4);
  24700. var Cartesian = __webpack_require__(127);
  24701. function Cartesian2D(name) {
  24702. Cartesian.call(this, name);
  24703. }
  24704. Cartesian2D.prototype = {
  24705. constructor: Cartesian2D,
  24706. type: 'cartesian2d',
  24707. /**
  24708. * @type {Array.<string>}
  24709. * @readOnly
  24710. */
  24711. dimensions: ['x', 'y'],
  24712. /**
  24713. * Base axis will be used on stacking.
  24714. *
  24715. * @return {module:echarts/coord/cartesian/Axis2D}
  24716. */
  24717. getBaseAxis: function () {
  24718. return this.getAxesByScale('ordinal')[0]
  24719. || this.getAxesByScale('time')[0]
  24720. || this.getAxis('x');
  24721. },
  24722. /**
  24723. * If contain point
  24724. * @param {Array.<number>} point
  24725. * @return {boolean}
  24726. */
  24727. containPoint: function (point) {
  24728. var axisX = this.getAxis('x');
  24729. var axisY = this.getAxis('y');
  24730. return axisX.contain(axisX.toLocalCoord(point[0]))
  24731. && axisY.contain(axisY.toLocalCoord(point[1]));
  24732. },
  24733. /**
  24734. * If contain data
  24735. * @param {Array.<number>} data
  24736. * @return {boolean}
  24737. */
  24738. containData: function (data) {
  24739. return this.getAxis('x').containData(data[0])
  24740. && this.getAxis('y').containData(data[1]);
  24741. },
  24742. /**
  24743. * Convert series data to an array of points
  24744. * @param {module:echarts/data/List} data
  24745. * @param {boolean} stack
  24746. * @return {Array}
  24747. * Return array of points. For example:
  24748. * `[[10, 10], [20, 20], [30, 30]]`
  24749. */
  24750. dataToPoints: function (data, stack) {
  24751. return data.mapArray(['x', 'y'], function (x, y) {
  24752. return this.dataToPoint([x, y]);
  24753. }, stack, this);
  24754. },
  24755. /**
  24756. * @param {Array.<number>} data
  24757. * @param {boolean} [clamp=false]
  24758. * @return {Array.<number>}
  24759. */
  24760. dataToPoint: function (data, clamp) {
  24761. var xAxis = this.getAxis('x');
  24762. var yAxis = this.getAxis('y');
  24763. return [
  24764. xAxis.toGlobalCoord(xAxis.dataToCoord(data[0], clamp)),
  24765. yAxis.toGlobalCoord(yAxis.dataToCoord(data[1], clamp))
  24766. ];
  24767. },
  24768. /**
  24769. * @param {Array.<number>} point
  24770. * @param {boolean} [clamp=false]
  24771. * @return {Array.<number>}
  24772. */
  24773. pointToData: function (point, clamp) {
  24774. var xAxis = this.getAxis('x');
  24775. var yAxis = this.getAxis('y');
  24776. return [
  24777. xAxis.coordToData(xAxis.toLocalCoord(point[0]), clamp),
  24778. yAxis.coordToData(yAxis.toLocalCoord(point[1]), clamp)
  24779. ];
  24780. },
  24781. /**
  24782. * Get other axis
  24783. * @param {module:echarts/coord/cartesian/Axis2D} axis
  24784. */
  24785. getOtherAxis: function (axis) {
  24786. return this.getAxis(axis.dim === 'x' ? 'y' : 'x');
  24787. }
  24788. };
  24789. zrUtil.inherits(Cartesian2D, Cartesian);
  24790. module.exports = Cartesian2D;
  24791. /***/ },
  24792. /* 127 */
  24793. /***/ function(module, exports, __webpack_require__) {
  24794. 'use strict';
  24795. /**
  24796. * Cartesian coordinate system
  24797. * @module echarts/coord/Cartesian
  24798. *
  24799. */
  24800. var zrUtil = __webpack_require__(4);
  24801. function dimAxisMapper(dim) {
  24802. return this._axes[dim];
  24803. }
  24804. /**
  24805. * @alias module:echarts/coord/Cartesian
  24806. * @constructor
  24807. */
  24808. var Cartesian = function (name) {
  24809. this._axes = {};
  24810. this._dimList = [];
  24811. /**
  24812. * @type {string}
  24813. */
  24814. this.name = name || '';
  24815. };
  24816. Cartesian.prototype = {
  24817. constructor: Cartesian,
  24818. type: 'cartesian',
  24819. /**
  24820. * Get axis
  24821. * @param {number|string} dim
  24822. * @return {module:echarts/coord/Cartesian~Axis}
  24823. */
  24824. getAxis: function (dim) {
  24825. return this._axes[dim];
  24826. },
  24827. /**
  24828. * Get axes list
  24829. * @return {Array.<module:echarts/coord/Cartesian~Axis>}
  24830. */
  24831. getAxes: function () {
  24832. return zrUtil.map(this._dimList, dimAxisMapper, this);
  24833. },
  24834. /**
  24835. * Get axes list by given scale type
  24836. */
  24837. getAxesByScale: function (scaleType) {
  24838. scaleType = scaleType.toLowerCase();
  24839. return zrUtil.filter(
  24840. this.getAxes(),
  24841. function (axis) {
  24842. return axis.scale.type === scaleType;
  24843. }
  24844. );
  24845. },
  24846. /**
  24847. * Add axis
  24848. * @param {module:echarts/coord/Cartesian.Axis}
  24849. */
  24850. addAxis: function (axis) {
  24851. var dim = axis.dim;
  24852. this._axes[dim] = axis;
  24853. this._dimList.push(dim);
  24854. },
  24855. /**
  24856. * Convert data to coord in nd space
  24857. * @param {Array.<number>|Object.<string, number>} val
  24858. * @return {Array.<number>|Object.<string, number>}
  24859. */
  24860. dataToCoord: function (val) {
  24861. return this._dataCoordConvert(val, 'dataToCoord');
  24862. },
  24863. /**
  24864. * Convert coord in nd space to data
  24865. * @param {Array.<number>|Object.<string, number>} val
  24866. * @return {Array.<number>|Object.<string, number>}
  24867. */
  24868. coordToData: function (val) {
  24869. return this._dataCoordConvert(val, 'coordToData');
  24870. },
  24871. _dataCoordConvert: function (input, method) {
  24872. var dimList = this._dimList;
  24873. var output = input instanceof Array ? [] : {};
  24874. for (var i = 0; i < dimList.length; i++) {
  24875. var dim = dimList[i];
  24876. var axis = this._axes[dim];
  24877. output[dim] = axis[method](input[dim]);
  24878. }
  24879. return output;
  24880. }
  24881. };
  24882. module.exports = Cartesian;
  24883. /***/ },
  24884. /* 128 */
  24885. /***/ function(module, exports, __webpack_require__) {
  24886. var zrUtil = __webpack_require__(4);
  24887. var Axis = __webpack_require__(100);
  24888. /**
  24889. * Extend axis 2d
  24890. * @constructor module:echarts/coord/cartesian/Axis2D
  24891. * @extends {module:echarts/coord/cartesian/Axis}
  24892. * @param {string} dim
  24893. * @param {*} scale
  24894. * @param {Array.<number>} coordExtent
  24895. * @param {string} axisType
  24896. * @param {string} position
  24897. */
  24898. var Axis2D = function (dim, scale, coordExtent, axisType, position) {
  24899. Axis.call(this, dim, scale, coordExtent);
  24900. /**
  24901. * Axis type
  24902. * - 'category'
  24903. * - 'value'
  24904. * - 'time'
  24905. * - 'log'
  24906. * @type {string}
  24907. */
  24908. this.type = axisType || 'value';
  24909. /**
  24910. * Axis position
  24911. * - 'top'
  24912. * - 'bottom'
  24913. * - 'left'
  24914. * - 'right'
  24915. */
  24916. this.position = position || 'bottom';
  24917. };
  24918. Axis2D.prototype = {
  24919. constructor: Axis2D,
  24920. /**
  24921. * Index of axis, can be used as key
  24922. */
  24923. index: 0,
  24924. /**
  24925. * If axis is on the zero position of the other axis
  24926. * @type {boolean}
  24927. */
  24928. onZero: false,
  24929. /**
  24930. * Axis model
  24931. * @param {module:echarts/coord/cartesian/AxisModel}
  24932. */
  24933. model: null,
  24934. isHorizontal: function () {
  24935. var position = this.position;
  24936. return position === 'top' || position === 'bottom';
  24937. },
  24938. /**
  24939. * Each item cooresponds to this.getExtent(), which
  24940. * means globalExtent[0] may greater than globalExtent[1],
  24941. * unless `asc` is input.
  24942. *
  24943. * @param {boolean} [asc]
  24944. * @return {Array.<number>}
  24945. */
  24946. getGlobalExtent: function (asc) {
  24947. var ret = this.getExtent();
  24948. ret[0] = this.toGlobalCoord(ret[0]);
  24949. ret[1] = this.toGlobalCoord(ret[1]);
  24950. asc && ret[0] > ret[1] && ret.reverse();
  24951. return ret;
  24952. },
  24953. getOtherAxis: function () {
  24954. this.grid.getOtherAxis();
  24955. },
  24956. /**
  24957. * If label is ignored.
  24958. * Automatically used when axis is category and label can not be all shown
  24959. * @param {number} idx
  24960. * @return {boolean}
  24961. */
  24962. isLabelIgnored: function (idx) {
  24963. if (this.type === 'category') {
  24964. var labelInterval = this.getLabelInterval();
  24965. return ((typeof labelInterval === 'function')
  24966. && !labelInterval(idx, this.scale.getLabel(idx)))
  24967. || idx % (labelInterval + 1);
  24968. }
  24969. },
  24970. /**
  24971. * @override
  24972. */
  24973. pointToData: function (point, clamp) {
  24974. return this.coordToData(this.toLocalCoord(point[this.dim === 'x' ? 0 : 1]), clamp);
  24975. },
  24976. /**
  24977. * Transform global coord to local coord,
  24978. * i.e. var localCoord = axis.toLocalCoord(80);
  24979. * designate by module:echarts/coord/cartesian/Grid.
  24980. * @type {Function}
  24981. */
  24982. toLocalCoord: null,
  24983. /**
  24984. * Transform global coord to local coord,
  24985. * i.e. var globalCoord = axis.toLocalCoord(40);
  24986. * designate by module:echarts/coord/cartesian/Grid.
  24987. * @type {Function}
  24988. */
  24989. toGlobalCoord: null
  24990. };
  24991. zrUtil.inherits(Axis2D, Axis);
  24992. module.exports = Axis2D;
  24993. /***/ },
  24994. /* 129 */
  24995. /***/ function(module, exports, __webpack_require__) {
  24996. 'use strict';
  24997. // Grid 是在有直角坐标系的时候必须要存在的
  24998. // 所以这里也要被 Cartesian2D 依赖
  24999. __webpack_require__(130);
  25000. var ComponentModel = __webpack_require__(69);
  25001. module.exports = ComponentModel.extend({
  25002. type: 'grid',
  25003. dependencies: ['xAxis', 'yAxis'],
  25004. layoutMode: 'box',
  25005. /**
  25006. * @type {module:echarts/coord/cartesian/Grid}
  25007. */
  25008. coordinateSystem: null,
  25009. defaultOption: {
  25010. show: false,
  25011. zlevel: 0,
  25012. z: 0,
  25013. left: '10%',
  25014. top: 60,
  25015. right: '10%',
  25016. bottom: 60,
  25017. // If grid size contain label
  25018. containLabel: false,
  25019. // width: {totalWidth} - left - right,
  25020. // height: {totalHeight} - top - bottom,
  25021. backgroundColor: 'rgba(0,0,0,0)',
  25022. borderWidth: 1,
  25023. borderColor: '#ccc'
  25024. }
  25025. });
  25026. /***/ },
  25027. /* 130 */
  25028. /***/ function(module, exports, __webpack_require__) {
  25029. 'use strict';
  25030. var ComponentModel = __webpack_require__(69);
  25031. var zrUtil = __webpack_require__(4);
  25032. var axisModelCreator = __webpack_require__(131);
  25033. var AxisModel = ComponentModel.extend({
  25034. type: 'cartesian2dAxis',
  25035. /**
  25036. * @type {module:echarts/coord/cartesian/Axis2D}
  25037. */
  25038. axis: null,
  25039. /**
  25040. * @override
  25041. */
  25042. init: function () {
  25043. AxisModel.superApply(this, 'init', arguments);
  25044. this.resetRange();
  25045. },
  25046. /**
  25047. * @override
  25048. */
  25049. mergeOption: function () {
  25050. AxisModel.superApply(this, 'mergeOption', arguments);
  25051. this.resetRange();
  25052. },
  25053. /**
  25054. * @override
  25055. */
  25056. restoreData: function () {
  25057. AxisModel.superApply(this, 'restoreData', arguments);
  25058. this.resetRange();
  25059. },
  25060. /**
  25061. * @override
  25062. * @return {module:echarts/model/Component}
  25063. */
  25064. getCoordSysModel: function () {
  25065. return this.ecModel.queryComponents({
  25066. mainType: 'grid',
  25067. index: this.option.gridIndex,
  25068. id: this.option.gridId
  25069. })[0];
  25070. }
  25071. });
  25072. function getAxisType(axisDim, option) {
  25073. // Default axis with data is category axis
  25074. return option.type || (option.data ? 'category' : 'value');
  25075. }
  25076. zrUtil.merge(AxisModel.prototype, __webpack_require__(112));
  25077. var extraOption = {
  25078. // gridIndex: 0,
  25079. // gridId: '',
  25080. // Offset is for multiple axis on the same position
  25081. offset: 0
  25082. };
  25083. axisModelCreator('x', AxisModel, getAxisType, extraOption);
  25084. axisModelCreator('y', AxisModel, getAxisType, extraOption);
  25085. module.exports = AxisModel;
  25086. /***/ },
  25087. /* 131 */
  25088. /***/ function(module, exports, __webpack_require__) {
  25089. var axisDefault = __webpack_require__(132);
  25090. var zrUtil = __webpack_require__(4);
  25091. var ComponentModel = __webpack_require__(69);
  25092. var layout = __webpack_require__(71);
  25093. // FIXME axisType is fixed ?
  25094. var AXIS_TYPES = ['value', 'category', 'time', 'log'];
  25095. /**
  25096. * Generate sub axis model class
  25097. * @param {string} axisName 'x' 'y' 'radius' 'angle' 'parallel'
  25098. * @param {module:echarts/model/Component} BaseAxisModelClass
  25099. * @param {Function} axisTypeDefaulter
  25100. * @param {Object} [extraDefaultOption]
  25101. */
  25102. module.exports = function (axisName, BaseAxisModelClass, axisTypeDefaulter, extraDefaultOption) {
  25103. zrUtil.each(AXIS_TYPES, function (axisType) {
  25104. BaseAxisModelClass.extend({
  25105. type: axisName + 'Axis.' + axisType,
  25106. mergeDefaultAndTheme: function (option, ecModel) {
  25107. var layoutMode = this.layoutMode;
  25108. var inputPositionParams = layoutMode
  25109. ? layout.getLayoutParams(option) : {};
  25110. var themeModel = ecModel.getTheme();
  25111. zrUtil.merge(option, themeModel.get(axisType + 'Axis'));
  25112. zrUtil.merge(option, this.getDefaultOption());
  25113. option.type = axisTypeDefaulter(axisName, option);
  25114. if (layoutMode) {
  25115. layout.mergeLayoutParam(option, inputPositionParams, layoutMode);
  25116. }
  25117. },
  25118. defaultOption: zrUtil.mergeAll(
  25119. [
  25120. {},
  25121. axisDefault[axisType + 'Axis'],
  25122. extraDefaultOption
  25123. ],
  25124. true
  25125. )
  25126. });
  25127. });
  25128. ComponentModel.registerSubTypeDefaulter(
  25129. axisName + 'Axis',
  25130. zrUtil.curry(axisTypeDefaulter, axisName)
  25131. );
  25132. };
  25133. /***/ },
  25134. /* 132 */
  25135. /***/ function(module, exports, __webpack_require__) {
  25136. var zrUtil = __webpack_require__(4);
  25137. var defaultOption = {
  25138. show: true,
  25139. zlevel: 0, // 一级层叠
  25140. z: 0, // 二级层叠
  25141. // 反向坐标轴
  25142. inverse: false,
  25143. // 坐标轴名字,默认为空
  25144. name: '',
  25145. // 坐标轴名字位置,支持'start' | 'middle' | 'end'
  25146. nameLocation: 'end',
  25147. // 坐标轴名字旋转,degree。
  25148. nameRotate: null, // Adapt to axis rotate, when nameLocation is 'middle'.
  25149. nameTruncate: {
  25150. maxWidth: null,
  25151. ellipsis: '...',
  25152. placeholder: '.'
  25153. },
  25154. // 坐标轴文字样式,默认取全局样式
  25155. nameTextStyle: {},
  25156. // 文字与轴线距离
  25157. nameGap: 15,
  25158. silent: false, // Default false to support tooltip.
  25159. triggerEvent: false, // Default false to avoid legacy user event listener fail.
  25160. tooltip: {
  25161. show: false
  25162. },
  25163. axisPointer: {},
  25164. // 坐标轴线
  25165. axisLine: {
  25166. // 默认显示,属性show控制显示与否
  25167. show: true,
  25168. onZero: true,
  25169. // 属性lineStyle控制线条样式
  25170. lineStyle: {
  25171. color: '#333',
  25172. width: 1,
  25173. type: 'solid'
  25174. }
  25175. },
  25176. // 坐标轴小标记
  25177. axisTick: {
  25178. // 属性show控制显示与否,默认显示
  25179. show: true,
  25180. // 控制小标记是否在grid里
  25181. inside: false,
  25182. // 属性length控制线长
  25183. length: 5,
  25184. // 属性lineStyle控制线条样式
  25185. lineStyle: {
  25186. width: 1
  25187. }
  25188. },
  25189. // 坐标轴文本标签,详见axis.axisLabel
  25190. axisLabel: {
  25191. show: true,
  25192. // 控制文本标签是否在grid里
  25193. inside: false,
  25194. rotate: 0,
  25195. showMinLabel: null, // true | false | null (auto)
  25196. showMaxLabel: null, // true | false | null (auto)
  25197. margin: 8,
  25198. // formatter: null,
  25199. // 其余属性默认使用全局文本样式,详见TEXTSTYLE
  25200. textStyle: {
  25201. fontSize: 12
  25202. }
  25203. },
  25204. // 分隔线
  25205. splitLine: {
  25206. // 默认显示,属性show控制显示与否
  25207. show: true,
  25208. // 属性lineStyle(详见lineStyle)控制线条样式
  25209. lineStyle: {
  25210. color: ['#ccc'],
  25211. width: 1,
  25212. type: 'solid'
  25213. }
  25214. },
  25215. // 分隔区域
  25216. splitArea: {
  25217. // 默认不显示,属性show控制显示与否
  25218. show: false,
  25219. // 属性areaStyle(详见areaStyle)控制区域样式
  25220. areaStyle: {
  25221. color: ['rgba(250,250,250,0.3)','rgba(200,200,200,0.3)']
  25222. }
  25223. }
  25224. };
  25225. var categoryAxis = zrUtil.merge({
  25226. // 类目起始和结束两端空白策略
  25227. boundaryGap: true,
  25228. // splitArea: {
  25229. // show: false
  25230. // },
  25231. splitLine: {
  25232. show: false
  25233. },
  25234. // 坐标轴小标记
  25235. axisTick: {
  25236. // If tick is align with label when boundaryGap is true
  25237. alignWithLabel: false,
  25238. interval: 'auto'
  25239. },
  25240. // 坐标轴文本标签,详见axis.axisLabel
  25241. axisLabel: {
  25242. interval: 'auto'
  25243. }
  25244. }, defaultOption);
  25245. var valueAxis = zrUtil.merge({
  25246. // 数值起始和结束两端空白策略
  25247. boundaryGap: [0, 0],
  25248. // 最小值, 设置成 'dataMin' 则从数据中计算最小值
  25249. // min: null,
  25250. // 最大值,设置成 'dataMax' 则从数据中计算最大值
  25251. // max: null,
  25252. // Readonly prop, specifies start value of the range when using data zoom.
  25253. // rangeStart: null
  25254. // Readonly prop, specifies end value of the range when using data zoom.
  25255. // rangeEnd: null
  25256. // 脱离0值比例,放大聚焦到最终_min,_max区间
  25257. // scale: false,
  25258. // 分割段数,默认为5
  25259. splitNumber: 5
  25260. // Minimum interval
  25261. // minInterval: null
  25262. }, defaultOption);
  25263. // FIXME
  25264. var timeAxis = zrUtil.defaults({
  25265. scale: true,
  25266. min: 'dataMin',
  25267. max: 'dataMax'
  25268. }, valueAxis);
  25269. var logAxis = zrUtil.defaults({
  25270. scale: true,
  25271. logBase: 10
  25272. }, valueAxis);
  25273. module.exports = {
  25274. categoryAxis: categoryAxis,
  25275. valueAxis: valueAxis,
  25276. timeAxis: timeAxis,
  25277. logAxis: logAxis
  25278. };
  25279. /***/ },
  25280. /* 133 */
  25281. /***/ function(module, exports, __webpack_require__) {
  25282. 'use strict';
  25283. // TODO boundaryGap
  25284. __webpack_require__(130);
  25285. __webpack_require__(134);
  25286. /***/ },
  25287. /* 134 */
  25288. /***/ function(module, exports, __webpack_require__) {
  25289. var zrUtil = __webpack_require__(4);
  25290. var graphic = __webpack_require__(18);
  25291. var AxisBuilder = __webpack_require__(135);
  25292. var AxisView = __webpack_require__(136);
  25293. var cartesianAxisHelper = __webpack_require__(138);
  25294. var ifIgnoreOnTick = AxisBuilder.ifIgnoreOnTick;
  25295. var getInterval = AxisBuilder.getInterval;
  25296. var axisBuilderAttrs = [
  25297. 'axisLine', 'axisLabel', 'axisTick', 'axisName'
  25298. ];
  25299. var selfBuilderAttrs = [
  25300. 'splitArea', 'splitLine'
  25301. ];
  25302. // function getAlignWithLabel(model, axisModel) {
  25303. // var alignWithLabel = model.get('alignWithLabel');
  25304. // if (alignWithLabel === 'auto') {
  25305. // alignWithLabel = axisModel.get('axisTick.alignWithLabel');
  25306. // }
  25307. // return alignWithLabel;
  25308. // }
  25309. var CartesianAxisView = AxisView.extend({
  25310. type: 'cartesianAxis',
  25311. axisPointerClass: 'CartesianAxisPointer',
  25312. /**
  25313. * @override
  25314. */
  25315. render: function (axisModel, ecModel, api, payload) {
  25316. this.group.removeAll();
  25317. var oldAxisGroup = this._axisGroup;
  25318. this._axisGroup = new graphic.Group();
  25319. this.group.add(this._axisGroup);
  25320. if (!axisModel.get('show')) {
  25321. return;
  25322. }
  25323. var gridModel = axisModel.getCoordSysModel();
  25324. var layout = cartesianAxisHelper.layout(gridModel, axisModel);
  25325. var axisBuilder = new AxisBuilder(axisModel, layout);
  25326. zrUtil.each(axisBuilderAttrs, axisBuilder.add, axisBuilder);
  25327. this._axisGroup.add(axisBuilder.getGroup());
  25328. zrUtil.each(selfBuilderAttrs, function (name) {
  25329. if (axisModel.get(name + '.show')) {
  25330. this['_' + name](axisModel, gridModel, layout.labelInterval);
  25331. }
  25332. }, this);
  25333. graphic.groupTransition(oldAxisGroup, this._axisGroup, axisModel);
  25334. CartesianAxisView.superCall(this, 'render', axisModel, ecModel, api, payload);
  25335. },
  25336. /**
  25337. * @param {module:echarts/coord/cartesian/AxisModel} axisModel
  25338. * @param {module:echarts/coord/cartesian/GridModel} gridModel
  25339. * @param {number|Function} labelInterval
  25340. * @private
  25341. */
  25342. _splitLine: function (axisModel, gridModel, labelInterval) {
  25343. var axis = axisModel.axis;
  25344. if (axis.scale.isBlank()) {
  25345. return;
  25346. }
  25347. var splitLineModel = axisModel.getModel('splitLine');
  25348. var lineStyleModel = splitLineModel.getModel('lineStyle');
  25349. var lineColors = lineStyleModel.get('color');
  25350. var lineInterval = getInterval(splitLineModel, labelInterval);
  25351. lineColors = zrUtil.isArray(lineColors) ? lineColors : [lineColors];
  25352. var gridRect = gridModel.coordinateSystem.getRect();
  25353. var isHorizontal = axis.isHorizontal();
  25354. var lineCount = 0;
  25355. var ticksCoords = axis.getTicksCoords(
  25356. // splitLineModel.get('alignWithLabel')
  25357. );
  25358. var ticks = axis.scale.getTicks();
  25359. var p1 = [];
  25360. var p2 = [];
  25361. // Simple optimization
  25362. // Batching the lines if color are the same
  25363. var lineStyle = lineStyleModel.getLineStyle();
  25364. for (var i = 0; i < ticksCoords.length; i++) {
  25365. if (ifIgnoreOnTick(axis, i, lineInterval)) {
  25366. continue;
  25367. }
  25368. var tickCoord = axis.toGlobalCoord(ticksCoords[i]);
  25369. if (isHorizontal) {
  25370. p1[0] = tickCoord;
  25371. p1[1] = gridRect.y;
  25372. p2[0] = tickCoord;
  25373. p2[1] = gridRect.y + gridRect.height;
  25374. }
  25375. else {
  25376. p1[0] = gridRect.x;
  25377. p1[1] = tickCoord;
  25378. p2[0] = gridRect.x + gridRect.width;
  25379. p2[1] = tickCoord;
  25380. }
  25381. var colorIndex = (lineCount++) % lineColors.length;
  25382. this._axisGroup.add(new graphic.Line(graphic.subPixelOptimizeLine({
  25383. anid: 'line_' + ticks[i],
  25384. shape: {
  25385. x1: p1[0],
  25386. y1: p1[1],
  25387. x2: p2[0],
  25388. y2: p2[1]
  25389. },
  25390. style: zrUtil.defaults({
  25391. stroke: lineColors[colorIndex]
  25392. }, lineStyle),
  25393. silent: true
  25394. })));
  25395. }
  25396. },
  25397. /**
  25398. * @param {module:echarts/coord/cartesian/AxisModel} axisModel
  25399. * @param {module:echarts/coord/cartesian/GridModel} gridModel
  25400. * @param {number|Function} labelInterval
  25401. * @private
  25402. */
  25403. _splitArea: function (axisModel, gridModel, labelInterval) {
  25404. var axis = axisModel.axis;
  25405. if (axis.scale.isBlank()) {
  25406. return;
  25407. }
  25408. var splitAreaModel = axisModel.getModel('splitArea');
  25409. var areaStyleModel = splitAreaModel.getModel('areaStyle');
  25410. var areaColors = areaStyleModel.get('color');
  25411. var gridRect = gridModel.coordinateSystem.getRect();
  25412. var ticksCoords = axis.getTicksCoords(
  25413. // splitAreaModel.get('alignWithLabel')
  25414. );
  25415. var ticks = axis.scale.getTicks();
  25416. var prevX = axis.toGlobalCoord(ticksCoords[0]);
  25417. var prevY = axis.toGlobalCoord(ticksCoords[0]);
  25418. var count = 0;
  25419. var areaInterval = getInterval(splitAreaModel, labelInterval);
  25420. var areaStyle = areaStyleModel.getAreaStyle();
  25421. areaColors = zrUtil.isArray(areaColors) ? areaColors : [areaColors];
  25422. for (var i = 1; i < ticksCoords.length; i++) {
  25423. if (ifIgnoreOnTick(axis, i, areaInterval)) {
  25424. continue;
  25425. }
  25426. var tickCoord = axis.toGlobalCoord(ticksCoords[i]);
  25427. var x;
  25428. var y;
  25429. var width;
  25430. var height;
  25431. if (axis.isHorizontal()) {
  25432. x = prevX;
  25433. y = gridRect.y;
  25434. width = tickCoord - x;
  25435. height = gridRect.height;
  25436. }
  25437. else {
  25438. x = gridRect.x;
  25439. y = prevY;
  25440. width = gridRect.width;
  25441. height = tickCoord - y;
  25442. }
  25443. var colorIndex = (count++) % areaColors.length;
  25444. this._axisGroup.add(new graphic.Rect({
  25445. anid: 'area_' + ticks[i],
  25446. shape: {
  25447. x: x,
  25448. y: y,
  25449. width: width,
  25450. height: height
  25451. },
  25452. style: zrUtil.defaults({
  25453. fill: areaColors[colorIndex]
  25454. }, areaStyle),
  25455. silent: true
  25456. }));
  25457. prevX = x + width;
  25458. prevY = y + height;
  25459. }
  25460. }
  25461. });
  25462. CartesianAxisView.extend({
  25463. type: 'xAxis'
  25464. });
  25465. CartesianAxisView.extend({
  25466. type: 'yAxis'
  25467. });
  25468. /***/ },
  25469. /* 135 */
  25470. /***/ function(module, exports, __webpack_require__) {
  25471. var zrUtil = __webpack_require__(4);
  25472. var formatUtil = __webpack_require__(6);
  25473. var graphic = __webpack_require__(18);
  25474. var Model = __webpack_require__(12);
  25475. var numberUtil = __webpack_require__(7);
  25476. var remRadian = numberUtil.remRadian;
  25477. var isRadianAroundZero = numberUtil.isRadianAroundZero;
  25478. var vec2 = __webpack_require__(10);
  25479. var matrix = __webpack_require__(11);
  25480. var v2ApplyTransform = vec2.applyTransform;
  25481. var retrieve = zrUtil.retrieve;
  25482. var PI = Math.PI;
  25483. function makeAxisEventDataBase(axisModel) {
  25484. var eventData = {
  25485. componentType: axisModel.mainType
  25486. };
  25487. eventData[axisModel.mainType + 'Index'] = axisModel.componentIndex;
  25488. return eventData;
  25489. }
  25490. /**
  25491. * A final axis is translated and rotated from a "standard axis".
  25492. * So opt.position and opt.rotation is required.
  25493. *
  25494. * A standard axis is and axis from [0, 0] to [0, axisExtent[1]],
  25495. * for example: (0, 0) ------------> (0, 50)
  25496. *
  25497. * nameDirection or tickDirection or labelDirection is 1 means tick
  25498. * or label is below the standard axis, whereas is -1 means above
  25499. * the standard axis. labelOffset means offset between label and axis,
  25500. * which is useful when 'onZero', where axisLabel is in the grid and
  25501. * label in outside grid.
  25502. *
  25503. * Tips: like always,
  25504. * positive rotation represents anticlockwise, and negative rotation
  25505. * represents clockwise.
  25506. * The direction of position coordinate is the same as the direction
  25507. * of screen coordinate.
  25508. *
  25509. * Do not need to consider axis 'inverse', which is auto processed by
  25510. * axis extent.
  25511. *
  25512. * @param {module:zrender/container/Group} group
  25513. * @param {Object} axisModel
  25514. * @param {Object} opt Standard axis parameters.
  25515. * @param {Array.<number>} opt.position [x, y]
  25516. * @param {number} opt.rotation by radian
  25517. * @param {number} [opt.nameDirection=1] 1 or -1 Used when nameLocation is 'middle'.
  25518. * @param {number} [opt.tickDirection=1] 1 or -1
  25519. * @param {number} [opt.labelDirection=1] 1 or -1
  25520. * @param {number} [opt.labelOffset=0] Usefull when onZero.
  25521. * @param {string} [opt.axisLabelShow] default get from axisModel.
  25522. * @param {string} [opt.axisName] default get from axisModel.
  25523. * @param {number} [opt.axisNameAvailableWidth]
  25524. * @param {number} [opt.labelRotate] by degree, default get from axisModel.
  25525. * @param {number} [opt.labelInterval] Default label interval when label
  25526. * interval from model is null or 'auto'.
  25527. * @param {number} [opt.strokeContainThreshold] Default label interval when label
  25528. * @param {number} [opt.nameTruncateMaxWidth]
  25529. */
  25530. var AxisBuilder = function (axisModel, opt) {
  25531. /**
  25532. * @readOnly
  25533. */
  25534. this.opt = opt;
  25535. /**
  25536. * @readOnly
  25537. */
  25538. this.axisModel = axisModel;
  25539. // Default value
  25540. zrUtil.defaults(
  25541. opt,
  25542. {
  25543. labelOffset: 0,
  25544. nameDirection: 1,
  25545. tickDirection: 1,
  25546. labelDirection: 1,
  25547. silent: true
  25548. }
  25549. );
  25550. /**
  25551. * @readOnly
  25552. */
  25553. this.group = new graphic.Group();
  25554. // FIXME Not use a seperate text group?
  25555. var dumbGroup = new graphic.Group({
  25556. position: opt.position.slice(),
  25557. rotation: opt.rotation
  25558. });
  25559. // this.group.add(dumbGroup);
  25560. // this._dumbGroup = dumbGroup;
  25561. dumbGroup.updateTransform();
  25562. this._transform = dumbGroup.transform;
  25563. this._dumbGroup = dumbGroup;
  25564. };
  25565. AxisBuilder.prototype = {
  25566. constructor: AxisBuilder,
  25567. hasBuilder: function (name) {
  25568. return !!builders[name];
  25569. },
  25570. add: function (name) {
  25571. builders[name].call(this);
  25572. },
  25573. getGroup: function () {
  25574. return this.group;
  25575. }
  25576. };
  25577. var builders = {
  25578. /**
  25579. * @private
  25580. */
  25581. axisLine: function () {
  25582. var opt = this.opt;
  25583. var axisModel = this.axisModel;
  25584. if (!axisModel.get('axisLine.show')) {
  25585. return;
  25586. }
  25587. var extent = this.axisModel.axis.getExtent();
  25588. var matrix = this._transform;
  25589. var pt1 = [extent[0], 0];
  25590. var pt2 = [extent[1], 0];
  25591. if (matrix) {
  25592. v2ApplyTransform(pt1, pt1, matrix);
  25593. v2ApplyTransform(pt2, pt2, matrix);
  25594. }
  25595. this.group.add(new graphic.Line(graphic.subPixelOptimizeLine({
  25596. // Id for animation
  25597. anid: 'line',
  25598. shape: {
  25599. x1: pt1[0],
  25600. y1: pt1[1],
  25601. x2: pt2[0],
  25602. y2: pt2[1]
  25603. },
  25604. style: zrUtil.extend(
  25605. {lineCap: 'round'},
  25606. axisModel.getModel('axisLine.lineStyle').getLineStyle()
  25607. ),
  25608. strokeContainThreshold: opt.strokeContainThreshold || 5,
  25609. silent: true,
  25610. z2: 1
  25611. })));
  25612. },
  25613. /**
  25614. * @private
  25615. */
  25616. axisTick: function () {
  25617. var axisModel = this.axisModel;
  25618. var axis = axisModel.axis;
  25619. if (!axisModel.get('axisTick.show') || axis.scale.isBlank()) {
  25620. return;
  25621. }
  25622. var tickModel = axisModel.getModel('axisTick');
  25623. var opt = this.opt;
  25624. var lineStyleModel = tickModel.getModel('lineStyle');
  25625. var tickLen = tickModel.get('length');
  25626. var tickInterval = getInterval(tickModel, opt.labelInterval);
  25627. var ticksCoords = axis.getTicksCoords(tickModel.get('alignWithLabel'));
  25628. var ticks = axis.scale.getTicks();
  25629. var pt1 = [];
  25630. var pt2 = [];
  25631. var matrix = this._transform;
  25632. for (var i = 0; i < ticksCoords.length; i++) {
  25633. // Only ordinal scale support tick interval
  25634. if (ifIgnoreOnTick(axis, i, tickInterval)) {
  25635. continue;
  25636. }
  25637. var tickCoord = ticksCoords[i];
  25638. pt1[0] = tickCoord;
  25639. pt1[1] = 0;
  25640. pt2[0] = tickCoord;
  25641. pt2[1] = opt.tickDirection * tickLen;
  25642. if (matrix) {
  25643. v2ApplyTransform(pt1, pt1, matrix);
  25644. v2ApplyTransform(pt2, pt2, matrix);
  25645. }
  25646. // Tick line, Not use group transform to have better line draw
  25647. this.group.add(new graphic.Line(graphic.subPixelOptimizeLine({
  25648. // Id for animation
  25649. anid: 'tick_' + ticks[i],
  25650. shape: {
  25651. x1: pt1[0],
  25652. y1: pt1[1],
  25653. x2: pt2[0],
  25654. y2: pt2[1]
  25655. },
  25656. style: zrUtil.defaults(
  25657. lineStyleModel.getLineStyle(),
  25658. {
  25659. stroke: axisModel.get('axisLine.lineStyle.color')
  25660. }
  25661. ),
  25662. z2: 2,
  25663. silent: true
  25664. })));
  25665. }
  25666. },
  25667. /**
  25668. * @param {module:echarts/coord/cartesian/AxisModel} axisModel
  25669. * @param {module:echarts/coord/cartesian/GridModel} gridModel
  25670. * @private
  25671. */
  25672. axisLabel: function () {
  25673. var opt = this.opt;
  25674. var axisModel = this.axisModel;
  25675. var axis = axisModel.axis;
  25676. var show = retrieve(opt.axisLabelShow, axisModel.get('axisLabel.show'));
  25677. if (!show || axis.scale.isBlank()) {
  25678. return;
  25679. }
  25680. var labelModel = axisModel.getModel('axisLabel');
  25681. var textStyleModel = labelModel.getModel('textStyle');
  25682. var labelMargin = labelModel.get('margin');
  25683. var ticks = axis.scale.getTicks();
  25684. var labels = axisModel.getFormattedLabels();
  25685. // Special label rotate.
  25686. var labelRotation = (
  25687. retrieve(opt.labelRotate, labelModel.get('rotate')) || 0
  25688. ) * PI / 180;
  25689. var labelLayout = innerTextLayout(opt.rotation, labelRotation, opt.labelDirection);
  25690. var categoryData = axisModel.get('data');
  25691. var textEls = [];
  25692. var silent = isSilent(axisModel);
  25693. var triggerEvent = axisModel.get('triggerEvent');
  25694. zrUtil.each(ticks, function (tickVal, index) {
  25695. if (ifIgnoreOnTick(axis, index, opt.labelInterval)) {
  25696. return;
  25697. }
  25698. var itemTextStyleModel = textStyleModel;
  25699. if (categoryData && categoryData[tickVal] && categoryData[tickVal].textStyle) {
  25700. itemTextStyleModel = new Model(
  25701. categoryData[tickVal].textStyle, textStyleModel, axisModel.ecModel
  25702. );
  25703. }
  25704. var textColor = itemTextStyleModel.getTextColor()
  25705. || axisModel.get('axisLine.lineStyle.color');
  25706. var tickCoord = axis.dataToCoord(tickVal);
  25707. var pos = [
  25708. tickCoord,
  25709. opt.labelOffset + opt.labelDirection * labelMargin
  25710. ];
  25711. var labelStr = axis.scale.getLabel(tickVal);
  25712. var textEl = new graphic.Text({
  25713. // Id for animation
  25714. anid: 'label_' + tickVal,
  25715. style: {
  25716. text: labels[index],
  25717. textAlign: itemTextStyleModel.get('align', true) || labelLayout.textAlign,
  25718. textVerticalAlign: itemTextStyleModel.get('baseline', true) || labelLayout.textVerticalAlign,
  25719. textFont: itemTextStyleModel.getFont(),
  25720. fill: typeof textColor === 'function'
  25721. ? textColor(
  25722. // (1) In category axis with data zoom, tick is not the original
  25723. // index of axis.data. So tick should not be exposed to user
  25724. // in category axis.
  25725. // (2) Compatible with previous version, which always returns labelStr.
  25726. // But in interval scale labelStr is like '223,445', which maked
  25727. // user repalce ','. So we modify it to return original val but remain
  25728. // it as 'string' to avoid error in replacing.
  25729. axis.type === 'category' ? labelStr : axis.type === 'value' ? tickVal + '' : tickVal,
  25730. index
  25731. )
  25732. : textColor
  25733. },
  25734. position: pos,
  25735. rotation: labelLayout.rotation,
  25736. silent: silent,
  25737. z2: 10
  25738. });
  25739. // Pack data for mouse event
  25740. if (triggerEvent) {
  25741. textEl.eventData = makeAxisEventDataBase(axisModel);
  25742. textEl.eventData.targetType = 'axisLabel';
  25743. textEl.eventData.value = labelStr;
  25744. }
  25745. // FIXME
  25746. this._dumbGroup.add(textEl);
  25747. textEl.updateTransform();
  25748. textEls.push(textEl);
  25749. this.group.add(textEl);
  25750. textEl.decomposeTransform();
  25751. }, this);
  25752. fixMinMaxLabelShow(axisModel, textEls);
  25753. },
  25754. /**
  25755. * @private
  25756. */
  25757. axisName: function () {
  25758. var opt = this.opt;
  25759. var axisModel = this.axisModel;
  25760. var name = retrieve(opt.axisName, axisModel.get('name'));
  25761. if (!name) {
  25762. return;
  25763. }
  25764. var nameLocation = axisModel.get('nameLocation');
  25765. var nameDirection = opt.nameDirection;
  25766. var textStyleModel = axisModel.getModel('nameTextStyle');
  25767. var gap = axisModel.get('nameGap') || 0;
  25768. var extent = this.axisModel.axis.getExtent();
  25769. var gapSignal = extent[0] > extent[1] ? -1 : 1;
  25770. var pos = [
  25771. nameLocation === 'start'
  25772. ? extent[0] - gapSignal * gap
  25773. : nameLocation === 'end'
  25774. ? extent[1] + gapSignal * gap
  25775. : (extent[0] + extent[1]) / 2, // 'middle'
  25776. // Reuse labelOffset.
  25777. nameLocation === 'middle' ? opt.labelOffset + nameDirection * gap : 0
  25778. ];
  25779. var labelLayout;
  25780. var nameRotation = axisModel.get('nameRotate');
  25781. if (nameRotation != null) {
  25782. nameRotation = nameRotation * PI / 180; // To radian.
  25783. }
  25784. var axisNameAvailableWidth;
  25785. if (nameLocation === 'middle') {
  25786. labelLayout = innerTextLayout(
  25787. opt.rotation,
  25788. nameRotation != null ? nameRotation : opt.rotation, // Adapt to axis.
  25789. nameDirection
  25790. );
  25791. }
  25792. else {
  25793. labelLayout = endTextLayout(
  25794. opt, nameLocation, nameRotation || 0, extent
  25795. );
  25796. axisNameAvailableWidth = opt.axisNameAvailableWidth;
  25797. if (axisNameAvailableWidth != null) {
  25798. axisNameAvailableWidth = Math.abs(
  25799. axisNameAvailableWidth / Math.sin(labelLayout.rotation)
  25800. );
  25801. !isFinite(axisNameAvailableWidth) && (axisNameAvailableWidth = null);
  25802. }
  25803. }
  25804. var textFont = textStyleModel.getFont();
  25805. var truncateOpt = axisModel.get('nameTruncate', true) || {};
  25806. var ellipsis = truncateOpt.ellipsis;
  25807. var maxWidth = retrieve(
  25808. opt.nameTruncateMaxWidth, truncateOpt.maxWidth, axisNameAvailableWidth
  25809. );
  25810. var truncatedText = (ellipsis != null && maxWidth != null)
  25811. ? formatUtil.truncateText(
  25812. name, maxWidth, textFont, ellipsis,
  25813. {minChar: 2, placeholder: truncateOpt.placeholder}
  25814. )
  25815. : name;
  25816. var tooltipOpt = axisModel.get('tooltip', true);
  25817. var mainType = axisModel.mainType;
  25818. var formatterParams = {
  25819. componentType: mainType,
  25820. name: name,
  25821. $vars: ['name']
  25822. };
  25823. formatterParams[mainType + 'Index'] = axisModel.componentIndex;
  25824. var textEl = new graphic.Text({
  25825. // Id for animation
  25826. anid: 'name',
  25827. __fullText: name,
  25828. __truncatedText: truncatedText,
  25829. style: {
  25830. text: truncatedText,
  25831. textFont: textFont,
  25832. fill: textStyleModel.getTextColor()
  25833. || axisModel.get('axisLine.lineStyle.color'),
  25834. textAlign: labelLayout.textAlign,
  25835. textVerticalAlign: labelLayout.textVerticalAlign
  25836. },
  25837. position: pos,
  25838. rotation: labelLayout.rotation,
  25839. silent: isSilent(axisModel),
  25840. z2: 1,
  25841. tooltip: (tooltipOpt && tooltipOpt.show)
  25842. ? zrUtil.extend({
  25843. content: name,
  25844. formatter: function () {
  25845. return name;
  25846. },
  25847. formatterParams: formatterParams
  25848. }, tooltipOpt)
  25849. : null
  25850. });
  25851. if (axisModel.get('triggerEvent')) {
  25852. textEl.eventData = makeAxisEventDataBase(axisModel);
  25853. textEl.eventData.targetType = 'axisName';
  25854. textEl.eventData.name = name;
  25855. }
  25856. // FIXME
  25857. this._dumbGroup.add(textEl);
  25858. textEl.updateTransform();
  25859. this.group.add(textEl);
  25860. textEl.decomposeTransform();
  25861. }
  25862. };
  25863. /**
  25864. * @public
  25865. * @static
  25866. * @param {Object} opt
  25867. * @param {number} axisRotation in radian
  25868. * @param {number} textRotation in radian
  25869. * @param {number} direction
  25870. * @return {Object} {
  25871. * rotation, // according to axis
  25872. * textAlign,
  25873. * textVerticalAlign
  25874. * }
  25875. */
  25876. var innerTextLayout = AxisBuilder.innerTextLayout = function (axisRotation, textRotation, direction) {
  25877. var rotationDiff = remRadian(textRotation - axisRotation);
  25878. var textAlign;
  25879. var textVerticalAlign;
  25880. if (isRadianAroundZero(rotationDiff)) { // Label is parallel with axis line.
  25881. textVerticalAlign = direction > 0 ? 'top' : 'bottom';
  25882. textAlign = 'center';
  25883. }
  25884. else if (isRadianAroundZero(rotationDiff - PI)) { // Label is inverse parallel with axis line.
  25885. textVerticalAlign = direction > 0 ? 'bottom' : 'top';
  25886. textAlign = 'center';
  25887. }
  25888. else {
  25889. textVerticalAlign = 'middle';
  25890. if (rotationDiff > 0 && rotationDiff < PI) {
  25891. textAlign = direction > 0 ? 'right' : 'left';
  25892. }
  25893. else {
  25894. textAlign = direction > 0 ? 'left' : 'right';
  25895. }
  25896. }
  25897. return {
  25898. rotation: rotationDiff,
  25899. textAlign: textAlign,
  25900. textVerticalAlign: textVerticalAlign
  25901. };
  25902. };
  25903. function endTextLayout(opt, textPosition, textRotate, extent) {
  25904. var rotationDiff = remRadian(textRotate - opt.rotation);
  25905. var textAlign;
  25906. var textVerticalAlign;
  25907. var inverse = extent[0] > extent[1];
  25908. var onLeft = (textPosition === 'start' && !inverse)
  25909. || (textPosition !== 'start' && inverse);
  25910. if (isRadianAroundZero(rotationDiff - PI / 2)) {
  25911. textVerticalAlign = onLeft ? 'bottom' : 'top';
  25912. textAlign = 'center';
  25913. }
  25914. else if (isRadianAroundZero(rotationDiff - PI * 1.5)) {
  25915. textVerticalAlign = onLeft ? 'top' : 'bottom';
  25916. textAlign = 'center';
  25917. }
  25918. else {
  25919. textVerticalAlign = 'middle';
  25920. if (rotationDiff < PI * 1.5 && rotationDiff > PI / 2) {
  25921. textAlign = onLeft ? 'left' : 'right';
  25922. }
  25923. else {
  25924. textAlign = onLeft ? 'right' : 'left';
  25925. }
  25926. }
  25927. return {
  25928. rotation: rotationDiff,
  25929. textAlign: textAlign,
  25930. textVerticalAlign: textVerticalAlign
  25931. };
  25932. }
  25933. function isSilent(axisModel) {
  25934. var tooltipOpt = axisModel.get('tooltip');
  25935. return axisModel.get('silent')
  25936. // Consider mouse cursor, add these restrictions.
  25937. || !(
  25938. axisModel.get('triggerEvent') || (tooltipOpt && tooltipOpt.show)
  25939. );
  25940. }
  25941. function fixMinMaxLabelShow(axisModel, textEls) {
  25942. // If min or max are user set, we need to check
  25943. // If the tick on min(max) are overlap on their neighbour tick
  25944. // If they are overlapped, we need to hide the min(max) tick label
  25945. var showMinLabel = axisModel.get('axisLabel.showMinLabel');
  25946. var showMaxLabel = axisModel.get('axisLabel.showMaxLabel');
  25947. var firstLabel = textEls[0];
  25948. var nextLabel = textEls[1];
  25949. var lastLabel = textEls[textEls.length - 1];
  25950. var prevLabel = textEls[textEls.length - 2];
  25951. if (showMinLabel === false) {
  25952. firstLabel.ignore = true;
  25953. }
  25954. else if (axisModel.getMin() != null && isTwoLabelOverlapped(firstLabel, nextLabel)) {
  25955. showMinLabel ? (nextLabel.ignore = true) : (firstLabel.ignore = true);
  25956. }
  25957. if (showMaxLabel === false) {
  25958. lastLabel.ignore = true;
  25959. }
  25960. else if (axisModel.getMax() != null && isTwoLabelOverlapped(prevLabel, lastLabel)) {
  25961. showMaxLabel ? (prevLabel.ignore = true) : (lastLabel.ignore = true);
  25962. }
  25963. }
  25964. function isTwoLabelOverlapped(current, next, labelLayout) {
  25965. // current and next has the same rotation.
  25966. var firstRect = current && current.getBoundingRect().clone();
  25967. var nextRect = next && next.getBoundingRect().clone();
  25968. if (!firstRect || !nextRect) {
  25969. return;
  25970. }
  25971. // When checking intersect of two rotated labels, we use mRotationBack
  25972. // to avoid that boundingRect is enlarge when using `boundingRect.applyTransform`.
  25973. var mRotationBack = matrix.identity([]);
  25974. matrix.rotate(mRotationBack, mRotationBack, -current.rotation);
  25975. firstRect.applyTransform(matrix.mul([], mRotationBack, current.getLocalTransform()));
  25976. nextRect.applyTransform(matrix.mul([], mRotationBack, next.getLocalTransform()));
  25977. return firstRect.intersect(nextRect);
  25978. }
  25979. /**
  25980. * @static
  25981. */
  25982. var ifIgnoreOnTick = AxisBuilder.ifIgnoreOnTick = function (axis, i, interval) {
  25983. var rawTick;
  25984. var scale = axis.scale;
  25985. return scale.type === 'ordinal'
  25986. && (
  25987. typeof interval === 'function'
  25988. ? (
  25989. rawTick = scale.getTicks()[i],
  25990. !interval(rawTick, scale.getLabel(rawTick))
  25991. )
  25992. : i % (interval + 1)
  25993. );
  25994. };
  25995. /**
  25996. * @static
  25997. */
  25998. var getInterval = AxisBuilder.getInterval = function (model, labelInterval) {
  25999. var interval = model.get('interval');
  26000. if (interval == null || interval == 'auto') {
  26001. interval = labelInterval;
  26002. }
  26003. return interval;
  26004. };
  26005. module.exports = AxisBuilder;
  26006. /***/ },
  26007. /* 136 */
  26008. /***/ function(module, exports, __webpack_require__) {
  26009. var axisPointerModelHelper = __webpack_require__(137);
  26010. /**
  26011. * Base class of AxisView.
  26012. */
  26013. var AxisView = __webpack_require__(1).extendComponentView({
  26014. type: 'axis',
  26015. /**
  26016. * @private
  26017. */
  26018. _axisPointer: null,
  26019. /**
  26020. * @protected
  26021. * @type {string}
  26022. */
  26023. axisPointerClass: null,
  26024. /**
  26025. * @override
  26026. */
  26027. render: function (axisModel, ecModel, api, payload) {
  26028. // FIXME
  26029. // This process should proformed after coordinate systems updated
  26030. // (axis scale updated), and should be performed each time update.
  26031. // So put it here temporarily, although it is not appropriate to
  26032. // put a model-writing procedure in `view`.
  26033. this.axisPointerClass && axisPointerModelHelper.fixValue(axisModel);
  26034. AxisView.superApply(this, 'render', arguments);
  26035. updateAxisPointer(this, axisModel, ecModel, api, payload, true);
  26036. },
  26037. /**
  26038. * Action handler.
  26039. * @public
  26040. * @param {module:echarts/coord/cartesian/AxisModel} axisModel
  26041. * @param {module:echarts/model/Global} ecModel
  26042. * @param {module:echarts/ExtensionAPI} api
  26043. * @param {Object} payload
  26044. */
  26045. updateAxisPointer: function (axisModel, ecModel, api, payload, force) {
  26046. updateAxisPointer(this, axisModel, ecModel, api, payload, false);
  26047. },
  26048. /**
  26049. * @override
  26050. */
  26051. remove: function (ecModel, api) {
  26052. var axisPointer = this._axisPointer;
  26053. axisPointer && axisPointer.remove(api);
  26054. AxisView.superApply(this, 'remove', arguments);
  26055. },
  26056. /**
  26057. * @override
  26058. */
  26059. dispose: function (ecModel, api) {
  26060. disposeAxisPointer(this, api);
  26061. AxisView.superApply(this, 'dispose', arguments);
  26062. }
  26063. });
  26064. function updateAxisPointer(axisView, axisModel, ecModel, api, payload, forceRender) {
  26065. var Clazz = AxisView.getAxisPointerClass(axisView.axisPointerClass);
  26066. if (!Clazz) {
  26067. return;
  26068. }
  26069. var axisPointerModel = axisPointerModelHelper.getAxisPointerModel(axisModel);
  26070. axisPointerModel
  26071. ? (axisView._axisPointer || (axisView._axisPointer = new Clazz()))
  26072. .render(axisModel, axisPointerModel, api, forceRender)
  26073. : disposeAxisPointer(axisView, api);
  26074. }
  26075. function disposeAxisPointer(axisView, ecModel, api) {
  26076. var axisPointer = axisView._axisPointer;
  26077. axisPointer && axisPointer.dispose(ecModel, api);
  26078. axisView._axisPointer = null;
  26079. }
  26080. var axisPointerClazz = [];
  26081. AxisView.registerAxisPointerClass = function (type, clazz) {
  26082. if (true) {
  26083. if (axisPointerClazz[type]) {
  26084. throw new Error('axisPointer ' + type + ' exists');
  26085. }
  26086. }
  26087. axisPointerClazz[type] = clazz;
  26088. };
  26089. AxisView.getAxisPointerClass = function (type) {
  26090. return type && axisPointerClazz[type];
  26091. };
  26092. module.exports = AxisView;
  26093. /***/ },
  26094. /* 137 */
  26095. /***/ function(module, exports, __webpack_require__) {
  26096. var zrUtil = __webpack_require__(4);
  26097. var Model = __webpack_require__(12);
  26098. var each = zrUtil.each;
  26099. var curry = zrUtil.curry;
  26100. var helper = {};
  26101. // Build axisPointerModel, mergin tooltip.axisPointer model for each axis.
  26102. // allAxesInfo should be updated when setOption performed.
  26103. helper.collect = function (ecModel, api) {
  26104. var result = {
  26105. /**
  26106. * key: makeKey(axis.model)
  26107. * value: {
  26108. * axis,
  26109. * coordSys,
  26110. * axisPointerModel,
  26111. * triggerTooltip,
  26112. * involveSeries,
  26113. * snap,
  26114. * seriesModels,
  26115. * seriesDataCount
  26116. * }
  26117. */
  26118. axesInfo: {},
  26119. seriesInvolved: false,
  26120. /**
  26121. * key: makeKey(coordSys.model)
  26122. * value: Object: key makeKey(axis.model), value: axisInfo
  26123. */
  26124. coordSysAxesInfo: {},
  26125. coordSysMap: {}
  26126. };
  26127. collectAxesInfo(result, ecModel, api);
  26128. // Check seriesInvolved for performance, in case too many series in some chart.
  26129. result.seriesInvolved && collectSeriesInfo(result, ecModel);
  26130. return result;
  26131. };
  26132. function collectAxesInfo(result, ecModel, api) {
  26133. var globalTooltipModel = ecModel.getComponent('tooltip');
  26134. var globalAxisPointerModel = ecModel.getComponent('axisPointer');
  26135. // links can only be set on global.
  26136. var linksOption = globalAxisPointerModel.get('link', true) || [];
  26137. var linkGroups = [];
  26138. // Collect axes info.
  26139. each(api.getCoordinateSystems(), function (coordSys) {
  26140. // Some coordinate system do not support axes, like geo.
  26141. if (!coordSys.axisPointerEnabled) {
  26142. return;
  26143. }
  26144. var coordSysKey = makeKey(coordSys.model);
  26145. var axesInfoInCoordSys = result.coordSysAxesInfo[coordSysKey] = {};
  26146. result.coordSysMap[coordSysKey] = coordSys;
  26147. // Set tooltip (like 'cross') is a convienent way to show axisPointer
  26148. // for user. So we enable seting tooltip on coordSys model.
  26149. var coordSysModel = coordSys.model;
  26150. var baseTooltipModel = coordSysModel.getModel('tooltip', globalTooltipModel);
  26151. each(coordSys.getAxes(), curry(saveTooltipAxisInfo, false, null));
  26152. // If axis tooltip used, choose tooltip axis for each coordSys.
  26153. // Notice this case: coordSys is `grid` but not `cartesian2D` here.
  26154. if (coordSys.getTooltipAxes
  26155. && globalTooltipModel
  26156. // If tooltip.showContent is set as false, tooltip will not
  26157. // show but axisPointer will show as normal.
  26158. && baseTooltipModel.get('show')
  26159. ) {
  26160. // Compatible with previous logic. But series.tooltip.trigger: 'axis'
  26161. // or series.data[n].tooltip.trigger: 'axis' are not support any more.
  26162. var triggerAxis = baseTooltipModel.get('trigger') === 'axis';
  26163. var cross = baseTooltipModel.get('axisPointer.type') === 'cross';
  26164. var tooltipAxes = coordSys.getTooltipAxes(baseTooltipModel.get('axisPointer.axis'));
  26165. if (triggerAxis || cross) {
  26166. each(tooltipAxes.baseAxes, curry(
  26167. saveTooltipAxisInfo, cross ? 'cross' : true, triggerAxis
  26168. ));
  26169. }
  26170. if (cross) {
  26171. each(tooltipAxes.otherAxes, curry(saveTooltipAxisInfo, 'cross', false));
  26172. }
  26173. }
  26174. // fromTooltip: true | false | 'cross'
  26175. // triggerTooltip: true | false | null
  26176. function saveTooltipAxisInfo(fromTooltip, triggerTooltip, axis) {
  26177. var axisPointerModel = axis.model.getModel('axisPointer', globalAxisPointerModel);
  26178. var axisPointerShow = axisPointerModel.get('show');
  26179. if (!axisPointerShow || (
  26180. axisPointerShow === 'auto'
  26181. && !fromTooltip
  26182. && !isHandleTrigger(axisPointerModel)
  26183. )) {
  26184. return;
  26185. }
  26186. if (triggerTooltip == null) {
  26187. triggerTooltip = axisPointerModel.get('triggerTooltip');
  26188. }
  26189. axisPointerModel = fromTooltip
  26190. ? makeAxisPointerModel(
  26191. axis, baseTooltipModel, globalAxisPointerModel, ecModel,
  26192. fromTooltip, triggerTooltip
  26193. )
  26194. : axisPointerModel;
  26195. var snap = axisPointerModel.get('snap');
  26196. var key = makeKey(axis.model);
  26197. var involveSeries = triggerTooltip || snap || axis.type === 'category';
  26198. // If result.axesInfo[key] exist, override it (tooltip has higher priority).
  26199. var axisInfo = result.axesInfo[key] = {
  26200. key: key,
  26201. axis: axis,
  26202. coordSys: coordSys,
  26203. axisPointerModel: axisPointerModel,
  26204. triggerTooltip: triggerTooltip,
  26205. involveSeries: involveSeries,
  26206. snap: snap,
  26207. useHandle: isHandleTrigger(axisPointerModel),
  26208. seriesModels: []
  26209. };
  26210. axesInfoInCoordSys[key] = axisInfo;
  26211. result.seriesInvolved |= involveSeries;
  26212. var groupIndex = getLinkGroupIndex(linksOption, axis);
  26213. if (groupIndex != null) {
  26214. var linkGroup = linkGroups[groupIndex] || (linkGroups[groupIndex] = {axesInfo: {}});
  26215. linkGroup.axesInfo[key] = axisInfo;
  26216. linkGroup.mapper = linksOption[groupIndex].mapper;
  26217. axisInfo.linkGroup = linkGroup;
  26218. }
  26219. }
  26220. });
  26221. }
  26222. function makeAxisPointerModel(
  26223. axis, baseTooltipModel, globalAxisPointerModel, ecModel, fromTooltip, triggerTooltip
  26224. ) {
  26225. var tooltipAxisPointerModel = baseTooltipModel.getModel('axisPointer');
  26226. var volatileOption = {};
  26227. each(
  26228. [
  26229. 'type', 'snap', 'lineStyle', 'shadowStyle', 'label',
  26230. 'animation', 'animationDurationUpdate', 'animationEasingUpdate', 'z'
  26231. ],
  26232. function (field) {
  26233. volatileOption[field] = zrUtil.clone(tooltipAxisPointerModel.get(field));
  26234. }
  26235. );
  26236. // category axis do not auto snap, otherwise some tick that do not
  26237. // has value can not be hovered. value/time/log axis default snap if
  26238. // triggered from tooltip and trigger tooltip.
  26239. volatileOption.snap = axis.type !== 'category' && !!triggerTooltip;
  26240. // Compatibel with previous behavior, tooltip axis do not show label by default.
  26241. // Only these properties can be overrided from tooltip to axisPointer.
  26242. if (tooltipAxisPointerModel.get('type') === 'cross') {
  26243. volatileOption.type = 'line';
  26244. }
  26245. var labelOption = volatileOption.label || (volatileOption.label = {});
  26246. // Follow the convention, do not show label when triggered by tooltip by default.
  26247. labelOption.show == null && (labelOption.show = false);
  26248. if (fromTooltip === 'cross') {
  26249. // When 'cross', both axes show labels.
  26250. labelOption.show = true;
  26251. // If triggerTooltip, this is a base axis, which should better not use cross style
  26252. // (cross style is dashed by default)
  26253. if (!triggerTooltip) {
  26254. var crossStyle = volatileOption.lineStyle = tooltipAxisPointerModel.get('crossStyle');
  26255. crossStyle && zrUtil.defaults(
  26256. labelOption.textStyle || (labelOption.textStyle = {}),
  26257. crossStyle.textStyle
  26258. );
  26259. }
  26260. }
  26261. return axis.model.getModel(
  26262. 'axisPointer',
  26263. new Model(volatileOption, globalAxisPointerModel, ecModel)
  26264. );
  26265. }
  26266. function collectSeriesInfo(result, ecModel) {
  26267. // Prepare data for axis trigger
  26268. ecModel.eachSeries(function (seriesModel) {
  26269. // Notice this case: this coordSys is `cartesian2D` but not `grid`.
  26270. var coordSys = seriesModel.coordinateSystem;
  26271. var seriesTooltipTrigger = seriesModel.get('tooltip.trigger', true);
  26272. if (!coordSys
  26273. || seriesTooltipTrigger === 'none'
  26274. || seriesTooltipTrigger === false
  26275. || seriesTooltipTrigger === 'item'
  26276. || seriesModel.get('axisPointer.show', true) === false
  26277. ) {
  26278. return;
  26279. }
  26280. each(result.coordSysAxesInfo[makeKey(coordSys.model)], function (axisInfo) {
  26281. var axis = axisInfo.axis;
  26282. if (coordSys.getAxis(axis.dim) === axis) {
  26283. axisInfo.seriesModels.push(seriesModel);
  26284. axisInfo.seriesDataCount == null && (axisInfo.seriesDataCount = 0);
  26285. axisInfo.seriesDataCount += seriesModel.getData().count();
  26286. }
  26287. });
  26288. }, this);
  26289. }
  26290. /**
  26291. * For example:
  26292. * {
  26293. * axisPointer: {
  26294. * links: [{
  26295. * xAxisIndex: [2, 4],
  26296. * yAxisIndex: 'all'
  26297. * }, {
  26298. * xAxisId: ['a5', 'a7'],
  26299. * xAxisName: 'xxx'
  26300. * }]
  26301. * }
  26302. * }
  26303. */
  26304. function getLinkGroupIndex(linksOption, axis) {
  26305. var axisModel = axis.model;
  26306. var dim = axis.dim;
  26307. for (var i = 0; i < linksOption.length; i++) {
  26308. var linkOption = linksOption[i] || {};
  26309. if (checkPropInLink(linkOption[dim + 'AxisId'], axisModel.id)
  26310. || checkPropInLink(linkOption[dim + 'AxisIndex'], axisModel.componentIndex)
  26311. || checkPropInLink(linkOption[dim + 'AxisName'], axisModel.name)
  26312. ) {
  26313. return i;
  26314. }
  26315. }
  26316. }
  26317. function checkPropInLink(linkPropValue, axisPropValue) {
  26318. return linkPropValue === 'all'
  26319. || (zrUtil.isArray(linkPropValue) && zrUtil.indexOf(linkPropValue, axisPropValue) >= 0)
  26320. || linkPropValue === axisPropValue;
  26321. }
  26322. helper.fixValue = function (axisModel) {
  26323. var axisInfo = helper.getAxisInfo(axisModel);
  26324. if (!axisInfo) {
  26325. return;
  26326. }
  26327. var axisPointerModel = axisInfo.axisPointerModel;
  26328. var scale = axisInfo.axis.scale;
  26329. var option = axisPointerModel.option;
  26330. var status = axisPointerModel.get('status');
  26331. var value = axisPointerModel.get('value');
  26332. // Parse init value for category and time axis.
  26333. if (value != null) {
  26334. value = scale.parse(value);
  26335. }
  26336. var useHandle = isHandleTrigger(axisPointerModel);
  26337. // If `handle` used, `axisPointer` will always be displayed, so value
  26338. // and status should be initialized.
  26339. if (status == null) {
  26340. option.status = useHandle ? 'show' : 'hide';
  26341. }
  26342. var extent = scale.getExtent().slice();
  26343. extent[0] > extent[1] && extent.reverse();
  26344. if (// Pick a value on axis when initializing.
  26345. value == null
  26346. // If both `handle` and `dataZoom` are used, value may be out of axis extent,
  26347. // where we should re-pick a value to keep `handle` displaying normally.
  26348. || value > extent[1]
  26349. ) {
  26350. // Make handle displayed on the end of the axis when init, which looks better.
  26351. value = extent[1];
  26352. }
  26353. if (value < extent[0]) {
  26354. value = extent[0];
  26355. }
  26356. option.value = value;
  26357. if (useHandle) {
  26358. option.status = axisInfo.axis.scale.isBlank() ? 'hide' : 'show';
  26359. }
  26360. };
  26361. helper.getAxisInfo = function (axisModel) {
  26362. var coordSysAxesInfo = (axisModel.ecModel.getComponent('axisPointer') || {}).coordSysAxesInfo;
  26363. return coordSysAxesInfo && coordSysAxesInfo.axesInfo[makeKey(axisModel)];
  26364. };
  26365. helper.getAxisPointerModel = function (axisModel) {
  26366. var axisInfo = helper.getAxisInfo(axisModel);
  26367. return axisInfo && axisInfo.axisPointerModel;
  26368. };
  26369. function isHandleTrigger(axisPointerModel) {
  26370. return !!axisPointerModel.get('handle.show');
  26371. }
  26372. /**
  26373. * @param {module:echarts/model/Model} model
  26374. * @return {string} unique key
  26375. */
  26376. var makeKey = helper.makeKey = function (model) {
  26377. return model.type + '||' + model.id;
  26378. };
  26379. module.exports = helper;
  26380. /***/ },
  26381. /* 138 */
  26382. /***/ function(module, exports, __webpack_require__) {
  26383. var zrUtil = __webpack_require__(4);
  26384. var helper = {};
  26385. /**
  26386. * @param {Object} opt {labelInside}
  26387. * @return {Object} {
  26388. * position, rotation, labelDirection, labelOffset,
  26389. * tickDirection, labelRotate, labelInterval, z2
  26390. * }
  26391. */
  26392. helper.layout = function (gridModel, axisModel, opt) {
  26393. opt = opt || {};
  26394. var grid = gridModel.coordinateSystem;
  26395. var axis = axisModel.axis;
  26396. var layout = {};
  26397. var rawAxisPosition = axis.position;
  26398. var axisPosition = axis.onZero ? 'onZero' : rawAxisPosition;
  26399. var axisDim = axis.dim;
  26400. // [left, right, top, bottom]
  26401. var rect = grid.getRect();
  26402. var rectBound = [rect.x, rect.x + rect.width, rect.y, rect.y + rect.height];
  26403. var axisOffset = axisModel.get('offset') || 0;
  26404. var posMap = {
  26405. x: { top: rectBound[2] - axisOffset, bottom: rectBound[3] + axisOffset },
  26406. y: { left: rectBound[0] - axisOffset, right: rectBound[1] + axisOffset }
  26407. };
  26408. posMap.x.onZero = Math.max(Math.min(getZero('y'), posMap.x.bottom), posMap.x.top);
  26409. posMap.y.onZero = Math.max(Math.min(getZero('x'), posMap.y.right), posMap.y.left);
  26410. function getZero(dim, val) {
  26411. var theAxis = grid.getAxis(dim);
  26412. return theAxis.toGlobalCoord(theAxis.dataToCoord(0));
  26413. }
  26414. // Axis position
  26415. layout.position = [
  26416. axisDim === 'y' ? posMap.y[axisPosition] : rectBound[0],
  26417. axisDim === 'x' ? posMap.x[axisPosition] : rectBound[3]
  26418. ];
  26419. // Axis rotation
  26420. layout.rotation = Math.PI / 2 * (axisDim === 'x' ? 0 : 1);
  26421. // Tick and label direction, x y is axisDim
  26422. var dirMap = {top: -1, bottom: 1, left: -1, right: 1};
  26423. layout.labelDirection = layout.tickDirection = layout.nameDirection = dirMap[rawAxisPosition];
  26424. layout.labelOffset = axis.onZero ? posMap[axisDim][rawAxisPosition] - posMap[axisDim].onZero : 0;
  26425. if (axisModel.get('axisTick.inside')) {
  26426. layout.tickDirection = -layout.tickDirection;
  26427. }
  26428. if (zrUtil.retrieve(opt.labelInside, axisModel.get('axisLabel.inside'))) {
  26429. layout.labelDirection = -layout.labelDirection;
  26430. }
  26431. // Special label rotation
  26432. var labelRotate = axisModel.get('axisLabel.rotate');
  26433. layout.labelRotate = axisPosition === 'top' ? -labelRotate : labelRotate;
  26434. // label interval when auto mode.
  26435. layout.labelInterval = axis.getLabelInterval();
  26436. // Over splitLine and splitArea
  26437. layout.z2 = 1;
  26438. return layout;
  26439. };
  26440. module.exports = helper;
  26441. /***/ },
  26442. /* 139 */
  26443. /***/ function(module, exports, __webpack_require__) {
  26444. var zrUtil = __webpack_require__(4);
  26445. __webpack_require__(125);
  26446. __webpack_require__(140);
  26447. __webpack_require__(142);
  26448. var barLayoutGrid = __webpack_require__(145);
  26449. var echarts = __webpack_require__(1);
  26450. echarts.registerLayout(zrUtil.curry(barLayoutGrid, 'bar'));
  26451. // Visual coding for legend
  26452. echarts.registerVisual(function (ecModel) {
  26453. ecModel.eachSeriesByType('bar', function (seriesModel) {
  26454. var data = seriesModel.getData();
  26455. data.setVisual('legendSymbol', 'roundRect');
  26456. });
  26457. });
  26458. // In case developer forget to include grid component
  26459. __webpack_require__(124);
  26460. /***/ },
  26461. /* 140 */
  26462. /***/ function(module, exports, __webpack_require__) {
  26463. module.exports = __webpack_require__(141).extend({
  26464. type: 'series.bar',
  26465. dependencies: ['grid', 'polar'],
  26466. brushSelector: 'rect'
  26467. });
  26468. /***/ },
  26469. /* 141 */
  26470. /***/ function(module, exports, __webpack_require__) {
  26471. 'use strict';
  26472. var SeriesModel = __webpack_require__(78);
  26473. var createListFromArray = __webpack_require__(109);
  26474. module.exports = SeriesModel.extend({
  26475. type: 'series.__base_bar__',
  26476. getInitialData: function (option, ecModel) {
  26477. return createListFromArray(option.data, this, ecModel);
  26478. },
  26479. getMarkerPosition: function (value) {
  26480. var coordSys = this.coordinateSystem;
  26481. if (coordSys) {
  26482. // PENDING if clamp ?
  26483. var pt = coordSys.dataToPoint(value, true);
  26484. var data = this.getData();
  26485. var offset = data.getLayout('offset');
  26486. var size = data.getLayout('size');
  26487. var offsetIndex = coordSys.getBaseAxis().isHorizontal() ? 0 : 1;
  26488. pt[offsetIndex] += offset + size / 2;
  26489. return pt;
  26490. }
  26491. return [NaN, NaN];
  26492. },
  26493. defaultOption: {
  26494. zlevel: 0, // 一级层叠
  26495. z: 2, // 二级层叠
  26496. coordinateSystem: 'cartesian2d',
  26497. legendHoverLink: true,
  26498. // stack: null
  26499. // Cartesian coordinate system
  26500. // xAxisIndex: 0,
  26501. // yAxisIndex: 0,
  26502. // 最小高度改为0
  26503. barMinHeight: 0,
  26504. // 最小角度为0,仅对极坐标系下的柱状图有效
  26505. barMinAngle: 0,
  26506. // barMaxWidth: null,
  26507. // 默认自适应
  26508. // barWidth: null,
  26509. // 柱间距离,默认为柱形宽度的30%,可设固定值
  26510. // barGap: '30%',
  26511. // 类目间柱形距离,默认为类目间距的20%,可设固定值
  26512. // barCategoryGap: '20%',
  26513. // label: {
  26514. // normal: {
  26515. // show: false
  26516. // }
  26517. // },
  26518. itemStyle: {
  26519. normal: {
  26520. // color: '各异'
  26521. },
  26522. emphasis: {}
  26523. }
  26524. }
  26525. });
  26526. /***/ },
  26527. /* 142 */
  26528. /***/ function(module, exports, __webpack_require__) {
  26529. 'use strict';
  26530. var zrUtil = __webpack_require__(4);
  26531. var graphic = __webpack_require__(18);
  26532. var helper = __webpack_require__(143);
  26533. var BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'normal', 'barBorderWidth'];
  26534. // FIXME
  26535. // Just for compatible with ec2.
  26536. zrUtil.extend(__webpack_require__(12).prototype, __webpack_require__(144));
  26537. var BarView = __webpack_require__(1).extendChartView({
  26538. type: 'bar',
  26539. render: function (seriesModel, ecModel, api) {
  26540. var coordinateSystemType = seriesModel.get('coordinateSystem');
  26541. if (coordinateSystemType === 'cartesian2d'
  26542. || coordinateSystemType === 'polar'
  26543. ) {
  26544. this._render(seriesModel, ecModel, api);
  26545. }
  26546. else if (true) {
  26547. console.warn('Only cartesian2d and polar supported for bar.');
  26548. }
  26549. return this.group;
  26550. },
  26551. dispose: zrUtil.noop,
  26552. _render: function (seriesModel, ecModel, api) {
  26553. var group = this.group;
  26554. var data = seriesModel.getData();
  26555. var oldData = this._data;
  26556. var coord = seriesModel.coordinateSystem;
  26557. var baseAxis = coord.getBaseAxis();
  26558. var isHorizontalOrRadial;
  26559. if (coord.type === 'cartesian2d') {
  26560. isHorizontalOrRadial = baseAxis.isHorizontal();
  26561. }
  26562. else if (coord.type === 'polar') {
  26563. isHorizontalOrRadial = baseAxis.dim === 'angle';
  26564. }
  26565. var animationModel = seriesModel.isAnimationEnabled() ? seriesModel : null;
  26566. data.diff(oldData)
  26567. .add(function (dataIndex) {
  26568. if (!data.hasValue(dataIndex)) {
  26569. return;
  26570. }
  26571. var itemModel = data.getItemModel(dataIndex);
  26572. var layout = getLayout[coord.type](data, dataIndex, itemModel);
  26573. var el = elementCreator[coord.type](
  26574. data, dataIndex, itemModel, layout, isHorizontalOrRadial, animationModel
  26575. );
  26576. data.setItemGraphicEl(dataIndex, el);
  26577. group.add(el);
  26578. updateStyle(
  26579. el, data, dataIndex, itemModel, layout,
  26580. seriesModel, isHorizontalOrRadial, coord.type === 'polar'
  26581. );
  26582. })
  26583. .update(function (newIndex, oldIndex) {
  26584. var el = oldData.getItemGraphicEl(oldIndex);
  26585. if (!data.hasValue(newIndex)) {
  26586. group.remove(el);
  26587. return;
  26588. }
  26589. var itemModel = data.getItemModel(newIndex);
  26590. var layout = getLayout[coord.type](data, newIndex, itemModel);
  26591. if (el) {
  26592. graphic.updateProps(el, {shape: layout}, animationModel, newIndex);
  26593. }
  26594. else {
  26595. el = elementCreator[coord.type](
  26596. data, newIndex, itemModel, layout, isHorizontalOrRadial, animationModel, true
  26597. );
  26598. }
  26599. data.setItemGraphicEl(newIndex, el);
  26600. // Add back
  26601. group.add(el);
  26602. updateStyle(
  26603. el, data, newIndex, itemModel, layout,
  26604. seriesModel, isHorizontalOrRadial, coord.type === 'polar'
  26605. );
  26606. })
  26607. .remove(function (dataIndex) {
  26608. var el = oldData.getItemGraphicEl(dataIndex);
  26609. if (coord.type === 'cartesian2d') {
  26610. el && removeRect(dataIndex, animationModel, el);
  26611. }
  26612. else {
  26613. el && removeSector(dataIndex, animationModel, el);
  26614. }
  26615. })
  26616. .execute();
  26617. this._data = data;
  26618. },
  26619. remove: function (ecModel, api) {
  26620. var group = this.group;
  26621. var data = this._data;
  26622. if (ecModel.get('animation')) {
  26623. if (data) {
  26624. data.eachItemGraphicEl(function (el) {
  26625. if (el.type === 'sector') {
  26626. removeSector(el.dataIndex, ecModel, el);
  26627. }
  26628. else {
  26629. removeRect(el.dataIndex, ecModel, el);
  26630. }
  26631. });
  26632. }
  26633. }
  26634. else {
  26635. group.removeAll();
  26636. }
  26637. }
  26638. });
  26639. var elementCreator = {
  26640. cartesian2d: function (
  26641. data, dataIndex, itemModel, layout, isHorizontal,
  26642. animationModel, isUpdate
  26643. ) {
  26644. var rect = new graphic.Rect({shape: zrUtil.extend({}, layout)});
  26645. // Animation
  26646. if (animationModel) {
  26647. var rectShape = rect.shape;
  26648. var animateProperty = isHorizontal ? 'height' : 'width';
  26649. var animateTarget = {};
  26650. rectShape[animateProperty] = 0;
  26651. animateTarget[animateProperty] = layout[animateProperty];
  26652. graphic[isUpdate ? 'updateProps' : 'initProps'](rect, {
  26653. shape: animateTarget
  26654. }, animationModel, dataIndex);
  26655. }
  26656. return rect;
  26657. },
  26658. polar: function (
  26659. data, dataIndex, itemModel, layout, isRadial,
  26660. animationModel, isUpdate
  26661. ) {
  26662. var sector = new graphic.Sector({shape: zrUtil.extend({}, layout)});
  26663. // Animation
  26664. if (animationModel) {
  26665. var sectorShape = sector.shape;
  26666. var animateProperty = isRadial ? 'r' : 'endAngle';
  26667. var animateTarget = {};
  26668. sectorShape[animateProperty] = isRadial ? 0 : layout.startAngle;
  26669. animateTarget[animateProperty] = layout[animateProperty];
  26670. graphic[isUpdate ? 'updateProps' : 'initProps'](sector, {
  26671. shape: animateTarget
  26672. }, animationModel, dataIndex);
  26673. }
  26674. return sector;
  26675. }
  26676. };
  26677. function removeRect(dataIndex, animationModel, el) {
  26678. // Not show text when animating
  26679. el.style.text = '';
  26680. graphic.updateProps(el, {
  26681. shape: {
  26682. width: 0
  26683. }
  26684. }, animationModel, dataIndex, function () {
  26685. el.parent && el.parent.remove(el);
  26686. });
  26687. }
  26688. function removeSector(dataIndex, animationModel, el) {
  26689. // Not show text when animating
  26690. el.style.text = '';
  26691. graphic.updateProps(el, {
  26692. shape: {
  26693. r: el.shape.r0
  26694. }
  26695. }, animationModel, dataIndex, function () {
  26696. el.parent && el.parent.remove(el);
  26697. });
  26698. }
  26699. var getLayout = {
  26700. cartesian2d: function (data, dataIndex, itemModel) {
  26701. var layout = data.getItemLayout(dataIndex);
  26702. var fixedLineWidth = getLineWidth(itemModel, layout);
  26703. // fix layout with lineWidth
  26704. var signX = layout.width > 0 ? 1 : -1;
  26705. var signY = layout.height > 0 ? 1 : -1;
  26706. return {
  26707. x: layout.x + signX * fixedLineWidth / 2,
  26708. y: layout.y + signY * fixedLineWidth / 2,
  26709. width: layout.width - signX * fixedLineWidth,
  26710. height: layout.height - signY * fixedLineWidth
  26711. };
  26712. },
  26713. polar: function (data, dataIndex, itemModel) {
  26714. var layout = data.getItemLayout(dataIndex);
  26715. return {
  26716. cx: layout.cx,
  26717. cy: layout.cy,
  26718. r0: layout.r0,
  26719. r: layout.r,
  26720. startAngle: layout.startAngle,
  26721. endAngle: layout.endAngle
  26722. };
  26723. }
  26724. };
  26725. function updateStyle(
  26726. el, data, dataIndex, itemModel, layout, seriesModel, isHorizontal, isPolar
  26727. ) {
  26728. var color = data.getItemVisual(dataIndex, 'color');
  26729. var opacity = data.getItemVisual(dataIndex, 'opacity');
  26730. var itemStyleModel = itemModel.getModel('itemStyle.normal');
  26731. var hoverStyle = itemModel.getModel('itemStyle.emphasis').getBarItemStyle();
  26732. if (!isPolar && isHorizontal) {
  26733. el.setShape('r', itemStyleModel.get('barBorderRadius') || 0);
  26734. }
  26735. el.useStyle(zrUtil.defaults(
  26736. {
  26737. fill: color,
  26738. opacity: opacity
  26739. },
  26740. itemStyleModel.getBarItemStyle()
  26741. ));
  26742. var labelPositionOutside = isHorizontal
  26743. ? (layout.height > 0 ? 'bottom' : 'top')
  26744. : (layout.width > 0 ? 'left' : 'right');
  26745. if (!isPolar) {
  26746. helper.setLabel(
  26747. el.style, hoverStyle, itemModel, color,
  26748. seriesModel, dataIndex, labelPositionOutside
  26749. );
  26750. }
  26751. graphic.setHoverStyle(el, hoverStyle);
  26752. }
  26753. // In case width or height are too small.
  26754. function getLineWidth(itemModel, rawLayout) {
  26755. var lineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0;
  26756. return Math.min(lineWidth, Math.abs(rawLayout.width), Math.abs(rawLayout.height));
  26757. }
  26758. module.exports = BarView;
  26759. /***/ },
  26760. /* 143 */
  26761. /***/ function(module, exports, __webpack_require__) {
  26762. var zrUtil = __webpack_require__(4);
  26763. var graphic = __webpack_require__(18);
  26764. var helper = {};
  26765. helper.setLabel = function (
  26766. normalStyle, hoverStyle, itemModel, color, seriesModel, dataIndex, labelPositionOutside
  26767. ) {
  26768. var labelModel = itemModel.getModel('label.normal');
  26769. var hoverLabelModel = itemModel.getModel('label.emphasis');
  26770. if (labelModel.get('show')) {
  26771. setLabel(
  26772. normalStyle, labelModel, color,
  26773. zrUtil.retrieve(
  26774. seriesModel.getFormattedLabel(dataIndex, 'normal'),
  26775. seriesModel.getRawValue(dataIndex)
  26776. ),
  26777. labelPositionOutside
  26778. );
  26779. }
  26780. else {
  26781. normalStyle.text = '';
  26782. }
  26783. if (hoverLabelModel.get('show')) {
  26784. setLabel(
  26785. hoverStyle, hoverLabelModel, color,
  26786. zrUtil.retrieve(
  26787. seriesModel.getFormattedLabel(dataIndex, 'emphasis'),
  26788. seriesModel.getRawValue(dataIndex)
  26789. ),
  26790. labelPositionOutside
  26791. );
  26792. }
  26793. else {
  26794. hoverStyle.text = '';
  26795. }
  26796. };
  26797. function setLabel(style, model, color, labelText, labelPositionOutside) {
  26798. graphic.setText(style, model, color);
  26799. style.text = labelText;
  26800. if (style.textPosition === 'outside') {
  26801. style.textPosition = labelPositionOutside;
  26802. }
  26803. }
  26804. module.exports = helper;
  26805. /***/ },
  26806. /* 144 */
  26807. /***/ function(module, exports, __webpack_require__) {
  26808. var getBarItemStyle = __webpack_require__(15)(
  26809. [
  26810. ['fill', 'color'],
  26811. ['stroke', 'borderColor'],
  26812. ['lineWidth', 'borderWidth'],
  26813. // Compatitable with 2
  26814. ['stroke', 'barBorderColor'],
  26815. ['lineWidth', 'barBorderWidth'],
  26816. ['opacity'],
  26817. ['shadowBlur'],
  26818. ['shadowOffsetX'],
  26819. ['shadowOffsetY'],
  26820. ['shadowColor']
  26821. ]
  26822. );
  26823. module.exports = {
  26824. getBarItemStyle: function (excludes) {
  26825. var style = getBarItemStyle.call(this, excludes);
  26826. if (this.getBorderLineDash) {
  26827. var lineDash = this.getBorderLineDash();
  26828. lineDash && (style.lineDash = lineDash);
  26829. }
  26830. return style;
  26831. }
  26832. };
  26833. /***/ },
  26834. /* 145 */
  26835. /***/ function(module, exports, __webpack_require__) {
  26836. 'use strict';
  26837. var zrUtil = __webpack_require__(4);
  26838. var numberUtil = __webpack_require__(7);
  26839. var parsePercent = numberUtil.parsePercent;
  26840. var STACK_PREFIX = '__ec_stack_';
  26841. function getSeriesStackId(seriesModel) {
  26842. return seriesModel.get('stack') || STACK_PREFIX + seriesModel.seriesIndex;
  26843. }
  26844. function getAxisKey(axis) {
  26845. return axis.dim + axis.index;
  26846. }
  26847. /**
  26848. * @param {Object} opt
  26849. * @param {module:echarts/coord/Axis} opt.axis Only support category axis currently.
  26850. * @param {number} opt.count Positive interger.
  26851. * @param {number} [opt.barWidth]
  26852. * @param {number} [opt.barMaxWidth]
  26853. * @param {number} [opt.barGap]
  26854. * @param {number} [opt.barCategoryGap]
  26855. * @return {Object} {width, offset, offsetCenter} If axis.type is not 'category', return undefined.
  26856. */
  26857. function getLayoutOnAxis(opt, api) {
  26858. var params = [];
  26859. var baseAxis = opt.axis;
  26860. var axisKey = 'axis0';
  26861. if (baseAxis.type !== 'category') {
  26862. return;
  26863. }
  26864. var bandWidth = baseAxis.getBandWidth();
  26865. for (var i = 0; i < opt.count || 0; i++) {
  26866. params.push(zrUtil.defaults({
  26867. bandWidth: bandWidth,
  26868. axisKey: axisKey,
  26869. stackId: STACK_PREFIX + i
  26870. }, opt));
  26871. }
  26872. var widthAndOffsets = doCalBarWidthAndOffset(params, api);
  26873. var result = [];
  26874. for (var i = 0; i < opt.count; i++) {
  26875. var item = widthAndOffsets[axisKey][STACK_PREFIX + i];
  26876. item.offsetCenter = item.offset + item.width / 2;
  26877. result.push(item);
  26878. }
  26879. return result;
  26880. }
  26881. function calBarWidthAndOffset(barSeries, api) {
  26882. var seriesInfoList = zrUtil.map(barSeries, function (seriesModel) {
  26883. var data = seriesModel.getData();
  26884. var cartesian = seriesModel.coordinateSystem;
  26885. var baseAxis = cartesian.getBaseAxis();
  26886. var axisExtent = baseAxis.getExtent();
  26887. var bandWidth = baseAxis.type === 'category'
  26888. ? baseAxis.getBandWidth()
  26889. : (Math.abs(axisExtent[1] - axisExtent[0]) / data.count());
  26890. var barWidth = parsePercent(
  26891. seriesModel.get('barWidth'), bandWidth
  26892. );
  26893. var barMaxWidth = parsePercent(
  26894. seriesModel.get('barMaxWidth'), bandWidth
  26895. );
  26896. var barGap = seriesModel.get('barGap');
  26897. var barCategoryGap = seriesModel.get('barCategoryGap');
  26898. return {
  26899. bandWidth: bandWidth,
  26900. barWidth: barWidth,
  26901. barMaxWidth: barMaxWidth,
  26902. barGap: barGap,
  26903. barCategoryGap: barCategoryGap,
  26904. axisKey: getAxisKey(baseAxis),
  26905. stackId: getSeriesStackId(seriesModel)
  26906. };
  26907. });
  26908. return doCalBarWidthAndOffset(seriesInfoList, api);
  26909. }
  26910. function doCalBarWidthAndOffset(seriesInfoList, api) {
  26911. // Columns info on each category axis. Key is cartesian name
  26912. var columnsMap = {};
  26913. zrUtil.each(seriesInfoList, function (seriesInfo, idx) {
  26914. var axisKey = seriesInfo.axisKey;
  26915. var bandWidth = seriesInfo.bandWidth;
  26916. var columnsOnAxis = columnsMap[axisKey] || {
  26917. bandWidth: bandWidth,
  26918. remainedWidth: bandWidth,
  26919. autoWidthCount: 0,
  26920. categoryGap: '20%',
  26921. gap: '30%',
  26922. stacks: {}
  26923. };
  26924. var stacks = columnsOnAxis.stacks;
  26925. columnsMap[axisKey] = columnsOnAxis;
  26926. var stackId = seriesInfo.stackId;
  26927. if (!stacks[stackId]) {
  26928. columnsOnAxis.autoWidthCount++;
  26929. }
  26930. stacks[stackId] = stacks[stackId] || {
  26931. width: 0,
  26932. maxWidth: 0
  26933. };
  26934. // Caution: In a single coordinate system, these barGrid attributes
  26935. // will be shared by series. Consider that they have default values,
  26936. // only the attributes set on the last series will work.
  26937. // Do not change this fact unless there will be a break change.
  26938. // TODO
  26939. var barWidth = seriesInfo.barWidth;
  26940. if (barWidth && !stacks[stackId].width) {
  26941. barWidth = Math.min(columnsOnAxis.remainedWidth, barWidth);
  26942. stacks[stackId].width = barWidth;
  26943. columnsOnAxis.remainedWidth -= barWidth;
  26944. }
  26945. var barMaxWidth = seriesInfo.barMaxWidth;
  26946. barMaxWidth && (stacks[stackId].maxWidth = barMaxWidth);
  26947. var barGap = seriesInfo.barGap;
  26948. (barGap != null) && (columnsOnAxis.gap = barGap);
  26949. var barCategoryGap = seriesInfo.barCategoryGap;
  26950. (barCategoryGap != null) && (columnsOnAxis.categoryGap = barCategoryGap);
  26951. });
  26952. var result = {};
  26953. zrUtil.each(columnsMap, function (columnsOnAxis, coordSysName) {
  26954. result[coordSysName] = {};
  26955. var stacks = columnsOnAxis.stacks;
  26956. var bandWidth = columnsOnAxis.bandWidth;
  26957. var categoryGap = parsePercent(columnsOnAxis.categoryGap, bandWidth);
  26958. var barGapPercent = parsePercent(columnsOnAxis.gap, 1);
  26959. var remainedWidth = columnsOnAxis.remainedWidth;
  26960. var autoWidthCount = columnsOnAxis.autoWidthCount;
  26961. var autoWidth = (remainedWidth - categoryGap)
  26962. / (autoWidthCount + (autoWidthCount - 1) * barGapPercent);
  26963. autoWidth = Math.max(autoWidth, 0);
  26964. // Find if any auto calculated bar exceeded maxBarWidth
  26965. zrUtil.each(stacks, function (column, stack) {
  26966. var maxWidth = column.maxWidth;
  26967. if (maxWidth && maxWidth < autoWidth) {
  26968. maxWidth = Math.min(maxWidth, remainedWidth);
  26969. if (column.width) {
  26970. maxWidth = Math.min(maxWidth, column.width);
  26971. }
  26972. remainedWidth -= maxWidth;
  26973. column.width = maxWidth;
  26974. autoWidthCount--;
  26975. }
  26976. });
  26977. // Recalculate width again
  26978. autoWidth = (remainedWidth - categoryGap)
  26979. / (autoWidthCount + (autoWidthCount - 1) * barGapPercent);
  26980. autoWidth = Math.max(autoWidth, 0);
  26981. var widthSum = 0;
  26982. var lastColumn;
  26983. zrUtil.each(stacks, function (column, idx) {
  26984. if (!column.width) {
  26985. column.width = autoWidth;
  26986. }
  26987. lastColumn = column;
  26988. widthSum += column.width * (1 + barGapPercent);
  26989. });
  26990. if (lastColumn) {
  26991. widthSum -= lastColumn.width * barGapPercent;
  26992. }
  26993. var offset = -widthSum / 2;
  26994. zrUtil.each(stacks, function (column, stackId) {
  26995. result[coordSysName][stackId] = result[coordSysName][stackId] || {
  26996. offset: offset,
  26997. width: column.width
  26998. };
  26999. offset += column.width * (1 + barGapPercent);
  27000. });
  27001. });
  27002. return result;
  27003. }
  27004. /**
  27005. * @param {string} seriesType
  27006. * @param {module:echarts/model/Global} ecModel
  27007. * @param {module:echarts/ExtensionAPI} api
  27008. */
  27009. function barLayoutGrid(seriesType, ecModel, api) {
  27010. var barWidthAndOffset = calBarWidthAndOffset(
  27011. zrUtil.filter(
  27012. ecModel.getSeriesByType(seriesType),
  27013. function (seriesModel) {
  27014. return !ecModel.isSeriesFiltered(seriesModel)
  27015. && seriesModel.coordinateSystem
  27016. && seriesModel.coordinateSystem.type === 'cartesian2d';
  27017. }
  27018. )
  27019. );
  27020. var lastStackCoords = {};
  27021. var lastStackCoordsOrigin = {};
  27022. ecModel.eachSeriesByType(seriesType, function (seriesModel) {
  27023. // Check series coordinate, do layout for cartesian2d only
  27024. if (seriesModel.coordinateSystem.type !== 'cartesian2d') {
  27025. return;
  27026. }
  27027. var data = seriesModel.getData();
  27028. var cartesian = seriesModel.coordinateSystem;
  27029. var baseAxis = cartesian.getBaseAxis();
  27030. var stackId = getSeriesStackId(seriesModel);
  27031. var columnLayoutInfo = barWidthAndOffset[getAxisKey(baseAxis)][stackId];
  27032. var columnOffset = columnLayoutInfo.offset;
  27033. var columnWidth = columnLayoutInfo.width;
  27034. var valueAxis = cartesian.getOtherAxis(baseAxis);
  27035. var barMinHeight = seriesModel.get('barMinHeight') || 0;
  27036. var valueAxisStart = baseAxis.onZero
  27037. ? valueAxis.toGlobalCoord(valueAxis.dataToCoord(0))
  27038. : valueAxis.getGlobalExtent()[0];
  27039. var coords = cartesian.dataToPoints(data, true);
  27040. lastStackCoords[stackId] = lastStackCoords[stackId] || [];
  27041. lastStackCoordsOrigin[stackId] = lastStackCoordsOrigin[stackId] || []; // Fix #4243
  27042. data.setLayout({
  27043. offset: columnOffset,
  27044. size: columnWidth
  27045. });
  27046. data.each(valueAxis.dim, function (value, idx) {
  27047. if (isNaN(value)) {
  27048. return;
  27049. }
  27050. if (!lastStackCoords[stackId][idx]) {
  27051. lastStackCoords[stackId][idx] = {
  27052. p: valueAxisStart, // Positive stack
  27053. n: valueAxisStart // Negative stack
  27054. };
  27055. lastStackCoordsOrigin[stackId][idx] = {
  27056. p: valueAxisStart, // Positive stack
  27057. n: valueAxisStart // Negative stack
  27058. };
  27059. }
  27060. var sign = value >= 0 ? 'p' : 'n';
  27061. var coord = coords[idx];
  27062. var lastCoord = lastStackCoords[stackId][idx][sign];
  27063. var lastCoordOrigin = lastStackCoordsOrigin[stackId][idx][sign];
  27064. var x;
  27065. var y;
  27066. var width;
  27067. var height;
  27068. if (valueAxis.isHorizontal()) {
  27069. x = lastCoord;
  27070. y = coord[1] + columnOffset;
  27071. width = coord[0] - lastCoordOrigin;
  27072. height = columnWidth;
  27073. lastStackCoordsOrigin[stackId][idx][sign] += width;
  27074. if (Math.abs(width) < barMinHeight) {
  27075. width = (width < 0 ? -1 : 1) * barMinHeight;
  27076. }
  27077. lastStackCoords[stackId][idx][sign] += width;
  27078. }
  27079. else {
  27080. x = coord[0] + columnOffset;
  27081. y = lastCoord;
  27082. width = columnWidth;
  27083. height = coord[1] - lastCoordOrigin;
  27084. lastStackCoordsOrigin[stackId][idx][sign] += height;
  27085. if (Math.abs(height) < barMinHeight) {
  27086. // Include zero to has a positive bar
  27087. height = (height <= 0 ? -1 : 1) * barMinHeight;
  27088. }
  27089. lastStackCoords[stackId][idx][sign] += height;
  27090. }
  27091. data.setItemLayout(idx, {
  27092. x: x,
  27093. y: y,
  27094. width: width,
  27095. height: height
  27096. });
  27097. }, true);
  27098. }, this);
  27099. }
  27100. barLayoutGrid.getLayoutOnAxis = getLayoutOnAxis;
  27101. module.exports = barLayoutGrid;
  27102. /***/ },
  27103. /* 146 */
  27104. /***/ function(module, exports, __webpack_require__) {
  27105. var zrUtil = __webpack_require__(4);
  27106. var echarts = __webpack_require__(1);
  27107. __webpack_require__(147);
  27108. __webpack_require__(149);
  27109. __webpack_require__(150)('pie', [{
  27110. type: 'pieToggleSelect',
  27111. event: 'pieselectchanged',
  27112. method: 'toggleSelected'
  27113. }, {
  27114. type: 'pieSelect',
  27115. event: 'pieselected',
  27116. method: 'select'
  27117. }, {
  27118. type: 'pieUnSelect',
  27119. event: 'pieunselected',
  27120. method: 'unSelect'
  27121. }]);
  27122. echarts.registerVisual(zrUtil.curry(__webpack_require__(151), 'pie'));
  27123. echarts.registerLayout(zrUtil.curry(
  27124. __webpack_require__(152), 'pie'
  27125. ));
  27126. echarts.registerProcessor(zrUtil.curry(__webpack_require__(154), 'pie'));
  27127. /***/ },
  27128. /* 147 */
  27129. /***/ function(module, exports, __webpack_require__) {
  27130. 'use strict';
  27131. var List = __webpack_require__(98);
  27132. var zrUtil = __webpack_require__(4);
  27133. var modelUtil = __webpack_require__(5);
  27134. var completeDimensions = __webpack_require__(110);
  27135. var dataSelectableMixin = __webpack_require__(148);
  27136. var PieSeries = __webpack_require__(1).extendSeriesModel({
  27137. type: 'series.pie',
  27138. // Overwrite
  27139. init: function (option) {
  27140. PieSeries.superApply(this, 'init', arguments);
  27141. // Enable legend selection for each data item
  27142. // Use a function instead of direct access because data reference may changed
  27143. this.legendDataProvider = function () {
  27144. return this.getRawData();
  27145. };
  27146. this.updateSelectedMap(option.data);
  27147. this._defaultLabelLine(option);
  27148. },
  27149. // Overwrite
  27150. mergeOption: function (newOption) {
  27151. PieSeries.superCall(this, 'mergeOption', newOption);
  27152. this.updateSelectedMap(this.option.data);
  27153. },
  27154. getInitialData: function (option, ecModel) {
  27155. var dimensions = completeDimensions(['value'], option.data);
  27156. var list = new List(dimensions, this);
  27157. list.initData(option.data);
  27158. return list;
  27159. },
  27160. // Overwrite
  27161. getDataParams: function (dataIndex) {
  27162. var data = this.getData();
  27163. var params = PieSeries.superCall(this, 'getDataParams', dataIndex);
  27164. var sum = data.getSum('value');
  27165. // FIXME toFixed?
  27166. //
  27167. // Percent is 0 if sum is 0
  27168. params.percent = !sum ? 0 : +(data.get('value', dataIndex) / sum * 100).toFixed(2);
  27169. params.$vars.push('percent');
  27170. return params;
  27171. },
  27172. _defaultLabelLine: function (option) {
  27173. // Extend labelLine emphasis
  27174. modelUtil.defaultEmphasis(option.labelLine, ['show']);
  27175. var labelLineNormalOpt = option.labelLine.normal;
  27176. var labelLineEmphasisOpt = option.labelLine.emphasis;
  27177. // Not show label line if `label.normal.show = false`
  27178. labelLineNormalOpt.show = labelLineNormalOpt.show
  27179. && option.label.normal.show;
  27180. labelLineEmphasisOpt.show = labelLineEmphasisOpt.show
  27181. && option.label.emphasis.show;
  27182. },
  27183. defaultOption: {
  27184. zlevel: 0,
  27185. z: 2,
  27186. legendHoverLink: true,
  27187. hoverAnimation: true,
  27188. // 默认全局居中
  27189. center: ['50%', '50%'],
  27190. radius: [0, '75%'],
  27191. // 默认顺时针
  27192. clockwise: true,
  27193. startAngle: 90,
  27194. // 最小角度改为0
  27195. minAngle: 0,
  27196. // 选中是扇区偏移量
  27197. selectedOffset: 10,
  27198. // If use strategy to avoid label overlapping
  27199. avoidLabelOverlap: true,
  27200. // 选择模式,默认关闭,可选single,multiple
  27201. // selectedMode: false,
  27202. // 南丁格尔玫瑰图模式,'radius'(半径) | 'area'(面积)
  27203. // roseType: null,
  27204. // If still show when all data zero.
  27205. stillShowZeroSum: true,
  27206. label: {
  27207. normal: {
  27208. // If rotate around circle
  27209. rotate: false,
  27210. show: true,
  27211. // 'outer', 'inside', 'center'
  27212. position: 'outer'
  27213. // formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调
  27214. // textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
  27215. // distance: 当position为inner时有效,为label位置到圆心的距离与圆半径(环状图为内外半径和)的比例系数
  27216. },
  27217. emphasis: {}
  27218. },
  27219. // Enabled when label.normal.position is 'outer'
  27220. labelLine: {
  27221. normal: {
  27222. show: true,
  27223. // 引导线两段中的第一段长度
  27224. length: 15,
  27225. // 引导线两段中的第二段长度
  27226. length2: 15,
  27227. smooth: false,
  27228. lineStyle: {
  27229. // color: 各异,
  27230. width: 1,
  27231. type: 'solid'
  27232. }
  27233. }
  27234. },
  27235. itemStyle: {
  27236. normal: {
  27237. borderWidth: 1
  27238. },
  27239. emphasis: {}
  27240. },
  27241. // Animation type canbe expansion, scale
  27242. animationType: 'expansion',
  27243. animationEasing: 'cubicOut',
  27244. data: []
  27245. }
  27246. });
  27247. zrUtil.mixin(PieSeries, dataSelectableMixin);
  27248. module.exports = PieSeries;
  27249. /***/ },
  27250. /* 148 */
  27251. /***/ function(module, exports, __webpack_require__) {
  27252. /**
  27253. * Data selectable mixin for chart series.
  27254. * To eanble data select, option of series must have `selectedMode`.
  27255. * And each data item will use `selected` to toggle itself selected status
  27256. *
  27257. * @module echarts/chart/helper/DataSelectable
  27258. */
  27259. var zrUtil = __webpack_require__(4);
  27260. module.exports = {
  27261. updateSelectedMap: function (targetList) {
  27262. this._selectTargetMap = zrUtil.reduce(targetList || [], function (targetMap, target) {
  27263. targetMap.set(target.name, target);
  27264. return targetMap;
  27265. }, zrUtil.createHashMap());
  27266. },
  27267. /**
  27268. * @param {string} name
  27269. */
  27270. // PENGING If selectedMode is null ?
  27271. select: function (name) {
  27272. var targetMap = this._selectTargetMap;
  27273. var target = targetMap.get(name);
  27274. var selectedMode = this.get('selectedMode');
  27275. if (selectedMode === 'single') {
  27276. targetMap.each(function (target) {
  27277. target.selected = false;
  27278. });
  27279. }
  27280. target && (target.selected = true);
  27281. },
  27282. /**
  27283. * @param {string} name
  27284. */
  27285. unSelect: function (name) {
  27286. var target = this._selectTargetMap.get(name);
  27287. // var selectedMode = this.get('selectedMode');
  27288. // selectedMode !== 'single' && target && (target.selected = false);
  27289. target && (target.selected = false);
  27290. },
  27291. /**
  27292. * @param {string} name
  27293. */
  27294. toggleSelected: function (name) {
  27295. var target = this._selectTargetMap.get(name);
  27296. if (target != null) {
  27297. this[target.selected ? 'unSelect' : 'select'](name);
  27298. return target.selected;
  27299. }
  27300. },
  27301. /**
  27302. * @param {string} name
  27303. */
  27304. isSelected: function (name) {
  27305. var target = this._selectTargetMap.get(name);
  27306. return target && target.selected;
  27307. }
  27308. };
  27309. /***/ },
  27310. /* 149 */
  27311. /***/ function(module, exports, __webpack_require__) {
  27312. var graphic = __webpack_require__(18);
  27313. var zrUtil = __webpack_require__(4);
  27314. /**
  27315. * @param {module:echarts/model/Series} seriesModel
  27316. * @param {boolean} hasAnimation
  27317. * @inner
  27318. */
  27319. function updateDataSelected(uid, seriesModel, hasAnimation, api) {
  27320. var data = seriesModel.getData();
  27321. var dataIndex = this.dataIndex;
  27322. var name = data.getName(dataIndex);
  27323. var selectedOffset = seriesModel.get('selectedOffset');
  27324. api.dispatchAction({
  27325. type: 'pieToggleSelect',
  27326. from: uid,
  27327. name: name,
  27328. seriesId: seriesModel.id
  27329. });
  27330. data.each(function (idx) {
  27331. toggleItemSelected(
  27332. data.getItemGraphicEl(idx),
  27333. data.getItemLayout(idx),
  27334. seriesModel.isSelected(data.getName(idx)),
  27335. selectedOffset,
  27336. hasAnimation
  27337. );
  27338. });
  27339. }
  27340. /**
  27341. * @param {module:zrender/graphic/Sector} el
  27342. * @param {Object} layout
  27343. * @param {boolean} isSelected
  27344. * @param {number} selectedOffset
  27345. * @param {boolean} hasAnimation
  27346. * @inner
  27347. */
  27348. function toggleItemSelected(el, layout, isSelected, selectedOffset, hasAnimation) {
  27349. var midAngle = (layout.startAngle + layout.endAngle) / 2;
  27350. var dx = Math.cos(midAngle);
  27351. var dy = Math.sin(midAngle);
  27352. var offset = isSelected ? selectedOffset : 0;
  27353. var position = [dx * offset, dy * offset];
  27354. hasAnimation
  27355. // animateTo will stop revious animation like update transition
  27356. ? el.animate()
  27357. .when(200, {
  27358. position: position
  27359. })
  27360. .start('bounceOut')
  27361. : el.attr('position', position);
  27362. }
  27363. /**
  27364. * Piece of pie including Sector, Label, LabelLine
  27365. * @constructor
  27366. * @extends {module:zrender/graphic/Group}
  27367. */
  27368. function PiePiece(data, idx) {
  27369. graphic.Group.call(this);
  27370. var sector = new graphic.Sector({
  27371. z2: 2
  27372. });
  27373. var polyline = new graphic.Polyline();
  27374. var text = new graphic.Text();
  27375. this.add(sector);
  27376. this.add(polyline);
  27377. this.add(text);
  27378. this.updateData(data, idx, true);
  27379. // Hover to change label and labelLine
  27380. function onEmphasis() {
  27381. polyline.ignore = polyline.hoverIgnore;
  27382. text.ignore = text.hoverIgnore;
  27383. }
  27384. function onNormal() {
  27385. polyline.ignore = polyline.normalIgnore;
  27386. text.ignore = text.normalIgnore;
  27387. }
  27388. this.on('emphasis', onEmphasis)
  27389. .on('normal', onNormal)
  27390. .on('mouseover', onEmphasis)
  27391. .on('mouseout', onNormal);
  27392. }
  27393. var piePieceProto = PiePiece.prototype;
  27394. function getLabelStyle(data, idx, state, labelModel, labelPosition) {
  27395. var textStyleModel = labelModel.getModel('textStyle');
  27396. var isLabelInside = labelPosition === 'inside' || labelPosition === 'inner';
  27397. return {
  27398. fill: textStyleModel.getTextColor()
  27399. || (isLabelInside ? '#fff' : data.getItemVisual(idx, 'color')),
  27400. opacity: data.getItemVisual(idx, 'opacity'),
  27401. textFont: textStyleModel.getFont(),
  27402. text: zrUtil.retrieve(
  27403. data.hostModel.getFormattedLabel(idx, state), data.getName(idx)
  27404. )
  27405. };
  27406. }
  27407. piePieceProto.updateData = function (data, idx, firstCreate) {
  27408. var sector = this.childAt(0);
  27409. var seriesModel = data.hostModel;
  27410. var itemModel = data.getItemModel(idx);
  27411. var layout = data.getItemLayout(idx);
  27412. var sectorShape = zrUtil.extend({}, layout);
  27413. sectorShape.label = null;
  27414. if (firstCreate) {
  27415. sector.setShape(sectorShape);
  27416. var animationType = seriesModel.getShallow('animationType');
  27417. if (animationType === 'scale') {
  27418. sector.shape.r = layout.r0;
  27419. graphic.initProps(sector, {
  27420. shape: {
  27421. r: layout.r
  27422. }
  27423. }, seriesModel, idx);
  27424. }
  27425. // Expansion
  27426. else {
  27427. sector.shape.endAngle = layout.startAngle;
  27428. graphic.updateProps(sector, {
  27429. shape: {
  27430. endAngle: layout.endAngle
  27431. }
  27432. }, seriesModel, idx);
  27433. }
  27434. }
  27435. else {
  27436. graphic.updateProps(sector, {
  27437. shape: sectorShape
  27438. }, seriesModel, idx);
  27439. }
  27440. // Update common style
  27441. var itemStyleModel = itemModel.getModel('itemStyle');
  27442. var visualColor = data.getItemVisual(idx, 'color');
  27443. sector.useStyle(
  27444. zrUtil.defaults(
  27445. {
  27446. lineJoin: 'bevel',
  27447. fill: visualColor
  27448. },
  27449. itemStyleModel.getModel('normal').getItemStyle()
  27450. )
  27451. );
  27452. sector.hoverStyle = itemStyleModel.getModel('emphasis').getItemStyle();
  27453. // Toggle selected
  27454. toggleItemSelected(
  27455. this,
  27456. data.getItemLayout(idx),
  27457. itemModel.get('selected'),
  27458. seriesModel.get('selectedOffset'),
  27459. seriesModel.get('animation')
  27460. );
  27461. function onEmphasis() {
  27462. // Sector may has animation of updating data. Force to move to the last frame
  27463. // Or it may stopped on the wrong shape
  27464. sector.stopAnimation(true);
  27465. sector.animateTo({
  27466. shape: {
  27467. r: layout.r + 10
  27468. }
  27469. }, 300, 'elasticOut');
  27470. }
  27471. function onNormal() {
  27472. sector.stopAnimation(true);
  27473. sector.animateTo({
  27474. shape: {
  27475. r: layout.r
  27476. }
  27477. }, 300, 'elasticOut');
  27478. }
  27479. sector.off('mouseover').off('mouseout').off('emphasis').off('normal');
  27480. if (itemModel.get('hoverAnimation') && seriesModel.isAnimationEnabled()) {
  27481. sector
  27482. .on('mouseover', onEmphasis)
  27483. .on('mouseout', onNormal)
  27484. .on('emphasis', onEmphasis)
  27485. .on('normal', onNormal);
  27486. }
  27487. this._updateLabel(data, idx);
  27488. graphic.setHoverStyle(this);
  27489. };
  27490. piePieceProto._updateLabel = function (data, idx) {
  27491. var labelLine = this.childAt(1);
  27492. var labelText = this.childAt(2);
  27493. var seriesModel = data.hostModel;
  27494. var itemModel = data.getItemModel(idx);
  27495. var layout = data.getItemLayout(idx);
  27496. var labelLayout = layout.label;
  27497. var visualColor = data.getItemVisual(idx, 'color');
  27498. graphic.updateProps(labelLine, {
  27499. shape: {
  27500. points: labelLayout.linePoints || [
  27501. [labelLayout.x, labelLayout.y], [labelLayout.x, labelLayout.y], [labelLayout.x, labelLayout.y]
  27502. ]
  27503. }
  27504. }, seriesModel, idx);
  27505. graphic.updateProps(labelText, {
  27506. style: {
  27507. x: labelLayout.x,
  27508. y: labelLayout.y
  27509. }
  27510. }, seriesModel, idx);
  27511. labelText.attr({
  27512. style: {
  27513. textVerticalAlign: labelLayout.verticalAlign,
  27514. textAlign: labelLayout.textAlign,
  27515. textFont: labelLayout.font
  27516. },
  27517. rotation: labelLayout.rotation,
  27518. origin: [labelLayout.x, labelLayout.y],
  27519. z2: 10
  27520. });
  27521. var labelModel = itemModel.getModel('label.normal');
  27522. var labelHoverModel = itemModel.getModel('label.emphasis');
  27523. var labelLineModel = itemModel.getModel('labelLine.normal');
  27524. var labelLineHoverModel = itemModel.getModel('labelLine.emphasis');
  27525. var labelPosition = labelModel.get('position') || labelHoverModel.get('position');
  27526. labelText.setStyle(getLabelStyle(data, idx, 'normal', labelModel, labelPosition));
  27527. labelText.ignore = labelText.normalIgnore = !labelModel.get('show');
  27528. labelText.hoverIgnore = !labelHoverModel.get('show');
  27529. labelLine.ignore = labelLine.normalIgnore = !labelLineModel.get('show');
  27530. labelLine.hoverIgnore = !labelLineHoverModel.get('show');
  27531. // Default use item visual color
  27532. labelLine.setStyle({
  27533. stroke: visualColor,
  27534. opacity: data.getItemVisual(idx, 'opacity')
  27535. });
  27536. labelLine.setStyle(labelLineModel.getModel('lineStyle').getLineStyle());
  27537. labelText.hoverStyle = getLabelStyle(data, idx, 'emphasis', labelHoverModel, labelPosition);
  27538. labelLine.hoverStyle = labelLineHoverModel.getModel('lineStyle').getLineStyle();
  27539. var smooth = labelLineModel.get('smooth');
  27540. if (smooth && smooth === true) {
  27541. smooth = 0.4;
  27542. }
  27543. labelLine.setShape({
  27544. smooth: smooth
  27545. });
  27546. };
  27547. zrUtil.inherits(PiePiece, graphic.Group);
  27548. // Pie view
  27549. var Pie = __webpack_require__(80).extend({
  27550. type: 'pie',
  27551. init: function () {
  27552. var sectorGroup = new graphic.Group();
  27553. this._sectorGroup = sectorGroup;
  27554. },
  27555. render: function (seriesModel, ecModel, api, payload) {
  27556. if (payload && (payload.from === this.uid)) {
  27557. return;
  27558. }
  27559. var data = seriesModel.getData();
  27560. var oldData = this._data;
  27561. var group = this.group;
  27562. var hasAnimation = ecModel.get('animation');
  27563. var isFirstRender = !oldData;
  27564. var animationType = seriesModel.get('animationType');
  27565. var onSectorClick = zrUtil.curry(
  27566. updateDataSelected, this.uid, seriesModel, hasAnimation, api
  27567. );
  27568. var selectedMode = seriesModel.get('selectedMode');
  27569. data.diff(oldData)
  27570. .add(function (idx) {
  27571. var piePiece = new PiePiece(data, idx);
  27572. // Default expansion animation
  27573. if (isFirstRender && animationType !== 'scale') {
  27574. piePiece.eachChild(function (child) {
  27575. child.stopAnimation(true);
  27576. });
  27577. }
  27578. selectedMode && piePiece.on('click', onSectorClick);
  27579. data.setItemGraphicEl(idx, piePiece);
  27580. group.add(piePiece);
  27581. })
  27582. .update(function (newIdx, oldIdx) {
  27583. var piePiece = oldData.getItemGraphicEl(oldIdx);
  27584. piePiece.updateData(data, newIdx);
  27585. piePiece.off('click');
  27586. selectedMode && piePiece.on('click', onSectorClick);
  27587. group.add(piePiece);
  27588. data.setItemGraphicEl(newIdx, piePiece);
  27589. })
  27590. .remove(function (idx) {
  27591. var piePiece = oldData.getItemGraphicEl(idx);
  27592. group.remove(piePiece);
  27593. })
  27594. .execute();
  27595. if (
  27596. hasAnimation && isFirstRender && data.count() > 0
  27597. // Default expansion animation
  27598. && animationType !== 'scale'
  27599. ) {
  27600. var shape = data.getItemLayout(0);
  27601. var r = Math.max(api.getWidth(), api.getHeight()) / 2;
  27602. var removeClipPath = zrUtil.bind(group.removeClipPath, group);
  27603. group.setClipPath(this._createClipPath(
  27604. shape.cx, shape.cy, r, shape.startAngle, shape.clockwise, removeClipPath, seriesModel
  27605. ));
  27606. }
  27607. this._data = data;
  27608. },
  27609. dispose: function () {},
  27610. _createClipPath: function (
  27611. cx, cy, r, startAngle, clockwise, cb, seriesModel
  27612. ) {
  27613. var clipPath = new graphic.Sector({
  27614. shape: {
  27615. cx: cx,
  27616. cy: cy,
  27617. r0: 0,
  27618. r: r,
  27619. startAngle: startAngle,
  27620. endAngle: startAngle,
  27621. clockwise: clockwise
  27622. }
  27623. });
  27624. graphic.initProps(clipPath, {
  27625. shape: {
  27626. endAngle: startAngle + (clockwise ? 1 : -1) * Math.PI * 2
  27627. }
  27628. }, seriesModel, cb);
  27629. return clipPath;
  27630. },
  27631. /**
  27632. * @implement
  27633. */
  27634. containPoint: function (point, seriesModel) {
  27635. var data = seriesModel.getData();
  27636. var itemLayout = data.getItemLayout(0);
  27637. if (itemLayout) {
  27638. var dx = point[0] - itemLayout.cx;
  27639. var dy = point[1] - itemLayout.cy;
  27640. var radius = Math.sqrt(dx * dx + dy * dy);
  27641. return radius <= itemLayout.r && radius >= itemLayout.r0;
  27642. }
  27643. }
  27644. });
  27645. module.exports = Pie;
  27646. /***/ },
  27647. /* 150 */
  27648. /***/ function(module, exports, __webpack_require__) {
  27649. var echarts = __webpack_require__(1);
  27650. var zrUtil = __webpack_require__(4);
  27651. module.exports = function (seriesType, actionInfos) {
  27652. zrUtil.each(actionInfos, function (actionInfo) {
  27653. actionInfo.update = 'updateView';
  27654. /**
  27655. * @payload
  27656. * @property {string} seriesName
  27657. * @property {string} name
  27658. */
  27659. echarts.registerAction(actionInfo, function (payload, ecModel) {
  27660. var selected = {};
  27661. ecModel.eachComponent(
  27662. {mainType: 'series', subType: seriesType, query: payload},
  27663. function (seriesModel) {
  27664. if (seriesModel[actionInfo.method]) {
  27665. seriesModel[actionInfo.method](payload.name);
  27666. }
  27667. var data = seriesModel.getData();
  27668. // Create selected map
  27669. data.each(function (idx) {
  27670. var name = data.getName(idx);
  27671. selected[name] = seriesModel.isSelected(name) || false;
  27672. });
  27673. }
  27674. );
  27675. return {
  27676. name: payload.name,
  27677. selected: selected
  27678. };
  27679. });
  27680. });
  27681. };
  27682. /***/ },
  27683. /* 151 */
  27684. /***/ function(module, exports) {
  27685. // Pick color from palette for each data item.
  27686. // Applicable for charts that require applying color palette
  27687. // in data level (like pie, funnel, chord).
  27688. module.exports = function (seriesType, ecModel) {
  27689. // Pie and funnel may use diferrent scope
  27690. var paletteScope = {};
  27691. ecModel.eachRawSeriesByType(seriesType, function (seriesModel) {
  27692. var dataAll = seriesModel.getRawData();
  27693. var idxMap = {};
  27694. if (!ecModel.isSeriesFiltered(seriesModel)) {
  27695. var data = seriesModel.getData();
  27696. data.each(function (idx) {
  27697. var rawIdx = data.getRawIndex(idx);
  27698. idxMap[rawIdx] = idx;
  27699. });
  27700. dataAll.each(function (rawIdx) {
  27701. var filteredIdx = idxMap[rawIdx];
  27702. // If series.itemStyle.normal.color is a function. itemVisual may be encoded
  27703. var singleDataColor = filteredIdx != null
  27704. && data.getItemVisual(filteredIdx, 'color', true);
  27705. if (!singleDataColor) {
  27706. // FIXME Performance
  27707. var itemModel = dataAll.getItemModel(rawIdx);
  27708. var color = itemModel.get('itemStyle.normal.color')
  27709. || seriesModel.getColorFromPalette(dataAll.getName(rawIdx), paletteScope);
  27710. // Legend may use the visual info in data before processed
  27711. dataAll.setItemVisual(rawIdx, 'color', color);
  27712. // Data is not filtered
  27713. if (filteredIdx != null) {
  27714. data.setItemVisual(filteredIdx, 'color', color);
  27715. }
  27716. }
  27717. else {
  27718. // Set data all color for legend
  27719. dataAll.setItemVisual(rawIdx, 'color', singleDataColor);
  27720. }
  27721. });
  27722. }
  27723. });
  27724. };
  27725. /***/ },
  27726. /* 152 */
  27727. /***/ function(module, exports, __webpack_require__) {
  27728. var numberUtil = __webpack_require__(7);
  27729. var parsePercent = numberUtil.parsePercent;
  27730. var labelLayout = __webpack_require__(153);
  27731. var zrUtil = __webpack_require__(4);
  27732. var PI2 = Math.PI * 2;
  27733. var RADIAN = Math.PI / 180;
  27734. module.exports = function (seriesType, ecModel, api, payload) {
  27735. ecModel.eachSeriesByType(seriesType, function (seriesModel) {
  27736. var center = seriesModel.get('center');
  27737. var radius = seriesModel.get('radius');
  27738. if (!zrUtil.isArray(radius)) {
  27739. radius = [0, radius];
  27740. }
  27741. if (!zrUtil.isArray(center)) {
  27742. center = [center, center];
  27743. }
  27744. var width = api.getWidth();
  27745. var height = api.getHeight();
  27746. var size = Math.min(width, height);
  27747. var cx = parsePercent(center[0], width);
  27748. var cy = parsePercent(center[1], height);
  27749. var r0 = parsePercent(radius[0], size / 2);
  27750. var r = parsePercent(radius[1], size / 2);
  27751. var data = seriesModel.getData();
  27752. var startAngle = -seriesModel.get('startAngle') * RADIAN;
  27753. var minAngle = seriesModel.get('minAngle') * RADIAN;
  27754. var validDataCount = 0;
  27755. data.each('value', function (value) {
  27756. !isNaN(value) && validDataCount++;
  27757. });
  27758. var sum = data.getSum('value');
  27759. // Sum may be 0
  27760. var unitRadian = Math.PI / (sum || validDataCount) * 2;
  27761. var clockwise = seriesModel.get('clockwise');
  27762. var roseType = seriesModel.get('roseType');
  27763. var stillShowZeroSum = seriesModel.get('stillShowZeroSum');
  27764. // [0...max]
  27765. var extent = data.getDataExtent('value');
  27766. extent[0] = 0;
  27767. // In the case some sector angle is smaller than minAngle
  27768. var restAngle = PI2;
  27769. var valueSumLargerThanMinAngle = 0;
  27770. var currentAngle = startAngle;
  27771. var dir = clockwise ? 1 : -1;
  27772. data.each('value', function (value, idx) {
  27773. var angle;
  27774. if (isNaN(value)) {
  27775. data.setItemLayout(idx, {
  27776. angle: NaN,
  27777. startAngle: NaN,
  27778. endAngle: NaN,
  27779. clockwise: clockwise,
  27780. cx: cx,
  27781. cy: cy,
  27782. r0: r0,
  27783. r: roseType
  27784. ? NaN
  27785. : r
  27786. });
  27787. return;
  27788. }
  27789. // FIXME 兼容 2.0 但是 roseType 是 area 的时候才是这样?
  27790. if (roseType !== 'area') {
  27791. angle = (sum === 0 && stillShowZeroSum)
  27792. ? unitRadian : (value * unitRadian);
  27793. }
  27794. else {
  27795. angle = PI2 / validDataCount;
  27796. }
  27797. if (angle < minAngle) {
  27798. angle = minAngle;
  27799. restAngle -= minAngle;
  27800. }
  27801. else {
  27802. valueSumLargerThanMinAngle += value;
  27803. }
  27804. var endAngle = currentAngle + dir * angle;
  27805. data.setItemLayout(idx, {
  27806. angle: angle,
  27807. startAngle: currentAngle,
  27808. endAngle: endAngle,
  27809. clockwise: clockwise,
  27810. cx: cx,
  27811. cy: cy,
  27812. r0: r0,
  27813. r: roseType
  27814. ? numberUtil.linearMap(value, extent, [r0, r])
  27815. : r
  27816. });
  27817. currentAngle = endAngle;
  27818. }, true);
  27819. // Some sector is constrained by minAngle
  27820. // Rest sectors needs recalculate angle
  27821. if (restAngle < PI2 && validDataCount) {
  27822. // Average the angle if rest angle is not enough after all angles is
  27823. // Constrained by minAngle
  27824. if (restAngle <= 1e-3) {
  27825. var angle = PI2 / validDataCount;
  27826. data.each('value', function (value, idx) {
  27827. if (!isNaN(value)) {
  27828. var layout = data.getItemLayout(idx);
  27829. layout.angle = angle;
  27830. layout.startAngle = startAngle + dir * idx * angle;
  27831. layout.endAngle = startAngle + dir * (idx + 1) * angle;
  27832. }
  27833. });
  27834. }
  27835. else {
  27836. unitRadian = restAngle / valueSumLargerThanMinAngle;
  27837. currentAngle = startAngle;
  27838. data.each('value', function (value, idx) {
  27839. if (!isNaN(value)) {
  27840. var layout = data.getItemLayout(idx);
  27841. var angle = layout.angle === minAngle
  27842. ? minAngle : value * unitRadian;
  27843. layout.startAngle = currentAngle;
  27844. layout.endAngle = currentAngle + dir * angle;
  27845. currentAngle += dir * angle;
  27846. }
  27847. });
  27848. }
  27849. }
  27850. labelLayout(seriesModel, r, width, height);
  27851. });
  27852. };
  27853. /***/ },
  27854. /* 153 */
  27855. /***/ function(module, exports, __webpack_require__) {
  27856. 'use strict';
  27857. // FIXME emphasis label position is not same with normal label position
  27858. var textContain = __webpack_require__(8);
  27859. function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight) {
  27860. list.sort(function (a, b) {
  27861. return a.y - b.y;
  27862. });
  27863. // 压
  27864. function shiftDown(start, end, delta, dir) {
  27865. for (var j = start; j < end; j++) {
  27866. list[j].y += delta;
  27867. if (j > start
  27868. && j + 1 < end
  27869. && list[j + 1].y > list[j].y + list[j].height
  27870. ) {
  27871. shiftUp(j, delta / 2);
  27872. return;
  27873. }
  27874. }
  27875. shiftUp(end - 1, delta / 2);
  27876. }
  27877. // 弹
  27878. function shiftUp(end, delta) {
  27879. for (var j = end; j >= 0; j--) {
  27880. list[j].y -= delta;
  27881. if (j > 0
  27882. && list[j].y > list[j - 1].y + list[j - 1].height
  27883. ) {
  27884. break;
  27885. }
  27886. }
  27887. }
  27888. function changeX(list, isDownList, cx, cy, r, dir) {
  27889. var lastDeltaX = dir > 0
  27890. ? isDownList // 右侧
  27891. ? Number.MAX_VALUE // 下
  27892. : 0 // 上
  27893. : isDownList // 左侧
  27894. ? Number.MAX_VALUE // 下
  27895. : 0; // 上
  27896. for (var i = 0, l = list.length; i < l; i++) {
  27897. // Not change x for center label
  27898. if (list[i].position === 'center') {
  27899. continue;
  27900. }
  27901. var deltaY = Math.abs(list[i].y - cy);
  27902. var length = list[i].len;
  27903. var length2 = list[i].len2;
  27904. var deltaX = (deltaY < r + length)
  27905. ? Math.sqrt(
  27906. (r + length + length2) * (r + length + length2)
  27907. - deltaY * deltaY
  27908. )
  27909. : Math.abs(list[i].x - cx);
  27910. if (isDownList && deltaX >= lastDeltaX) {
  27911. // 右下,左下
  27912. deltaX = lastDeltaX - 10;
  27913. }
  27914. if (!isDownList && deltaX <= lastDeltaX) {
  27915. // 右上,左上
  27916. deltaX = lastDeltaX + 10;
  27917. }
  27918. list[i].x = cx + deltaX * dir;
  27919. lastDeltaX = deltaX;
  27920. }
  27921. }
  27922. var lastY = 0;
  27923. var delta;
  27924. var len = list.length;
  27925. var upList = [];
  27926. var downList = [];
  27927. for (var i = 0; i < len; i++) {
  27928. delta = list[i].y - lastY;
  27929. if (delta < 0) {
  27930. shiftDown(i, len, -delta, dir);
  27931. }
  27932. lastY = list[i].y + list[i].height;
  27933. }
  27934. if (viewHeight - lastY < 0) {
  27935. shiftUp(len - 1, lastY - viewHeight);
  27936. }
  27937. for (var i = 0; i < len; i++) {
  27938. if (list[i].y >= cy) {
  27939. downList.push(list[i]);
  27940. }
  27941. else {
  27942. upList.push(list[i]);
  27943. }
  27944. }
  27945. changeX(upList, false, cx, cy, r, dir);
  27946. changeX(downList, true, cx, cy, r, dir);
  27947. }
  27948. function avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight) {
  27949. var leftList = [];
  27950. var rightList = [];
  27951. for (var i = 0; i < labelLayoutList.length; i++) {
  27952. if (labelLayoutList[i].x < cx) {
  27953. leftList.push(labelLayoutList[i]);
  27954. }
  27955. else {
  27956. rightList.push(labelLayoutList[i]);
  27957. }
  27958. }
  27959. adjustSingleSide(rightList, cx, cy, r, 1, viewWidth, viewHeight);
  27960. adjustSingleSide(leftList, cx, cy, r, -1, viewWidth, viewHeight);
  27961. for (var i = 0; i < labelLayoutList.length; i++) {
  27962. var linePoints = labelLayoutList[i].linePoints;
  27963. if (linePoints) {
  27964. var dist = linePoints[1][0] - linePoints[2][0];
  27965. if (labelLayoutList[i].x < cx) {
  27966. linePoints[2][0] = labelLayoutList[i].x + 3;
  27967. }
  27968. else {
  27969. linePoints[2][0] = labelLayoutList[i].x - 3;
  27970. }
  27971. linePoints[1][1] = linePoints[2][1] = labelLayoutList[i].y;
  27972. linePoints[1][0] = linePoints[2][0] + dist;
  27973. }
  27974. }
  27975. }
  27976. module.exports = function (seriesModel, r, viewWidth, viewHeight) {
  27977. var data = seriesModel.getData();
  27978. var labelLayoutList = [];
  27979. var cx;
  27980. var cy;
  27981. var hasLabelRotate = false;
  27982. data.each(function (idx) {
  27983. var layout = data.getItemLayout(idx);
  27984. var itemModel = data.getItemModel(idx);
  27985. var labelModel = itemModel.getModel('label.normal');
  27986. // Use position in normal or emphasis
  27987. var labelPosition = labelModel.get('position') || itemModel.get('label.emphasis.position');
  27988. var labelLineModel = itemModel.getModel('labelLine.normal');
  27989. var labelLineLen = labelLineModel.get('length');
  27990. var labelLineLen2 = labelLineModel.get('length2');
  27991. var midAngle = (layout.startAngle + layout.endAngle) / 2;
  27992. var dx = Math.cos(midAngle);
  27993. var dy = Math.sin(midAngle);
  27994. var textX;
  27995. var textY;
  27996. var linePoints;
  27997. var textAlign;
  27998. cx = layout.cx;
  27999. cy = layout.cy;
  28000. var isLabelInside = labelPosition === 'inside' || labelPosition === 'inner';
  28001. if (labelPosition === 'center') {
  28002. textX = layout.cx;
  28003. textY = layout.cy;
  28004. textAlign = 'center';
  28005. }
  28006. else {
  28007. var x1 = (isLabelInside ? (layout.r + layout.r0) / 2 * dx : layout.r * dx) + cx;
  28008. var y1 = (isLabelInside ? (layout.r + layout.r0) / 2 * dy : layout.r * dy) + cy;
  28009. textX = x1 + dx * 3;
  28010. textY = y1 + dy * 3;
  28011. if (!isLabelInside) {
  28012. // For roseType
  28013. var x2 = x1 + dx * (labelLineLen + r - layout.r);
  28014. var y2 = y1 + dy * (labelLineLen + r - layout.r);
  28015. var x3 = x2 + ((dx < 0 ? -1 : 1) * labelLineLen2);
  28016. var y3 = y2;
  28017. textX = x3 + (dx < 0 ? -5 : 5);
  28018. textY = y3;
  28019. linePoints = [[x1, y1], [x2, y2], [x3, y3]];
  28020. }
  28021. textAlign = isLabelInside ? 'center' : (dx > 0 ? 'left' : 'right');
  28022. }
  28023. var font = labelModel.getModel('textStyle').getFont();
  28024. var labelRotate = labelModel.get('rotate')
  28025. ? (dx < 0 ? -midAngle + Math.PI : -midAngle) : 0;
  28026. var text = seriesModel.getFormattedLabel(idx, 'normal')
  28027. || data.getName(idx);
  28028. var textRect = textContain.getBoundingRect(
  28029. text, font, textAlign, 'top'
  28030. );
  28031. hasLabelRotate = !!labelRotate;
  28032. layout.label = {
  28033. x: textX,
  28034. y: textY,
  28035. position: labelPosition,
  28036. height: textRect.height,
  28037. len: labelLineLen,
  28038. len2: labelLineLen2,
  28039. linePoints: linePoints,
  28040. textAlign: textAlign,
  28041. verticalAlign: 'middle',
  28042. font: font,
  28043. rotation: labelRotate
  28044. };
  28045. // Not layout the inside label
  28046. if (!isLabelInside) {
  28047. labelLayoutList.push(layout.label);
  28048. }
  28049. });
  28050. if (!hasLabelRotate && seriesModel.get('avoidLabelOverlap')) {
  28051. avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight);
  28052. }
  28053. };
  28054. /***/ },
  28055. /* 154 */
  28056. /***/ function(module, exports) {
  28057. module.exports = function (seriesType, ecModel) {
  28058. var legendModels = ecModel.findComponents({
  28059. mainType: 'legend'
  28060. });
  28061. if (!legendModels || !legendModels.length) {
  28062. return;
  28063. }
  28064. ecModel.eachSeriesByType(seriesType, function (series) {
  28065. var data = series.getData();
  28066. data.filterSelf(function (idx) {
  28067. var name = data.getName(idx);
  28068. // If in any legend component the status is not selected.
  28069. for (var i = 0; i < legendModels.length; i++) {
  28070. if (!legendModels[i].isSelected(name)) {
  28071. return false;
  28072. }
  28073. }
  28074. return true;
  28075. }, this);
  28076. }, this);
  28077. };
  28078. /***/ },
  28079. /* 155 */
  28080. /***/ function(module, exports, __webpack_require__) {
  28081. var zrUtil = __webpack_require__(4);
  28082. var echarts = __webpack_require__(1);
  28083. __webpack_require__(156);
  28084. __webpack_require__(157);
  28085. echarts.registerVisual(zrUtil.curry(
  28086. __webpack_require__(121), 'scatter', 'circle', null
  28087. ));
  28088. echarts.registerLayout(zrUtil.curry(
  28089. __webpack_require__(122), 'scatter'
  28090. ));
  28091. // In case developer forget to include grid component
  28092. __webpack_require__(124);
  28093. /***/ },
  28094. /* 156 */
  28095. /***/ function(module, exports, __webpack_require__) {
  28096. 'use strict';
  28097. var createListFromArray = __webpack_require__(109);
  28098. var SeriesModel = __webpack_require__(78);
  28099. module.exports = SeriesModel.extend({
  28100. type: 'series.scatter',
  28101. dependencies: ['grid', 'polar', 'geo', 'singleAxis', 'calendar'],
  28102. getInitialData: function (option, ecModel) {
  28103. return createListFromArray(option.data, this, ecModel);
  28104. },
  28105. brushSelector: 'point',
  28106. defaultOption: {
  28107. coordinateSystem: 'cartesian2d',
  28108. zlevel: 0,
  28109. z: 2,
  28110. legendHoverLink: true,
  28111. hoverAnimation: true,
  28112. // Cartesian coordinate system
  28113. // xAxisIndex: 0,
  28114. // yAxisIndex: 0,
  28115. // Polar coordinate system
  28116. // polarIndex: 0,
  28117. // Geo coordinate system
  28118. // geoIndex: 0,
  28119. // symbol: null, // 图形类型
  28120. symbolSize: 10, // 图形大小,半宽(半径)参数,当图形为方向或菱形则总宽度为symbolSize * 2
  28121. // symbolRotate: null, // 图形旋转控制
  28122. large: false,
  28123. // Available when large is true
  28124. largeThreshold: 2000,
  28125. // label: {
  28126. // normal: {
  28127. // show: false
  28128. // distance: 5,
  28129. // formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调
  28130. // position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
  28131. // 'inside'|'left'|'right'|'top'|'bottom'
  28132. // textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
  28133. // }
  28134. // },
  28135. itemStyle: {
  28136. normal: {
  28137. opacity: 0.8
  28138. // color: 各异
  28139. }
  28140. }
  28141. }
  28142. });
  28143. /***/ },
  28144. /* 157 */
  28145. /***/ function(module, exports, __webpack_require__) {
  28146. var SymbolDraw = __webpack_require__(116);
  28147. var LargeSymbolDraw = __webpack_require__(158);
  28148. __webpack_require__(1).extendChartView({
  28149. type: 'scatter',
  28150. init: function () {
  28151. this._normalSymbolDraw = new SymbolDraw();
  28152. this._largeSymbolDraw = new LargeSymbolDraw();
  28153. },
  28154. render: function (seriesModel, ecModel, api) {
  28155. var data = seriesModel.getData();
  28156. var largeSymbolDraw = this._largeSymbolDraw;
  28157. var normalSymbolDraw = this._normalSymbolDraw;
  28158. var group = this.group;
  28159. var symbolDraw = seriesModel.get('large') && data.count() > seriesModel.get('largeThreshold')
  28160. ? largeSymbolDraw : normalSymbolDraw;
  28161. this._symbolDraw = symbolDraw;
  28162. symbolDraw.updateData(data);
  28163. group.add(symbolDraw.group);
  28164. group.remove(
  28165. symbolDraw === largeSymbolDraw
  28166. ? normalSymbolDraw.group : largeSymbolDraw.group
  28167. );
  28168. },
  28169. updateLayout: function (seriesModel) {
  28170. this._symbolDraw.updateLayout(seriesModel);
  28171. },
  28172. remove: function (ecModel, api) {
  28173. this._symbolDraw && this._symbolDraw.remove(api, true);
  28174. },
  28175. dispose: function () {}
  28176. });
  28177. /***/ },
  28178. /* 158 */
  28179. /***/ function(module, exports, __webpack_require__) {
  28180. // TODO Batch by color
  28181. var graphic = __webpack_require__(18);
  28182. var symbolUtil = __webpack_require__(111);
  28183. var LargeSymbolPath = graphic.extendShape({
  28184. shape: {
  28185. points: null,
  28186. sizes: null
  28187. },
  28188. symbolProxy: null,
  28189. buildPath: function (path, shape) {
  28190. var points = shape.points;
  28191. var sizes = shape.sizes;
  28192. var symbolProxy = this.symbolProxy;
  28193. var symbolProxyShape = symbolProxy.shape;
  28194. for (var i = 0; i < points.length; i++) {
  28195. var pt = points[i];
  28196. var size = sizes[i];
  28197. if (size[0] < 4) {
  28198. // Optimize for small symbol
  28199. path.rect(
  28200. pt[0] - size[0] / 2, pt[1] - size[1] / 2,
  28201. size[0], size[1]
  28202. );
  28203. }
  28204. else {
  28205. symbolProxyShape.x = pt[0] - size[0] / 2;
  28206. symbolProxyShape.y = pt[1] - size[1] / 2;
  28207. symbolProxyShape.width = size[0];
  28208. symbolProxyShape.height = size[1];
  28209. symbolProxy.buildPath(path, symbolProxyShape, true);
  28210. }
  28211. }
  28212. },
  28213. findDataIndex: function (x, y) {
  28214. var shape = this.shape;
  28215. var points = shape.points;
  28216. var sizes = shape.sizes;
  28217. // Not consider transform
  28218. // Treat each element as a rect
  28219. // top down traverse
  28220. for (var i = points.length - 1; i >= 0; i--) {
  28221. var pt = points[i];
  28222. var size = sizes[i];
  28223. var x0 = pt[0] - size[0] / 2;
  28224. var y0 = pt[1] - size[1] / 2;
  28225. if (x >= x0 && y >= y0 && x <= x0 + size[0] && y <= y0 + size[1]) {
  28226. // i is dataIndex
  28227. return i;
  28228. }
  28229. }
  28230. return -1;
  28231. }
  28232. });
  28233. function LargeSymbolDraw() {
  28234. this.group = new graphic.Group();
  28235. this._symbolEl = new LargeSymbolPath({
  28236. // rectHover: true,
  28237. // cursor: 'default'
  28238. });
  28239. }
  28240. var largeSymbolProto = LargeSymbolDraw.prototype;
  28241. /**
  28242. * Update symbols draw by new data
  28243. * @param {module:echarts/data/List} data
  28244. */
  28245. largeSymbolProto.updateData = function (data) {
  28246. this.group.removeAll();
  28247. var symbolEl = this._symbolEl;
  28248. var seriesModel = data.hostModel;
  28249. symbolEl.setShape({
  28250. points: data.mapArray(data.getItemLayout),
  28251. sizes: data.mapArray(
  28252. function (idx) {
  28253. var size = data.getItemVisual(idx, 'symbolSize');
  28254. if (!(size instanceof Array)) {
  28255. size = [size, size];
  28256. }
  28257. return size;
  28258. }
  28259. )
  28260. });
  28261. // Create symbolProxy to build path for each data
  28262. symbolEl.symbolProxy = symbolUtil.createSymbol(
  28263. data.getVisual('symbol'), 0, 0, 0, 0
  28264. );
  28265. // Use symbolProxy setColor method
  28266. symbolEl.setColor = symbolEl.symbolProxy.setColor;
  28267. symbolEl.useStyle(
  28268. seriesModel.getModel('itemStyle.normal').getItemStyle(['color'])
  28269. );
  28270. var visualColor = data.getVisual('color');
  28271. if (visualColor) {
  28272. symbolEl.setColor(visualColor);
  28273. }
  28274. // Enable tooltip
  28275. // PENDING May have performance issue when path is extremely large
  28276. symbolEl.seriesIndex = seriesModel.seriesIndex;
  28277. symbolEl.on('mousemove', function (e) {
  28278. symbolEl.dataIndex = null;
  28279. var dataIndex = symbolEl.findDataIndex(e.offsetX, e.offsetY);
  28280. if (dataIndex > 0) {
  28281. // Provide dataIndex for tooltip
  28282. symbolEl.dataIndex = dataIndex;
  28283. }
  28284. });
  28285. // Add back
  28286. this.group.add(symbolEl);
  28287. };
  28288. largeSymbolProto.updateLayout = function (seriesModel) {
  28289. var data = seriesModel.getData();
  28290. this._symbolEl.setShape({
  28291. points: data.mapArray(data.getItemLayout)
  28292. });
  28293. };
  28294. largeSymbolProto.remove = function () {
  28295. this.group.removeAll();
  28296. };
  28297. module.exports = LargeSymbolDraw;
  28298. /***/ },
  28299. /* 159 */
  28300. /***/ function(module, exports, __webpack_require__) {
  28301. var zrUtil = __webpack_require__(4);
  28302. var echarts = __webpack_require__(1);
  28303. // Must use radar component
  28304. __webpack_require__(160);
  28305. __webpack_require__(165);
  28306. __webpack_require__(166);
  28307. echarts.registerVisual(zrUtil.curry(__webpack_require__(151), 'radar'));
  28308. echarts.registerVisual(zrUtil.curry(
  28309. __webpack_require__(121), 'radar', 'circle', null
  28310. ));
  28311. echarts.registerLayout(__webpack_require__(167));
  28312. echarts.registerProcessor(
  28313. zrUtil.curry(__webpack_require__(154), 'radar')
  28314. );
  28315. echarts.registerPreprocessor(__webpack_require__(168));
  28316. /***/ },
  28317. /* 160 */
  28318. /***/ function(module, exports, __webpack_require__) {
  28319. __webpack_require__(161);
  28320. __webpack_require__(163);
  28321. __webpack_require__(164);
  28322. /***/ },
  28323. /* 161 */
  28324. /***/ function(module, exports, __webpack_require__) {
  28325. // TODO clockwise
  28326. var zrUtil = __webpack_require__(4);
  28327. var IndicatorAxis = __webpack_require__(162);
  28328. var IntervalScale = __webpack_require__(104);
  28329. var numberUtil = __webpack_require__(7);
  28330. var axisHelper = __webpack_require__(101);
  28331. function Radar(radarModel, ecModel, api) {
  28332. this._model = radarModel;
  28333. /**
  28334. * Radar dimensions
  28335. * @type {Array.<string>}
  28336. */
  28337. this.dimensions = [];
  28338. this._indicatorAxes = zrUtil.map(radarModel.getIndicatorModels(), function (indicatorModel, idx) {
  28339. var dim = 'indicator_' + idx;
  28340. var indicatorAxis = new IndicatorAxis(dim, new IntervalScale());
  28341. indicatorAxis.name = indicatorModel.get('name');
  28342. // Inject model and axis
  28343. indicatorAxis.model = indicatorModel;
  28344. indicatorModel.axis = indicatorAxis;
  28345. this.dimensions.push(dim);
  28346. return indicatorAxis;
  28347. }, this);
  28348. this.resize(radarModel, api);
  28349. /**
  28350. * @type {number}
  28351. * @readOnly
  28352. */
  28353. this.cx;
  28354. /**
  28355. * @type {number}
  28356. * @readOnly
  28357. */
  28358. this.cy;
  28359. /**
  28360. * @type {number}
  28361. * @readOnly
  28362. */
  28363. this.r;
  28364. /**
  28365. * @type {number}
  28366. * @readOnly
  28367. */
  28368. this.startAngle;
  28369. }
  28370. Radar.prototype.getIndicatorAxes = function () {
  28371. return this._indicatorAxes;
  28372. };
  28373. Radar.prototype.dataToPoint = function (value, indicatorIndex) {
  28374. var indicatorAxis = this._indicatorAxes[indicatorIndex];
  28375. return this.coordToPoint(indicatorAxis.dataToCoord(value), indicatorIndex);
  28376. };
  28377. Radar.prototype.coordToPoint = function (coord, indicatorIndex) {
  28378. var indicatorAxis = this._indicatorAxes[indicatorIndex];
  28379. var angle = indicatorAxis.angle;
  28380. var x = this.cx + coord * Math.cos(angle);
  28381. var y = this.cy - coord * Math.sin(angle);
  28382. return [x, y];
  28383. };
  28384. Radar.prototype.pointToData = function (pt) {
  28385. var dx = pt[0] - this.cx;
  28386. var dy = pt[1] - this.cy;
  28387. var radius = Math.sqrt(dx * dx + dy * dy);
  28388. dx /= radius;
  28389. dy /= radius;
  28390. var radian = Math.atan2(-dy, dx);
  28391. // Find the closest angle
  28392. // FIXME index can calculated directly
  28393. var minRadianDiff = Infinity;
  28394. var closestAxis;
  28395. var closestAxisIdx = -1;
  28396. for (var i = 0; i < this._indicatorAxes.length; i++) {
  28397. var indicatorAxis = this._indicatorAxes[i];
  28398. var diff = Math.abs(radian - indicatorAxis.angle);
  28399. if (diff < minRadianDiff) {
  28400. closestAxis = indicatorAxis;
  28401. closestAxisIdx = i;
  28402. minRadianDiff = diff;
  28403. }
  28404. }
  28405. return [closestAxisIdx, +(closestAxis && closestAxis.coodToData(radius))];
  28406. };
  28407. Radar.prototype.resize = function (radarModel, api) {
  28408. var center = radarModel.get('center');
  28409. var viewWidth = api.getWidth();
  28410. var viewHeight = api.getHeight();
  28411. var viewSize = Math.min(viewWidth, viewHeight) / 2;
  28412. this.cx = numberUtil.parsePercent(center[0], viewWidth);
  28413. this.cy = numberUtil.parsePercent(center[1], viewHeight);
  28414. this.startAngle = radarModel.get('startAngle') * Math.PI / 180;
  28415. this.r = numberUtil.parsePercent(radarModel.get('radius'), viewSize);
  28416. zrUtil.each(this._indicatorAxes, function (indicatorAxis, idx) {
  28417. indicatorAxis.setExtent(0, this.r);
  28418. var angle = (this.startAngle + idx * Math.PI * 2 / this._indicatorAxes.length);
  28419. // Normalize to [-PI, PI]
  28420. angle = Math.atan2(Math.sin(angle), Math.cos(angle));
  28421. indicatorAxis.angle = angle;
  28422. }, this);
  28423. };
  28424. Radar.prototype.update = function (ecModel, api) {
  28425. var indicatorAxes = this._indicatorAxes;
  28426. var radarModel = this._model;
  28427. zrUtil.each(indicatorAxes, function (indicatorAxis) {
  28428. indicatorAxis.scale.setExtent(Infinity, -Infinity);
  28429. });
  28430. ecModel.eachSeriesByType('radar', function (radarSeries, idx) {
  28431. if (radarSeries.get('coordinateSystem') !== 'radar'
  28432. || ecModel.getComponent('radar', radarSeries.get('radarIndex')) !== radarModel
  28433. ) {
  28434. return;
  28435. }
  28436. var data = radarSeries.getData();
  28437. zrUtil.each(indicatorAxes, function (indicatorAxis) {
  28438. indicatorAxis.scale.unionExtentFromData(data, indicatorAxis.dim);
  28439. });
  28440. }, this);
  28441. var splitNumber = radarModel.get('splitNumber');
  28442. function increaseInterval(interval) {
  28443. var exp10 = Math.pow(10, Math.floor(Math.log(interval) / Math.LN10));
  28444. // Increase interval
  28445. var f = interval / exp10;
  28446. if (f === 2) {
  28447. f = 5;
  28448. }
  28449. else { // f is 2 or 5
  28450. f *= 2;
  28451. }
  28452. return f * exp10;
  28453. }
  28454. // Force all the axis fixing the maxSplitNumber.
  28455. zrUtil.each(indicatorAxes, function (indicatorAxis, idx) {
  28456. var rawExtent = axisHelper.getScaleExtent(indicatorAxis.scale, indicatorAxis.model);
  28457. axisHelper.niceScaleExtent(indicatorAxis.scale, indicatorAxis.model);
  28458. var axisModel = indicatorAxis.model;
  28459. var scale = indicatorAxis.scale;
  28460. var fixedMin = axisModel.getMin();
  28461. var fixedMax = axisModel.getMax();
  28462. var interval = scale.getInterval();
  28463. if (fixedMin != null && fixedMax != null) {
  28464. // User set min, max, divide to get new interval
  28465. // FIXME precision
  28466. scale.setInterval(
  28467. (fixedMax - fixedMin) / splitNumber
  28468. );
  28469. }
  28470. else if (fixedMin != null) {
  28471. var max;
  28472. // User set min, expand extent on the other side
  28473. do {
  28474. max = fixedMin + interval * splitNumber;
  28475. scale.setExtent(+fixedMin, max);
  28476. // Interval must been set after extent
  28477. // FIXME
  28478. scale.setInterval(interval);
  28479. interval = increaseInterval(interval);
  28480. } while (max < rawExtent[1] && isFinite(max) && isFinite(rawExtent[1]));
  28481. }
  28482. else if (fixedMax != null) {
  28483. var min;
  28484. // User set min, expand extent on the other side
  28485. do {
  28486. min = fixedMax - interval * splitNumber;
  28487. scale.setExtent(min, +fixedMax);
  28488. scale.setInterval(interval);
  28489. interval = increaseInterval(interval);
  28490. } while (min > rawExtent[0] && isFinite(min) && isFinite(rawExtent[0]));
  28491. }
  28492. else {
  28493. var nicedSplitNumber = scale.getTicks().length - 1;
  28494. if (nicedSplitNumber > splitNumber) {
  28495. interval = increaseInterval(interval);
  28496. }
  28497. // PENDING
  28498. var center = Math.round((rawExtent[0] + rawExtent[1]) / 2 / interval) * interval;
  28499. var halfSplitNumber = Math.round(splitNumber / 2);
  28500. scale.setExtent(
  28501. numberUtil.round(center - halfSplitNumber * interval),
  28502. numberUtil.round(center + (splitNumber - halfSplitNumber) * interval)
  28503. );
  28504. scale.setInterval(interval);
  28505. }
  28506. });
  28507. };
  28508. /**
  28509. * Radar dimensions is based on the data
  28510. * @type {Array}
  28511. */
  28512. Radar.dimensions = [];
  28513. Radar.create = function (ecModel, api) {
  28514. var radarList = [];
  28515. ecModel.eachComponent('radar', function (radarModel) {
  28516. var radar = new Radar(radarModel, ecModel, api);
  28517. radarList.push(radar);
  28518. radarModel.coordinateSystem = radar;
  28519. });
  28520. ecModel.eachSeriesByType('radar', function (radarSeries) {
  28521. if (radarSeries.get('coordinateSystem') === 'radar') {
  28522. // Inject coordinate system
  28523. radarSeries.coordinateSystem = radarList[radarSeries.get('radarIndex') || 0];
  28524. }
  28525. });
  28526. return radarList;
  28527. };
  28528. __webpack_require__(76).register('radar', Radar);
  28529. module.exports = Radar;
  28530. /***/ },
  28531. /* 162 */
  28532. /***/ function(module, exports, __webpack_require__) {
  28533. var zrUtil = __webpack_require__(4);
  28534. var Axis = __webpack_require__(100);
  28535. function IndicatorAxis(dim, scale, radiusExtent) {
  28536. Axis.call(this, dim, scale, radiusExtent);
  28537. /**
  28538. * Axis type
  28539. * - 'category'
  28540. * - 'value'
  28541. * - 'time'
  28542. * - 'log'
  28543. * @type {string}
  28544. */
  28545. this.type = 'value';
  28546. this.angle = 0;
  28547. /**
  28548. * Indicator name
  28549. * @type {string}
  28550. */
  28551. this.name = '';
  28552. /**
  28553. * @type {module:echarts/model/Model}
  28554. */
  28555. this.model;
  28556. }
  28557. zrUtil.inherits(IndicatorAxis, Axis);
  28558. module.exports = IndicatorAxis;
  28559. /***/ },
  28560. /* 163 */
  28561. /***/ function(module, exports, __webpack_require__) {
  28562. var axisDefault = __webpack_require__(132);
  28563. var valueAxisDefault = axisDefault.valueAxis;
  28564. var Model = __webpack_require__(12);
  28565. var zrUtil = __webpack_require__(4);
  28566. var axisModelCommonMixin = __webpack_require__(112);
  28567. function defaultsShow(opt, show) {
  28568. return zrUtil.defaults({
  28569. show: show
  28570. }, opt);
  28571. }
  28572. var RadarModel = __webpack_require__(1).extendComponentModel({
  28573. type: 'radar',
  28574. optionUpdated: function () {
  28575. var boundaryGap = this.get('boundaryGap');
  28576. var splitNumber = this.get('splitNumber');
  28577. var scale = this.get('scale');
  28578. var axisLine = this.get('axisLine');
  28579. var axisTick = this.get('axisTick');
  28580. var axisLabel = this.get('axisLabel');
  28581. var nameTextStyle = this.get('name.textStyle');
  28582. var showName = this.get('name.show');
  28583. var nameFormatter = this.get('name.formatter');
  28584. var nameGap = this.get('nameGap');
  28585. var triggerEvent = this.get('triggerEvent');
  28586. var indicatorModels = zrUtil.map(this.get('indicator') || [], function (indicatorOpt) {
  28587. // PENDING
  28588. if (indicatorOpt.max != null && indicatorOpt.max > 0 && !indicatorOpt.min) {
  28589. indicatorOpt.min = 0;
  28590. }
  28591. else if (indicatorOpt.min != null && indicatorOpt.min < 0 && !indicatorOpt.max) {
  28592. indicatorOpt.max = 0;
  28593. }
  28594. // Use same configuration
  28595. indicatorOpt = zrUtil.merge(zrUtil.clone(indicatorOpt), {
  28596. boundaryGap: boundaryGap,
  28597. splitNumber: splitNumber,
  28598. scale: scale,
  28599. axisLine: axisLine,
  28600. axisTick: axisTick,
  28601. axisLabel: axisLabel,
  28602. // Competitable with 2 and use text
  28603. name: indicatorOpt.text,
  28604. nameLocation: 'end',
  28605. nameGap: nameGap,
  28606. // min: 0,
  28607. nameTextStyle: nameTextStyle,
  28608. triggerEvent: triggerEvent
  28609. }, false);
  28610. if (!showName) {
  28611. indicatorOpt.name = '';
  28612. }
  28613. if (typeof nameFormatter === 'string') {
  28614. var indName = indicatorOpt.name;
  28615. indicatorOpt.name = nameFormatter.replace('{value}', indName != null ? indName : '');
  28616. }
  28617. else if (typeof nameFormatter === 'function') {
  28618. indicatorOpt.name = nameFormatter(
  28619. indicatorOpt.name, indicatorOpt
  28620. );
  28621. }
  28622. var model = zrUtil.extend(
  28623. new Model(indicatorOpt, null, this.ecModel),
  28624. axisModelCommonMixin
  28625. );
  28626. // For triggerEvent.
  28627. model.mainType = 'radar';
  28628. model.componentIndex = this.componentIndex;
  28629. return model;
  28630. }, this);
  28631. this.getIndicatorModels = function () {
  28632. return indicatorModels;
  28633. };
  28634. },
  28635. defaultOption: {
  28636. zlevel: 0,
  28637. z: 0,
  28638. center: ['50%', '50%'],
  28639. radius: '75%',
  28640. startAngle: 90,
  28641. name: {
  28642. show: true
  28643. // formatter: null
  28644. // textStyle: {}
  28645. },
  28646. boundaryGap: [0, 0],
  28647. splitNumber: 5,
  28648. nameGap: 15,
  28649. scale: false,
  28650. // Polygon or circle
  28651. shape: 'polygon',
  28652. axisLine: zrUtil.merge(
  28653. {
  28654. lineStyle: {
  28655. color: '#bbb'
  28656. }
  28657. },
  28658. valueAxisDefault.axisLine
  28659. ),
  28660. axisLabel: defaultsShow(valueAxisDefault.axisLabel, false),
  28661. axisTick: defaultsShow(valueAxisDefault.axisTick, false),
  28662. splitLine: defaultsShow(valueAxisDefault.splitLine, true),
  28663. splitArea: defaultsShow(valueAxisDefault.splitArea, true),
  28664. // {text, min, max}
  28665. indicator: []
  28666. }
  28667. });
  28668. module.exports = RadarModel;
  28669. /***/ },
  28670. /* 164 */
  28671. /***/ function(module, exports, __webpack_require__) {
  28672. var AxisBuilder = __webpack_require__(135);
  28673. var zrUtil = __webpack_require__(4);
  28674. var graphic = __webpack_require__(18);
  28675. var axisBuilderAttrs = [
  28676. 'axisLine', 'axisLabel', 'axisTick', 'axisName'
  28677. ];
  28678. module.exports = __webpack_require__(1).extendComponentView({
  28679. type: 'radar',
  28680. render: function (radarModel, ecModel, api) {
  28681. var group = this.group;
  28682. group.removeAll();
  28683. this._buildAxes(radarModel);
  28684. this._buildSplitLineAndArea(radarModel);
  28685. },
  28686. _buildAxes: function (radarModel) {
  28687. var radar = radarModel.coordinateSystem;
  28688. var indicatorAxes = radar.getIndicatorAxes();
  28689. var axisBuilders = zrUtil.map(indicatorAxes, function (indicatorAxis) {
  28690. var axisBuilder = new AxisBuilder(indicatorAxis.model, {
  28691. position: [radar.cx, radar.cy],
  28692. rotation: indicatorAxis.angle,
  28693. labelDirection: -1,
  28694. tickDirection: -1,
  28695. nameDirection: 1
  28696. });
  28697. return axisBuilder;
  28698. });
  28699. zrUtil.each(axisBuilders, function (axisBuilder) {
  28700. zrUtil.each(axisBuilderAttrs, axisBuilder.add, axisBuilder);
  28701. this.group.add(axisBuilder.getGroup());
  28702. }, this);
  28703. },
  28704. _buildSplitLineAndArea: function (radarModel) {
  28705. var radar = radarModel.coordinateSystem;
  28706. var indicatorAxes = radar.getIndicatorAxes();
  28707. if (!indicatorAxes.length) {
  28708. return;
  28709. }
  28710. var shape = radarModel.get('shape');
  28711. var splitLineModel = radarModel.getModel('splitLine');
  28712. var splitAreaModel = radarModel.getModel('splitArea');
  28713. var lineStyleModel = splitLineModel.getModel('lineStyle');
  28714. var areaStyleModel = splitAreaModel.getModel('areaStyle');
  28715. var showSplitLine = splitLineModel.get('show');
  28716. var showSplitArea = splitAreaModel.get('show');
  28717. var splitLineColors = lineStyleModel.get('color');
  28718. var splitAreaColors = areaStyleModel.get('color');
  28719. splitLineColors = zrUtil.isArray(splitLineColors) ? splitLineColors : [splitLineColors];
  28720. splitAreaColors = zrUtil.isArray(splitAreaColors) ? splitAreaColors : [splitAreaColors];
  28721. var splitLines = [];
  28722. var splitAreas = [];
  28723. function getColorIndex(areaOrLine, areaOrLineColorList, idx) {
  28724. var colorIndex = idx % areaOrLineColorList.length;
  28725. areaOrLine[colorIndex] = areaOrLine[colorIndex] || [];
  28726. return colorIndex;
  28727. }
  28728. if (shape === 'circle') {
  28729. var ticksRadius = indicatorAxes[0].getTicksCoords();
  28730. var cx = radar.cx;
  28731. var cy = radar.cy;
  28732. for (var i = 0; i < ticksRadius.length; i++) {
  28733. if (showSplitLine) {
  28734. var colorIndex = getColorIndex(splitLines, splitLineColors, i);
  28735. splitLines[colorIndex].push(new graphic.Circle({
  28736. shape: {
  28737. cx: cx,
  28738. cy: cy,
  28739. r: ticksRadius[i]
  28740. }
  28741. }));
  28742. }
  28743. if (showSplitArea && i < ticksRadius.length - 1) {
  28744. var colorIndex = getColorIndex(splitAreas, splitAreaColors, i);
  28745. splitAreas[colorIndex].push(new graphic.Ring({
  28746. shape: {
  28747. cx: cx,
  28748. cy: cy,
  28749. r0: ticksRadius[i],
  28750. r: ticksRadius[i + 1]
  28751. }
  28752. }));
  28753. }
  28754. }
  28755. }
  28756. // Polyyon
  28757. else {
  28758. var realSplitNumber = -1;
  28759. var axesTicksPoints = zrUtil.map(indicatorAxes, function (indicatorAxis, idx) {
  28760. var ticksCoords = indicatorAxis.getTicksCoords();
  28761. realSplitNumber = Math.max(ticksCoords.length - 1, realSplitNumber);
  28762. return zrUtil.map(ticksCoords, function (tickCoord) {
  28763. return radar.coordToPoint(tickCoord, idx);
  28764. });
  28765. });
  28766. var prevPoints = [];
  28767. for (var i = 0; i <= realSplitNumber; i++) {
  28768. var points = [];
  28769. for (var j = 0; j < indicatorAxes.length; j++) {
  28770. points.push(axesTicksPoints[j][i]);
  28771. }
  28772. // Close
  28773. if (points[0]) {
  28774. points.push(points[0].slice());
  28775. }
  28776. else {
  28777. if (true) {
  28778. console.error('Can\'t draw value axis ' + i);
  28779. }
  28780. }
  28781. if (showSplitLine) {
  28782. var colorIndex = getColorIndex(splitLines, splitLineColors, i);
  28783. splitLines[colorIndex].push(new graphic.Polyline({
  28784. shape: {
  28785. points: points
  28786. }
  28787. }));
  28788. }
  28789. if (showSplitArea && prevPoints) {
  28790. var colorIndex = getColorIndex(splitAreas, splitAreaColors, i - 1);
  28791. splitAreas[colorIndex].push(new graphic.Polygon({
  28792. shape: {
  28793. points: points.concat(prevPoints)
  28794. }
  28795. }));
  28796. }
  28797. prevPoints = points.slice().reverse();
  28798. }
  28799. }
  28800. var lineStyle = lineStyleModel.getLineStyle();
  28801. var areaStyle = areaStyleModel.getAreaStyle();
  28802. // Add splitArea before splitLine
  28803. zrUtil.each(splitAreas, function (splitAreas, idx) {
  28804. this.group.add(graphic.mergePath(
  28805. splitAreas, {
  28806. style: zrUtil.defaults({
  28807. stroke: 'none',
  28808. fill: splitAreaColors[idx % splitAreaColors.length]
  28809. }, areaStyle),
  28810. silent: true
  28811. }
  28812. ));
  28813. }, this);
  28814. zrUtil.each(splitLines, function (splitLines, idx) {
  28815. this.group.add(graphic.mergePath(
  28816. splitLines, {
  28817. style: zrUtil.defaults({
  28818. fill: 'none',
  28819. stroke: splitLineColors[idx % splitLineColors.length]
  28820. }, lineStyle),
  28821. silent: true
  28822. }
  28823. ));
  28824. }, this);
  28825. }
  28826. });
  28827. /***/ },
  28828. /* 165 */
  28829. /***/ function(module, exports, __webpack_require__) {
  28830. 'use strict';
  28831. var SeriesModel = __webpack_require__(78);
  28832. var List = __webpack_require__(98);
  28833. var completeDimensions = __webpack_require__(110);
  28834. var zrUtil = __webpack_require__(4);
  28835. var encodeHTML = __webpack_require__(6).encodeHTML;
  28836. var RadarSeries = SeriesModel.extend({
  28837. type: 'series.radar',
  28838. dependencies: ['radar'],
  28839. // Overwrite
  28840. init: function (option) {
  28841. RadarSeries.superApply(this, 'init', arguments);
  28842. // Enable legend selection for each data item
  28843. // Use a function instead of direct access because data reference may changed
  28844. this.legendDataProvider = function () {
  28845. return this.getRawData();
  28846. };
  28847. },
  28848. getInitialData: function (option, ecModel) {
  28849. var data = option.data || [];
  28850. var dimensions = completeDimensions(
  28851. [], data, {extraPrefix: 'indicator_', extraFromZero: true}
  28852. );
  28853. var list = new List(dimensions, this);
  28854. list.initData(data);
  28855. return list;
  28856. },
  28857. formatTooltip: function (dataIndex) {
  28858. var value = this.getRawValue(dataIndex);
  28859. var coordSys = this.coordinateSystem;
  28860. var indicatorAxes = coordSys.getIndicatorAxes();
  28861. var name = this.getData().getName(dataIndex);
  28862. return encodeHTML(name === '' ? this.name : name) + '<br/>'
  28863. + zrUtil.map(indicatorAxes, function (axis, idx) {
  28864. return encodeHTML(axis.name + ' : ' + value[idx]);
  28865. }).join('<br />');
  28866. },
  28867. defaultOption: {
  28868. zlevel: 0,
  28869. z: 2,
  28870. coordinateSystem: 'radar',
  28871. legendHoverLink: true,
  28872. radarIndex: 0,
  28873. lineStyle: {
  28874. normal: {
  28875. width: 2,
  28876. type: 'solid'
  28877. }
  28878. },
  28879. label: {
  28880. normal: {
  28881. position: 'top'
  28882. }
  28883. },
  28884. // areaStyle: {
  28885. // },
  28886. // itemStyle: {}
  28887. symbol: 'emptyCircle',
  28888. symbolSize: 4
  28889. // symbolRotate: null
  28890. }
  28891. });
  28892. module.exports = RadarSeries;
  28893. /***/ },
  28894. /* 166 */
  28895. /***/ function(module, exports, __webpack_require__) {
  28896. var graphic = __webpack_require__(18);
  28897. var zrUtil = __webpack_require__(4);
  28898. var symbolUtil = __webpack_require__(111);
  28899. function normalizeSymbolSize(symbolSize) {
  28900. if (!zrUtil.isArray(symbolSize)) {
  28901. symbolSize = [+symbolSize, +symbolSize];
  28902. }
  28903. return symbolSize;
  28904. }
  28905. module.exports = __webpack_require__(1).extendChartView({
  28906. type: 'radar',
  28907. render: function (seriesModel, ecModel, api) {
  28908. var polar = seriesModel.coordinateSystem;
  28909. var group = this.group;
  28910. var data = seriesModel.getData();
  28911. var oldData = this._data;
  28912. function createSymbol(data, idx) {
  28913. var symbolType = data.getItemVisual(idx, 'symbol') || 'circle';
  28914. var color = data.getItemVisual(idx, 'color');
  28915. if (symbolType === 'none') {
  28916. return;
  28917. }
  28918. var symbolPath = symbolUtil.createSymbol(
  28919. symbolType, -0.5, -0.5, 1, 1, color
  28920. );
  28921. symbolPath.attr({
  28922. style: {
  28923. strokeNoScale: true
  28924. },
  28925. z2: 100,
  28926. scale: normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize'))
  28927. });
  28928. return symbolPath;
  28929. }
  28930. function updateSymbols(oldPoints, newPoints, symbolGroup, data, idx, isInit) {
  28931. // Simply rerender all
  28932. symbolGroup.removeAll();
  28933. for (var i = 0; i < newPoints.length - 1; i++) {
  28934. var symbolPath = createSymbol(data, idx);
  28935. if (symbolPath) {
  28936. symbolPath.__dimIdx = i;
  28937. if (oldPoints[i]) {
  28938. symbolPath.attr('position', oldPoints[i]);
  28939. graphic[isInit ? 'initProps' : 'updateProps'](
  28940. symbolPath, {
  28941. position: newPoints[i]
  28942. }, seriesModel, idx
  28943. );
  28944. }
  28945. else {
  28946. symbolPath.attr('position', newPoints[i]);
  28947. }
  28948. symbolGroup.add(symbolPath);
  28949. }
  28950. }
  28951. }
  28952. function getInitialPoints(points) {
  28953. return zrUtil.map(points, function (pt) {
  28954. return [polar.cx, polar.cy];
  28955. });
  28956. }
  28957. data.diff(oldData)
  28958. .add(function (idx) {
  28959. var points = data.getItemLayout(idx);
  28960. if (!points) {
  28961. return;
  28962. }
  28963. var polygon = new graphic.Polygon();
  28964. var polyline = new graphic.Polyline();
  28965. var target = {
  28966. shape: {
  28967. points: points
  28968. }
  28969. };
  28970. polygon.shape.points = getInitialPoints(points);
  28971. polyline.shape.points = getInitialPoints(points);
  28972. graphic.initProps(polygon, target, seriesModel, idx);
  28973. graphic.initProps(polyline, target, seriesModel, idx);
  28974. var itemGroup = new graphic.Group();
  28975. var symbolGroup = new graphic.Group();
  28976. itemGroup.add(polyline);
  28977. itemGroup.add(polygon);
  28978. itemGroup.add(symbolGroup);
  28979. updateSymbols(
  28980. polyline.shape.points, points, symbolGroup, data, idx, true
  28981. );
  28982. data.setItemGraphicEl(idx, itemGroup);
  28983. })
  28984. .update(function (newIdx, oldIdx) {
  28985. var itemGroup = oldData.getItemGraphicEl(oldIdx);
  28986. var polyline = itemGroup.childAt(0);
  28987. var polygon = itemGroup.childAt(1);
  28988. var symbolGroup = itemGroup.childAt(2);
  28989. var target = {
  28990. shape: {
  28991. points: data.getItemLayout(newIdx)
  28992. }
  28993. };
  28994. if (!target.shape.points) {
  28995. return;
  28996. }
  28997. updateSymbols(
  28998. polyline.shape.points, target.shape.points, symbolGroup, data, newIdx, false
  28999. );
  29000. graphic.updateProps(polyline, target, seriesModel);
  29001. graphic.updateProps(polygon, target, seriesModel);
  29002. data.setItemGraphicEl(newIdx, itemGroup);
  29003. })
  29004. .remove(function (idx) {
  29005. group.remove(oldData.getItemGraphicEl(idx));
  29006. })
  29007. .execute();
  29008. data.eachItemGraphicEl(function (itemGroup, idx) {
  29009. var itemModel = data.getItemModel(idx);
  29010. var polyline = itemGroup.childAt(0);
  29011. var polygon = itemGroup.childAt(1);
  29012. var symbolGroup = itemGroup.childAt(2);
  29013. var color = data.getItemVisual(idx, 'color');
  29014. group.add(itemGroup);
  29015. polyline.useStyle(
  29016. zrUtil.defaults(
  29017. itemModel.getModel('lineStyle.normal').getLineStyle(),
  29018. {
  29019. fill: 'none',
  29020. stroke: color
  29021. }
  29022. )
  29023. );
  29024. polyline.hoverStyle = itemModel.getModel('lineStyle.emphasis').getLineStyle();
  29025. var areaStyleModel = itemModel.getModel('areaStyle.normal');
  29026. var hoverAreaStyleModel = itemModel.getModel('areaStyle.emphasis');
  29027. var polygonIgnore = areaStyleModel.isEmpty() && areaStyleModel.parentModel.isEmpty();
  29028. var hoverPolygonIgnore = hoverAreaStyleModel.isEmpty() && hoverAreaStyleModel.parentModel.isEmpty();
  29029. hoverPolygonIgnore = hoverPolygonIgnore && polygonIgnore;
  29030. polygon.ignore = polygonIgnore;
  29031. polygon.useStyle(
  29032. zrUtil.defaults(
  29033. areaStyleModel.getAreaStyle(),
  29034. {
  29035. fill: color,
  29036. opacity: 0.7
  29037. }
  29038. )
  29039. );
  29040. polygon.hoverStyle = hoverAreaStyleModel.getAreaStyle();
  29041. var itemStyle = itemModel.getModel('itemStyle.normal').getItemStyle(['color']);
  29042. var itemHoverStyle = itemModel.getModel('itemStyle.emphasis').getItemStyle();
  29043. var labelModel = itemModel.getModel('label.normal');
  29044. var labelHoverModel = itemModel.getModel('label.emphasis');
  29045. symbolGroup.eachChild(function (symbolPath) {
  29046. symbolPath.setStyle(itemStyle);
  29047. symbolPath.hoverStyle = zrUtil.clone(itemHoverStyle);
  29048. var defaultText = data.get(data.dimensions[symbolPath.__dimIdx], idx);
  29049. graphic.setText(symbolPath.style, labelModel, color);
  29050. symbolPath.setStyle({
  29051. text: labelModel.get('show') ? zrUtil.retrieve(
  29052. seriesModel.getFormattedLabel(
  29053. idx, 'normal', null, symbolPath.__dimIdx
  29054. ),
  29055. defaultText
  29056. ) : ''
  29057. });
  29058. graphic.setText(symbolPath.hoverStyle, labelHoverModel, color);
  29059. symbolPath.hoverStyle.text = labelHoverModel.get('show') ? zrUtil.retrieve(
  29060. seriesModel.getFormattedLabel(
  29061. idx, 'emphasis', null, symbolPath.__dimIdx
  29062. ),
  29063. defaultText
  29064. ) : '';
  29065. });
  29066. function onEmphasis() {
  29067. polygon.attr('ignore', hoverPolygonIgnore);
  29068. }
  29069. function onNormal() {
  29070. polygon.attr('ignore', polygonIgnore);
  29071. }
  29072. itemGroup.off('mouseover').off('mouseout').off('normal').off('emphasis');
  29073. itemGroup.on('emphasis', onEmphasis)
  29074. .on('mouseover', onEmphasis)
  29075. .on('normal', onNormal)
  29076. .on('mouseout', onNormal);
  29077. graphic.setHoverStyle(itemGroup);
  29078. });
  29079. this._data = data;
  29080. },
  29081. remove: function () {
  29082. this.group.removeAll();
  29083. this._data = null;
  29084. },
  29085. dispose: function () {}
  29086. });
  29087. /***/ },
  29088. /* 167 */
  29089. /***/ function(module, exports) {
  29090. module.exports = function (ecModel) {
  29091. ecModel.eachSeriesByType('radar', function (seriesModel) {
  29092. var data = seriesModel.getData();
  29093. var points = [];
  29094. var coordSys = seriesModel.coordinateSystem;
  29095. if (!coordSys) {
  29096. return;
  29097. }
  29098. function pointsConverter(val, idx) {
  29099. points[idx] = points[idx] || [];
  29100. points[idx][i] = coordSys.dataToPoint(val, i);
  29101. }
  29102. for (var i = 0; i < coordSys.getIndicatorAxes().length; i++) {
  29103. var dim = data.dimensions[i];
  29104. data.each(dim, pointsConverter);
  29105. }
  29106. data.each(function (idx) {
  29107. // Close polygon
  29108. points[idx][0] && points[idx].push(points[idx][0].slice());
  29109. data.setItemLayout(idx, points[idx]);
  29110. });
  29111. });
  29112. };
  29113. /***/ },
  29114. /* 168 */
  29115. /***/ function(module, exports, __webpack_require__) {
  29116. // Backward compat for radar chart in 2
  29117. var zrUtil = __webpack_require__(4);
  29118. module.exports = function (option) {
  29119. var polarOptArr = option.polar;
  29120. if (polarOptArr) {
  29121. if (!zrUtil.isArray(polarOptArr)) {
  29122. polarOptArr = [polarOptArr];
  29123. }
  29124. var polarNotRadar = [];
  29125. zrUtil.each(polarOptArr, function (polarOpt, idx) {
  29126. if (polarOpt.indicator) {
  29127. if (polarOpt.type && !polarOpt.shape) {
  29128. polarOpt.shape = polarOpt.type;
  29129. }
  29130. option.radar = option.radar || [];
  29131. if (!zrUtil.isArray(option.radar)) {
  29132. option.radar = [option.radar];
  29133. }
  29134. option.radar.push(polarOpt);
  29135. }
  29136. else {
  29137. polarNotRadar.push(polarOpt);
  29138. }
  29139. });
  29140. option.polar = polarNotRadar;
  29141. }
  29142. zrUtil.each(option.series, function (seriesOpt) {
  29143. if (seriesOpt.type === 'radar' && seriesOpt.polarIndex) {
  29144. seriesOpt.radarIndex = seriesOpt.polarIndex;
  29145. }
  29146. });
  29147. };
  29148. /***/ },
  29149. /* 169 */
  29150. /***/ function(module, exports, __webpack_require__) {
  29151. var echarts = __webpack_require__(1);
  29152. var PRIORITY = echarts.PRIORITY;
  29153. __webpack_require__(170);
  29154. __webpack_require__(180);
  29155. __webpack_require__(186);
  29156. __webpack_require__(171);
  29157. echarts.registerLayout(__webpack_require__(188));
  29158. echarts.registerVisual(__webpack_require__(189));
  29159. echarts.registerProcessor(PRIORITY.PROCESSOR.STATISTIC, __webpack_require__(190));
  29160. echarts.registerPreprocessor(__webpack_require__(191));
  29161. __webpack_require__(150)('map', [{
  29162. type: 'mapToggleSelect',
  29163. event: 'mapselectchanged',
  29164. method: 'toggleSelected'
  29165. }, {
  29166. type: 'mapSelect',
  29167. event: 'mapselected',
  29168. method: 'select'
  29169. }, {
  29170. type: 'mapUnSelect',
  29171. event: 'mapunselected',
  29172. method: 'unSelect'
  29173. }]);
  29174. /***/ },
  29175. /* 170 */
  29176. /***/ function(module, exports, __webpack_require__) {
  29177. var List = __webpack_require__(98);
  29178. var SeriesModel = __webpack_require__(78);
  29179. var zrUtil = __webpack_require__(4);
  29180. var completeDimensions = __webpack_require__(110);
  29181. var formatUtil = __webpack_require__(6);
  29182. var encodeHTML = formatUtil.encodeHTML;
  29183. var addCommas = formatUtil.addCommas;
  29184. var dataSelectableMixin = __webpack_require__(148);
  29185. var geoCreator = __webpack_require__(171);
  29186. var MapSeries = SeriesModel.extend({
  29187. type: 'series.map',
  29188. dependencies: ['geo'],
  29189. layoutMode: 'box',
  29190. /**
  29191. * Only first map series of same mapType will drawMap
  29192. * @type {boolean}
  29193. */
  29194. needsDrawMap: false,
  29195. /**
  29196. * Group of all map series with same mapType
  29197. * @type {boolean}
  29198. */
  29199. seriesGroup: [],
  29200. init: function (option) {
  29201. option = this._fillOption(option, this.getMapType());
  29202. this.option = option;
  29203. MapSeries.superApply(this, 'init', arguments);
  29204. this.updateSelectedMap(option.data);
  29205. },
  29206. getInitialData: function (option) {
  29207. var dimensions = completeDimensions(['value'], option.data || []);
  29208. var list = new List(dimensions, this);
  29209. list.initData(option.data);
  29210. return list;
  29211. },
  29212. mergeOption: function (newOption) {
  29213. if (newOption.data) {
  29214. newOption = this._fillOption(newOption, this.getMapType());
  29215. }
  29216. MapSeries.superCall(this, 'mergeOption', newOption);
  29217. this.updateSelectedMap(this.option.data);
  29218. },
  29219. /**
  29220. * If no host geo model, return null, which means using a
  29221. * inner exclusive geo model.
  29222. */
  29223. getHostGeoModel: function () {
  29224. var geoIndex = this.option.geoIndex;
  29225. return geoIndex != null
  29226. ? this.dependentModels.geo[geoIndex]
  29227. : null;
  29228. },
  29229. getMapType: function () {
  29230. return (this.getHostGeoModel() || this).option.map;
  29231. },
  29232. _fillOption: function (option, mapName) {
  29233. // Shallow clone
  29234. option = zrUtil.extend({}, option);
  29235. option.data = geoCreator.getFilledRegions(option.data, mapName);
  29236. return option;
  29237. },
  29238. getRawValue: function (dataIndex) {
  29239. // Use value stored in data instead because it is calculated from multiple series
  29240. // FIXME Provide all value of multiple series ?
  29241. return this.getData().get('value', dataIndex);
  29242. },
  29243. /**
  29244. * Get model of region
  29245. * @param {string} name
  29246. * @return {module:echarts/model/Model}
  29247. */
  29248. getRegionModel: function (regionName) {
  29249. var data = this.getData();
  29250. return data.getItemModel(data.indexOfName(regionName));
  29251. },
  29252. /**
  29253. * Map tooltip formatter
  29254. *
  29255. * @param {number} dataIndex
  29256. */
  29257. formatTooltip: function (dataIndex) {
  29258. // FIXME orignalData and data is a bit confusing
  29259. var data = this.getData();
  29260. var formattedValue = addCommas(this.getRawValue(dataIndex));
  29261. var name = data.getName(dataIndex);
  29262. var seriesGroup = this.seriesGroup;
  29263. var seriesNames = [];
  29264. for (var i = 0; i < seriesGroup.length; i++) {
  29265. var otherIndex = seriesGroup[i].originalData.indexOfName(name);
  29266. if (!isNaN(seriesGroup[i].originalData.get('value', otherIndex))) {
  29267. seriesNames.push(
  29268. encodeHTML(seriesGroup[i].name)
  29269. );
  29270. }
  29271. }
  29272. return seriesNames.join(', ') + '<br />'
  29273. + encodeHTML(name + ' : ' + formattedValue);
  29274. },
  29275. /**
  29276. * @implement
  29277. */
  29278. getTooltipPosition: function (dataIndex) {
  29279. if (dataIndex != null) {
  29280. var name = this.getData().getName(dataIndex);
  29281. var geo = this.coordinateSystem;
  29282. var region = geo.getRegion(name);
  29283. return region && geo.dataToPoint(region.center);
  29284. }
  29285. },
  29286. setZoom: function (zoom) {
  29287. this.option.zoom = zoom;
  29288. },
  29289. setCenter: function (center) {
  29290. this.option.center = center;
  29291. },
  29292. defaultOption: {
  29293. // 一级层叠
  29294. zlevel: 0,
  29295. // 二级层叠
  29296. z: 2,
  29297. coordinateSystem: 'geo',
  29298. // map should be explicitly specified since ec3.
  29299. map: '',
  29300. // If `geoIndex` is not specified, a exclusive geo will be
  29301. // created. Otherwise use the specified geo component, and
  29302. // `map` and `mapType` are ignored.
  29303. // geoIndex: 0,
  29304. // 'center' | 'left' | 'right' | 'x%' | {number}
  29305. left: 'center',
  29306. // 'center' | 'top' | 'bottom' | 'x%' | {number}
  29307. top: 'center',
  29308. // right
  29309. // bottom
  29310. // width:
  29311. // height
  29312. // Aspect is width / height. Inited to be geoJson bbox aspect
  29313. // This parameter is used for scale this aspect
  29314. aspectScale: 0.75,
  29315. ///// Layout with center and size
  29316. // If you wan't to put map in a fixed size box with right aspect ratio
  29317. // This two properties may more conveninet
  29318. // layoutCenter: [50%, 50%]
  29319. // layoutSize: 100
  29320. // 数值合并方式,默认加和,可选为:
  29321. // 'sum' | 'average' | 'max' | 'min'
  29322. // mapValueCalculation: 'sum',
  29323. // 地图数值计算结果小数精度
  29324. // mapValuePrecision: 0,
  29325. // 显示图例颜色标识(系列标识的小圆点),图例开启时有效
  29326. showLegendSymbol: true,
  29327. // 选择模式,默认关闭,可选single,multiple
  29328. // selectedMode: false,
  29329. dataRangeHoverLink: true,
  29330. // 是否开启缩放及漫游模式
  29331. // roam: false,
  29332. // Define left-top, right-bottom coords to control view
  29333. // For example, [ [180, 90], [-180, -90] ],
  29334. // higher priority than center and zoom
  29335. boundingCoords: null,
  29336. // Default on center of map
  29337. center: null,
  29338. zoom: 1,
  29339. scaleLimit: null,
  29340. label: {
  29341. normal: {
  29342. show: false,
  29343. textStyle: {
  29344. color: '#000'
  29345. }
  29346. },
  29347. emphasis: {
  29348. show: true,
  29349. textStyle: {
  29350. color: 'rgb(100,0,0)'
  29351. }
  29352. }
  29353. },
  29354. // scaleLimit: null,
  29355. itemStyle: {
  29356. normal: {
  29357. // color: 各异,
  29358. borderWidth: 0.5,
  29359. borderColor: '#444',
  29360. areaColor: '#eee'
  29361. },
  29362. // 也是选中样式
  29363. emphasis: {
  29364. areaColor: 'rgba(255,215,0,0.8)'
  29365. }
  29366. }
  29367. }
  29368. });
  29369. zrUtil.mixin(MapSeries, dataSelectableMixin);
  29370. module.exports = MapSeries;
  29371. /***/ },
  29372. /* 171 */
  29373. /***/ function(module, exports, __webpack_require__) {
  29374. var Geo = __webpack_require__(172);
  29375. var layout = __webpack_require__(71);
  29376. var zrUtil = __webpack_require__(4);
  29377. var numberUtil = __webpack_require__(7);
  29378. var mapDataStores = {};
  29379. /**
  29380. * Resize method bound to the geo
  29381. * @param {module:echarts/coord/geo/GeoModel|module:echarts/chart/map/MapModel} geoModel
  29382. * @param {module:echarts/ExtensionAPI} api
  29383. */
  29384. function resizeGeo (geoModel, api) {
  29385. var boundingCoords = geoModel.get('boundingCoords');
  29386. if (boundingCoords != null) {
  29387. var leftTop = boundingCoords[0];
  29388. var rightBottom = boundingCoords[1];
  29389. if (isNaN(leftTop[0]) || isNaN(leftTop[1]) || isNaN(rightBottom[0]) || isNaN(rightBottom[1])) {
  29390. if (true) {
  29391. console.error('Invalid boundingCoords');
  29392. }
  29393. }
  29394. else {
  29395. this.setBoundingRect(leftTop[0], leftTop[1], rightBottom[0] - leftTop[0], rightBottom[1] - leftTop[1]);
  29396. }
  29397. }
  29398. var rect = this.getBoundingRect();
  29399. var boxLayoutOption;
  29400. var center = geoModel.get('layoutCenter');
  29401. var size = geoModel.get('layoutSize');
  29402. var viewWidth = api.getWidth();
  29403. var viewHeight = api.getHeight();
  29404. var aspectScale = geoModel.get('aspectScale') || 0.75;
  29405. var aspect = rect.width / rect.height * aspectScale;
  29406. var useCenterAndSize = false;
  29407. if (center && size) {
  29408. center = [
  29409. numberUtil.parsePercent(center[0], viewWidth),
  29410. numberUtil.parsePercent(center[1], viewHeight)
  29411. ];
  29412. size = numberUtil.parsePercent(size, Math.min(viewWidth, viewHeight));
  29413. if (!isNaN(center[0]) && !isNaN(center[1]) && !isNaN(size)) {
  29414. useCenterAndSize = true;
  29415. }
  29416. else {
  29417. if (true) {
  29418. console.warn('Given layoutCenter or layoutSize data are invalid. Use left/top/width/height instead.');
  29419. }
  29420. }
  29421. }
  29422. var viewRect;
  29423. if (useCenterAndSize) {
  29424. var viewRect = {};
  29425. if (aspect > 1) {
  29426. // Width is same with size
  29427. viewRect.width = size;
  29428. viewRect.height = size / aspect;
  29429. }
  29430. else {
  29431. viewRect.height = size;
  29432. viewRect.width = size * aspect;
  29433. }
  29434. viewRect.y = center[1] - viewRect.height / 2;
  29435. viewRect.x = center[0] - viewRect.width / 2;
  29436. }
  29437. else {
  29438. // Use left/top/width/height
  29439. boxLayoutOption = geoModel.getBoxLayoutParams();
  29440. // 0.75 rate
  29441. boxLayoutOption.aspect = aspect;
  29442. viewRect = layout.getLayoutRect(boxLayoutOption, {
  29443. width: viewWidth,
  29444. height: viewHeight
  29445. });
  29446. }
  29447. this.setViewRect(viewRect.x, viewRect.y, viewRect.width, viewRect.height);
  29448. this.setCenter(geoModel.get('center'));
  29449. this.setZoom(geoModel.get('zoom'));
  29450. }
  29451. /**
  29452. * @param {module:echarts/coord/Geo} geo
  29453. * @param {module:echarts/model/Model} model
  29454. * @inner
  29455. */
  29456. function setGeoCoords(geo, model) {
  29457. zrUtil.each(model.get('geoCoord'), function (geoCoord, name) {
  29458. geo.addGeoCoord(name, geoCoord);
  29459. });
  29460. }
  29461. if (true) {
  29462. var mapNotExistsError = function (name) {
  29463. console.error('Map ' + name + ' not exists. You can download map file on http://echarts.baidu.com/download-map.html');
  29464. };
  29465. }
  29466. var geoCreator = {
  29467. // For deciding which dimensions to use when creating list data
  29468. dimensions: Geo.prototype.dimensions,
  29469. create: function (ecModel, api) {
  29470. var geoList = [];
  29471. // FIXME Create each time may be slow
  29472. ecModel.eachComponent('geo', function (geoModel, idx) {
  29473. var name = geoModel.get('map');
  29474. var mapData = mapDataStores[name];
  29475. if (true) {
  29476. if (!mapData) {
  29477. mapNotExistsError(name);
  29478. }
  29479. }
  29480. var geo = new Geo(
  29481. name + idx, name,
  29482. mapData && mapData.geoJson, mapData && mapData.specialAreas,
  29483. geoModel.get('nameMap')
  29484. );
  29485. geo.zoomLimit = geoModel.get('scaleLimit');
  29486. geoList.push(geo);
  29487. setGeoCoords(geo, geoModel);
  29488. geoModel.coordinateSystem = geo;
  29489. geo.model = geoModel;
  29490. // Inject resize method
  29491. geo.resize = resizeGeo;
  29492. geo.resize(geoModel, api);
  29493. });
  29494. ecModel.eachSeries(function (seriesModel) {
  29495. var coordSys = seriesModel.get('coordinateSystem');
  29496. if (coordSys === 'geo') {
  29497. var geoIndex = seriesModel.get('geoIndex') || 0;
  29498. seriesModel.coordinateSystem = geoList[geoIndex];
  29499. }
  29500. });
  29501. // If has map series
  29502. var mapModelGroupBySeries = {};
  29503. ecModel.eachSeriesByType('map', function (seriesModel) {
  29504. if (!seriesModel.getHostGeoModel()) {
  29505. var mapType = seriesModel.getMapType();
  29506. mapModelGroupBySeries[mapType] = mapModelGroupBySeries[mapType] || [];
  29507. mapModelGroupBySeries[mapType].push(seriesModel);
  29508. }
  29509. });
  29510. zrUtil.each(mapModelGroupBySeries, function (mapSeries, mapType) {
  29511. var mapData = mapDataStores[mapType];
  29512. if (true) {
  29513. if (!mapData) {
  29514. mapNotExistsError(mapSeries[0].get('map'));
  29515. }
  29516. }
  29517. var nameMapList = zrUtil.map(mapSeries, function (singleMapSeries) {
  29518. return singleMapSeries.get('nameMap');
  29519. });
  29520. var geo = new Geo(
  29521. mapType, mapType,
  29522. mapData && mapData.geoJson, mapData && mapData.specialAreas,
  29523. zrUtil.mergeAll(nameMapList)
  29524. );
  29525. geo.zoomLimit = zrUtil.retrieve.apply(null, zrUtil.map(mapSeries, function (singleMapSeries) {
  29526. return singleMapSeries.get('scaleLimit');
  29527. }));
  29528. geoList.push(geo);
  29529. // Inject resize method
  29530. geo.resize = resizeGeo;
  29531. geo.resize(mapSeries[0], api);
  29532. zrUtil.each(mapSeries, function (singleMapSeries) {
  29533. singleMapSeries.coordinateSystem = geo;
  29534. setGeoCoords(geo, singleMapSeries);
  29535. });
  29536. });
  29537. return geoList;
  29538. },
  29539. /**
  29540. * @param {string} mapName
  29541. * @param {Object|string} geoJson
  29542. * @param {Object} [specialAreas]
  29543. *
  29544. * @example
  29545. * $.get('USA.json', function (geoJson) {
  29546. * echarts.registerMap('USA', geoJson);
  29547. * // Or
  29548. * echarts.registerMap('USA', {
  29549. * geoJson: geoJson,
  29550. * specialAreas: {}
  29551. * })
  29552. * });
  29553. */
  29554. registerMap: function (mapName, geoJson, specialAreas) {
  29555. if (geoJson.geoJson && !geoJson.features) {
  29556. specialAreas = geoJson.specialAreas;
  29557. geoJson = geoJson.geoJson;
  29558. }
  29559. if (typeof geoJson === 'string') {
  29560. geoJson = (typeof JSON !== 'undefined' && JSON.parse)
  29561. ? JSON.parse(geoJson) : (new Function('return (' + geoJson + ');'))();
  29562. }
  29563. mapDataStores[mapName] = {
  29564. geoJson: geoJson,
  29565. specialAreas: specialAreas
  29566. };
  29567. },
  29568. /**
  29569. * @param {string} mapName
  29570. * @return {Object}
  29571. */
  29572. getMap: function (mapName) {
  29573. return mapDataStores[mapName];
  29574. },
  29575. /**
  29576. * Fill given regions array
  29577. * @param {Array.<Object>} originRegionArr
  29578. * @param {string} mapName
  29579. * @return {Array}
  29580. */
  29581. getFilledRegions: function (originRegionArr, mapName) {
  29582. // Not use the original
  29583. var regionsArr = (originRegionArr || []).slice();
  29584. var map = geoCreator.getMap(mapName);
  29585. var geoJson = map && map.geoJson;
  29586. if (!geoJson) {
  29587. if (true) {
  29588. mapNotExistsError(mapName);
  29589. }
  29590. return originRegionArr;
  29591. }
  29592. var dataNameMap = zrUtil.createHashMap();
  29593. var features = geoJson.features;
  29594. for (var i = 0; i < regionsArr.length; i++) {
  29595. dataNameMap.set(regionsArr[i].name, regionsArr[i]);
  29596. }
  29597. for (var i = 0; i < features.length; i++) {
  29598. var name = features[i].properties.name;
  29599. if (!dataNameMap.get(name)) {
  29600. regionsArr.push({
  29601. name: name
  29602. });
  29603. }
  29604. }
  29605. return regionsArr;
  29606. }
  29607. };
  29608. // Inject methods into echarts
  29609. var echarts = __webpack_require__(1);
  29610. echarts.registerMap = geoCreator.registerMap;
  29611. echarts.getMap = geoCreator.getMap;
  29612. echarts.parseGeoJSON = __webpack_require__(173);
  29613. // TODO
  29614. echarts.loadMap = function () {};
  29615. echarts.registerCoordinateSystem('geo', geoCreator);
  29616. module.exports = geoCreator;
  29617. /***/ },
  29618. /* 172 */
  29619. /***/ function(module, exports, __webpack_require__) {
  29620. var parseGeoJson = __webpack_require__(173);
  29621. var zrUtil = __webpack_require__(4);
  29622. var BoundingRect = __webpack_require__(9);
  29623. var View = __webpack_require__(176);
  29624. // Geo fix functions
  29625. var geoFixFuncs = [
  29626. __webpack_require__(177),
  29627. __webpack_require__(178),
  29628. __webpack_require__(179)
  29629. ];
  29630. /**
  29631. * [Geo description]
  29632. * @param {string} name Geo name
  29633. * @param {string} map Map type
  29634. * @param {Object} geoJson
  29635. * @param {Object} [specialAreas]
  29636. * Specify the positioned areas by left, top, width, height
  29637. * @param {Object.<string, string>} [nameMap]
  29638. * Specify name alias
  29639. */
  29640. function Geo(name, map, geoJson, specialAreas, nameMap) {
  29641. View.call(this, name);
  29642. /**
  29643. * Map type
  29644. * @type {string}
  29645. */
  29646. this.map = map;
  29647. this._nameCoordMap = zrUtil.createHashMap();
  29648. this.loadGeoJson(geoJson, specialAreas, nameMap);
  29649. }
  29650. Geo.prototype = {
  29651. constructor: Geo,
  29652. type: 'geo',
  29653. /**
  29654. * @param {Array.<string>}
  29655. * @readOnly
  29656. */
  29657. dimensions: ['lng', 'lat'],
  29658. /**
  29659. * If contain given lng,lat coord
  29660. * @param {Array.<number>}
  29661. * @readOnly
  29662. */
  29663. containCoord: function (coord) {
  29664. var regions = this.regions;
  29665. for (var i = 0; i < regions.length; i++) {
  29666. if (regions[i].contain(coord)) {
  29667. return true;
  29668. }
  29669. }
  29670. return false;
  29671. },
  29672. /**
  29673. * @param {Object} geoJson
  29674. * @param {Object} [specialAreas]
  29675. * Specify the positioned areas by left, top, width, height
  29676. * @param {Object.<string, string>} [nameMap]
  29677. * Specify name alias
  29678. */
  29679. loadGeoJson: function (geoJson, specialAreas, nameMap) {
  29680. // https://jsperf.com/try-catch-performance-overhead
  29681. try {
  29682. this.regions = geoJson ? parseGeoJson(geoJson) : [];
  29683. }
  29684. catch (e) {
  29685. throw 'Invalid geoJson format\n' + e.message;
  29686. }
  29687. specialAreas = specialAreas || {};
  29688. nameMap = nameMap || {};
  29689. var regions = this.regions;
  29690. var regionsMap = zrUtil.createHashMap();
  29691. for (var i = 0; i < regions.length; i++) {
  29692. var regionName = regions[i].name;
  29693. // Try use the alias in nameMap
  29694. regionName = nameMap.hasOwnProperty(regionName) ? nameMap[regionName] : regionName;
  29695. regions[i].name = regionName;
  29696. regionsMap.set(regionName, regions[i]);
  29697. // Add geoJson
  29698. this.addGeoCoord(regionName, regions[i].center);
  29699. // Some area like Alaska in USA map needs to be tansformed
  29700. // to look better
  29701. var specialArea = specialAreas[regionName];
  29702. if (specialArea) {
  29703. regions[i].transformTo(
  29704. specialArea.left, specialArea.top, specialArea.width, specialArea.height
  29705. );
  29706. }
  29707. }
  29708. this._regionsMap = regionsMap;
  29709. this._rect = null;
  29710. zrUtil.each(geoFixFuncs, function (fixFunc) {
  29711. fixFunc(this);
  29712. }, this);
  29713. },
  29714. // Overwrite
  29715. transformTo: function (x, y, width, height) {
  29716. var rect = this.getBoundingRect();
  29717. rect = rect.clone();
  29718. // Longitute is inverted
  29719. rect.y = -rect.y - rect.height;
  29720. var viewTransform = this._viewTransform;
  29721. viewTransform.transform = rect.calculateTransform(
  29722. new BoundingRect(x, y, width, height)
  29723. );
  29724. viewTransform.decomposeTransform();
  29725. var scale = viewTransform.scale;
  29726. scale[1] = -scale[1];
  29727. viewTransform.updateTransform();
  29728. this._updateTransform();
  29729. },
  29730. /**
  29731. * @param {string} name
  29732. * @return {module:echarts/coord/geo/Region}
  29733. */
  29734. getRegion: function (name) {
  29735. return this._regionsMap.get(name);
  29736. },
  29737. getRegionByCoord: function (coord) {
  29738. var regions = this.regions;
  29739. for (var i = 0; i < regions.length; i++) {
  29740. if (regions[i].contain(coord)) {
  29741. return regions[i];
  29742. }
  29743. }
  29744. },
  29745. /**
  29746. * Add geoCoord for indexing by name
  29747. * @param {string} name
  29748. * @param {Array.<number>} geoCoord
  29749. */
  29750. addGeoCoord: function (name, geoCoord) {
  29751. this._nameCoordMap.set(name, geoCoord);
  29752. },
  29753. /**
  29754. * Get geoCoord by name
  29755. * @param {string} name
  29756. * @return {Array.<number>}
  29757. */
  29758. getGeoCoord: function (name) {
  29759. return this._nameCoordMap.get(name);
  29760. },
  29761. // Overwrite
  29762. getBoundingRect: function () {
  29763. if (this._rect) {
  29764. return this._rect;
  29765. }
  29766. var rect;
  29767. var regions = this.regions;
  29768. for (var i = 0; i < regions.length; i++) {
  29769. var regionRect = regions[i].getBoundingRect();
  29770. rect = rect || regionRect.clone();
  29771. rect.union(regionRect);
  29772. }
  29773. // FIXME Always return new ?
  29774. return (this._rect = rect || new BoundingRect(0, 0, 0, 0));
  29775. },
  29776. /**
  29777. * Convert series data to a list of points
  29778. * @param {module:echarts/data/List} data
  29779. * @param {boolean} stack
  29780. * @return {Array}
  29781. * Return list of points. For example:
  29782. * `[[10, 10], [20, 20], [30, 30]]`
  29783. */
  29784. dataToPoints: function (data) {
  29785. var item = [];
  29786. return data.mapArray(['lng', 'lat'], function (lon, lat) {
  29787. item[0] = lon;
  29788. item[1] = lat;
  29789. return this.dataToPoint(item);
  29790. }, this);
  29791. },
  29792. /**
  29793. * @param {string|Array.<number>} data
  29794. * @return {Array.<number>}
  29795. */
  29796. dataToPoint: function (data) {
  29797. if (typeof data === 'string') {
  29798. // Map area name to geoCoord
  29799. data = this.getGeoCoord(data);
  29800. }
  29801. if (data) {
  29802. return View.prototype.dataToPoint.call(this, data);
  29803. }
  29804. },
  29805. /**
  29806. * @inheritDoc
  29807. */
  29808. convertToPixel: zrUtil.curry(doConvert, 'dataToPoint'),
  29809. /**
  29810. * @inheritDoc
  29811. */
  29812. convertFromPixel: zrUtil.curry(doConvert, 'pointToData')
  29813. };
  29814. zrUtil.mixin(Geo, View);
  29815. function doConvert(methodName, ecModel, finder, value) {
  29816. var geoModel = finder.geoModel;
  29817. var seriesModel = finder.seriesModel;
  29818. var coordSys = geoModel
  29819. ? geoModel.coordinateSystem
  29820. : seriesModel
  29821. ? (
  29822. seriesModel.coordinateSystem // For map.
  29823. || (seriesModel.getReferringComponents('geo')[0] || {}).coordinateSystem
  29824. )
  29825. : null;
  29826. return coordSys === this ? coordSys[methodName](value) : null;
  29827. }
  29828. module.exports = Geo;
  29829. /***/ },
  29830. /* 173 */
  29831. /***/ function(module, exports, __webpack_require__) {
  29832. /**
  29833. * Parse and decode geo json
  29834. * @module echarts/coord/geo/parseGeoJson
  29835. */
  29836. var zrUtil = __webpack_require__(4);
  29837. var Region = __webpack_require__(174);
  29838. function decode(json) {
  29839. if (!json.UTF8Encoding) {
  29840. return json;
  29841. }
  29842. var encodeScale = json.UTF8Scale;
  29843. if (encodeScale == null) {
  29844. encodeScale = 1024;
  29845. }
  29846. var features = json.features;
  29847. for (var f = 0; f < features.length; f++) {
  29848. var feature = features[f];
  29849. var geometry = feature.geometry;
  29850. var coordinates = geometry.coordinates;
  29851. var encodeOffsets = geometry.encodeOffsets;
  29852. for (var c = 0; c < coordinates.length; c++) {
  29853. var coordinate = coordinates[c];
  29854. if (geometry.type === 'Polygon') {
  29855. coordinates[c] = decodePolygon(
  29856. coordinate,
  29857. encodeOffsets[c],
  29858. encodeScale
  29859. );
  29860. }
  29861. else if (geometry.type === 'MultiPolygon') {
  29862. for (var c2 = 0; c2 < coordinate.length; c2++) {
  29863. var polygon = coordinate[c2];
  29864. coordinate[c2] = decodePolygon(
  29865. polygon,
  29866. encodeOffsets[c][c2],
  29867. encodeScale
  29868. );
  29869. }
  29870. }
  29871. }
  29872. }
  29873. // Has been decoded
  29874. json.UTF8Encoding = false;
  29875. return json;
  29876. }
  29877. function decodePolygon(coordinate, encodeOffsets, encodeScale) {
  29878. var result = [];
  29879. var prevX = encodeOffsets[0];
  29880. var prevY = encodeOffsets[1];
  29881. for (var i = 0; i < coordinate.length; i += 2) {
  29882. var x = coordinate.charCodeAt(i) - 64;
  29883. var y = coordinate.charCodeAt(i + 1) - 64;
  29884. // ZigZag decoding
  29885. x = (x >> 1) ^ (-(x & 1));
  29886. y = (y >> 1) ^ (-(y & 1));
  29887. // Delta deocding
  29888. x += prevX;
  29889. y += prevY;
  29890. prevX = x;
  29891. prevY = y;
  29892. // Dequantize
  29893. result.push([x / encodeScale, y / encodeScale]);
  29894. }
  29895. return result;
  29896. }
  29897. /**
  29898. * @alias module:echarts/coord/geo/parseGeoJson
  29899. * @param {Object} geoJson
  29900. * @return {module:zrender/container/Group}
  29901. */
  29902. module.exports = function (geoJson) {
  29903. decode(geoJson);
  29904. return zrUtil.map(zrUtil.filter(geoJson.features, function (featureObj) {
  29905. // Output of mapshaper may have geometry null
  29906. return featureObj.geometry
  29907. && featureObj.properties
  29908. && featureObj.geometry.coordinates.length > 0;
  29909. }), function (featureObj) {
  29910. var properties = featureObj.properties;
  29911. var geo = featureObj.geometry;
  29912. var coordinates = geo.coordinates;
  29913. var geometries = [];
  29914. if (geo.type === 'Polygon') {
  29915. geometries.push({
  29916. type: 'polygon',
  29917. // According to the GeoJSON specification.
  29918. // First must be exterior, and the rest are all interior(holes).
  29919. exterior: coordinates[0],
  29920. interiors: coordinates.slice(1)
  29921. });
  29922. }
  29923. if (geo.type === 'MultiPolygon') {
  29924. zrUtil.each(coordinates, function (item) {
  29925. if (item[0]) {
  29926. geometries.push({
  29927. type: 'polygon',
  29928. exterior: item[0],
  29929. interiors: item.slice(1)
  29930. });
  29931. }
  29932. });
  29933. }
  29934. var region = new Region(
  29935. properties.name,
  29936. geometries,
  29937. properties.cp
  29938. );
  29939. region.properties = properties;
  29940. return region;
  29941. });
  29942. };
  29943. /***/ },
  29944. /* 174 */
  29945. /***/ function(module, exports, __webpack_require__) {
  29946. /**
  29947. * @module echarts/coord/geo/Region
  29948. */
  29949. var polygonContain = __webpack_require__(175);
  29950. var BoundingRect = __webpack_require__(9);
  29951. var bbox = __webpack_require__(38);
  29952. var vec2 = __webpack_require__(10);
  29953. /**
  29954. * @param {string} name
  29955. * @param {Array} geometries
  29956. * @param {Array.<number>} cp
  29957. */
  29958. function Region(name, geometries, cp) {
  29959. /**
  29960. * @type {string}
  29961. * @readOnly
  29962. */
  29963. this.name = name;
  29964. /**
  29965. * @type {Array.<Array>}
  29966. * @readOnly
  29967. */
  29968. this.geometries = geometries;
  29969. if (!cp) {
  29970. var rect = this.getBoundingRect();
  29971. cp = [
  29972. rect.x + rect.width / 2,
  29973. rect.y + rect.height / 2
  29974. ];
  29975. }
  29976. else {
  29977. cp = [cp[0], cp[1]];
  29978. }
  29979. /**
  29980. * @type {Array.<number>}
  29981. */
  29982. this.center = cp;
  29983. }
  29984. Region.prototype = {
  29985. constructor: Region,
  29986. properties: null,
  29987. /**
  29988. * @return {module:zrender/core/BoundingRect}
  29989. */
  29990. getBoundingRect: function () {
  29991. var rect = this._rect;
  29992. if (rect) {
  29993. return rect;
  29994. }
  29995. var MAX_NUMBER = Number.MAX_VALUE;
  29996. var min = [MAX_NUMBER, MAX_NUMBER];
  29997. var max = [-MAX_NUMBER, -MAX_NUMBER];
  29998. var min2 = [];
  29999. var max2 = [];
  30000. var geometries = this.geometries;
  30001. for (var i = 0; i < geometries.length; i++) {
  30002. // Only support polygon
  30003. if (geometries[i].type !== 'polygon') {
  30004. continue;
  30005. }
  30006. // Doesn't consider hole
  30007. var exterior = geometries[i].exterior;
  30008. bbox.fromPoints(exterior, min2, max2);
  30009. vec2.min(min, min, min2);
  30010. vec2.max(max, max, max2);
  30011. }
  30012. // No data
  30013. if (i === 0) {
  30014. min[0] = min[1] = max[0] = max[1] = 0;
  30015. }
  30016. return (this._rect = new BoundingRect(
  30017. min[0], min[1], max[0] - min[0], max[1] - min[1]
  30018. ));
  30019. },
  30020. /**
  30021. * @param {<Array.<number>} coord
  30022. * @return {boolean}
  30023. */
  30024. contain: function (coord) {
  30025. var rect = this.getBoundingRect();
  30026. var geometries = this.geometries;
  30027. if (!rect.contain(coord[0], coord[1])) {
  30028. return false;
  30029. }
  30030. loopGeo: for (var i = 0, len = geometries.length; i < len; i++) {
  30031. // Only support polygon.
  30032. if (geometries[i].type !== 'polygon') {
  30033. continue;
  30034. }
  30035. var exterior = geometries[i].exterior;
  30036. var interiors = geometries[i].interiors;
  30037. if (polygonContain.contain(exterior, coord[0], coord[1])) {
  30038. // Not in the region if point is in the hole.
  30039. for (var k = 0; k < (interiors ? interiors.length : 0); k++) {
  30040. if (polygonContain.contain(interiors[k])) {
  30041. continue loopGeo;
  30042. }
  30043. }
  30044. return true;
  30045. }
  30046. }
  30047. return false;
  30048. },
  30049. transformTo: function (x, y, width, height) {
  30050. var rect = this.getBoundingRect();
  30051. var aspect = rect.width / rect.height;
  30052. if (!width) {
  30053. width = aspect * height;
  30054. }
  30055. else if (!height) {
  30056. height = width / aspect ;
  30057. }
  30058. var target = new BoundingRect(x, y, width, height);
  30059. var transform = rect.calculateTransform(target);
  30060. var geometries = this.geometries;
  30061. for (var i = 0; i < geometries.length; i++) {
  30062. // Only support polygon.
  30063. if (geometries[i].type !== 'polygon') {
  30064. continue;
  30065. }
  30066. var exterior = geometries[i].exterior;
  30067. var interiors = geometries[i].interiors;
  30068. for (var p = 0; p < exterior.length; p++) {
  30069. vec2.applyTransform(exterior[p], exterior[p], transform);
  30070. }
  30071. for (var h = 0; h < (interiors ? interiors.length : 0); h++) {
  30072. for (var p = 0; p < interiors[h].length; p++) {
  30073. vec2.applyTransform(interiors[h][p], interiors[h][p], transform);
  30074. }
  30075. }
  30076. }
  30077. rect = this._rect;
  30078. rect.copy(target);
  30079. // Update center
  30080. this.center = [
  30081. rect.x + rect.width / 2,
  30082. rect.y + rect.height / 2
  30083. ];
  30084. }
  30085. };
  30086. module.exports = Region;
  30087. /***/ },
  30088. /* 175 */
  30089. /***/ function(module, exports, __webpack_require__) {
  30090. var windingLine = __webpack_require__(45);
  30091. var EPSILON = 1e-8;
  30092. function isAroundEqual(a, b) {
  30093. return Math.abs(a - b) < EPSILON;
  30094. }
  30095. function contain(points, x, y) {
  30096. var w = 0;
  30097. var p = points[0];
  30098. if (!p) {
  30099. return false;
  30100. }
  30101. for (var i = 1; i < points.length; i++) {
  30102. var p2 = points[i];
  30103. w += windingLine(p[0], p[1], p2[0], p2[1], x, y);
  30104. p = p2;
  30105. }
  30106. // Close polygon
  30107. var p0 = points[0];
  30108. if (!isAroundEqual(p[0], p0[0]) || !isAroundEqual(p[1], p0[1])) {
  30109. w += windingLine(p[0], p[1], p0[0], p0[1], x, y);
  30110. }
  30111. return w !== 0;
  30112. }
  30113. module.exports = {
  30114. contain: contain
  30115. };
  30116. /***/ },
  30117. /* 176 */
  30118. /***/ function(module, exports, __webpack_require__) {
  30119. /**
  30120. * Simple view coordinate system
  30121. * Mapping given x, y to transformd view x, y
  30122. */
  30123. var vector = __webpack_require__(10);
  30124. var matrix = __webpack_require__(11);
  30125. var Transformable = __webpack_require__(26);
  30126. var zrUtil = __webpack_require__(4);
  30127. var BoundingRect = __webpack_require__(9);
  30128. var v2ApplyTransform = vector.applyTransform;
  30129. // Dummy transform node
  30130. function TransformDummy() {
  30131. Transformable.call(this);
  30132. }
  30133. zrUtil.mixin(TransformDummy, Transformable);
  30134. function View(name) {
  30135. /**
  30136. * @type {string}
  30137. */
  30138. this.name = name;
  30139. /**
  30140. * @type {Object}
  30141. */
  30142. this.zoomLimit;
  30143. Transformable.call(this);
  30144. this._roamTransform = new TransformDummy();
  30145. this._viewTransform = new TransformDummy();
  30146. this._center;
  30147. this._zoom;
  30148. }
  30149. View.prototype = {
  30150. constructor: View,
  30151. type: 'view',
  30152. /**
  30153. * @param {Array.<string>}
  30154. * @readOnly
  30155. */
  30156. dimensions: ['x', 'y'],
  30157. /**
  30158. * Set bounding rect
  30159. * @param {number} x
  30160. * @param {number} y
  30161. * @param {number} width
  30162. * @param {number} height
  30163. */
  30164. // PENDING to getRect
  30165. setBoundingRect: function (x, y, width, height) {
  30166. this._rect = new BoundingRect(x, y, width, height);
  30167. return this._rect;
  30168. },
  30169. /**
  30170. * @return {module:zrender/core/BoundingRect}
  30171. */
  30172. // PENDING to getRect
  30173. getBoundingRect: function () {
  30174. return this._rect;
  30175. },
  30176. /**
  30177. * @param {number} x
  30178. * @param {number} y
  30179. * @param {number} width
  30180. * @param {number} height
  30181. */
  30182. setViewRect: function (x, y, width, height) {
  30183. this.transformTo(x, y, width, height);
  30184. this._viewRect = new BoundingRect(x, y, width, height);
  30185. },
  30186. /**
  30187. * Transformed to particular position and size
  30188. * @param {number} x
  30189. * @param {number} y
  30190. * @param {number} width
  30191. * @param {number} height
  30192. */
  30193. transformTo: function (x, y, width, height) {
  30194. var rect = this.getBoundingRect();
  30195. var viewTransform = this._viewTransform;
  30196. viewTransform.transform = rect.calculateTransform(
  30197. new BoundingRect(x, y, width, height)
  30198. );
  30199. viewTransform.decomposeTransform();
  30200. this._updateTransform();
  30201. },
  30202. /**
  30203. * Set center of view
  30204. * @param {Array.<number>} [centerCoord]
  30205. */
  30206. setCenter: function (centerCoord) {
  30207. if (!centerCoord) {
  30208. return;
  30209. }
  30210. this._center = centerCoord;
  30211. this._updateCenterAndZoom();
  30212. },
  30213. /**
  30214. * @param {number} zoom
  30215. */
  30216. setZoom: function (zoom) {
  30217. zoom = zoom || 1;
  30218. var zoomLimit = this.zoomLimit;
  30219. if (zoomLimit) {
  30220. if (zoomLimit.max != null) {
  30221. zoom = Math.min(zoomLimit.max, zoom);
  30222. }
  30223. if (zoomLimit.min != null) {
  30224. zoom = Math.max(zoomLimit.min, zoom);
  30225. }
  30226. }
  30227. this._zoom = zoom;
  30228. this._updateCenterAndZoom();
  30229. },
  30230. /**
  30231. * Get default center without roam
  30232. */
  30233. getDefaultCenter: function () {
  30234. // Rect before any transform
  30235. var rawRect = this.getBoundingRect();
  30236. var cx = rawRect.x + rawRect.width / 2;
  30237. var cy = rawRect.y + rawRect.height / 2;
  30238. return [cx, cy];
  30239. },
  30240. getCenter: function () {
  30241. return this._center || this.getDefaultCenter();
  30242. },
  30243. getZoom: function () {
  30244. return this._zoom || 1;
  30245. },
  30246. /**
  30247. * @return {Array.<number}
  30248. */
  30249. getRoamTransform: function () {
  30250. return this._roamTransform;
  30251. },
  30252. _updateCenterAndZoom: function () {
  30253. // Must update after view transform updated
  30254. var viewTransformMatrix = this._viewTransform.getLocalTransform();
  30255. var roamTransform = this._roamTransform;
  30256. var defaultCenter = this.getDefaultCenter();
  30257. var center = this.getCenter();
  30258. var zoom = this.getZoom();
  30259. center = vector.applyTransform([], center, viewTransformMatrix);
  30260. defaultCenter = vector.applyTransform([], defaultCenter, viewTransformMatrix);
  30261. roamTransform.origin = center;
  30262. roamTransform.position = [
  30263. defaultCenter[0] - center[0],
  30264. defaultCenter[1] - center[1]
  30265. ];
  30266. roamTransform.scale = [zoom, zoom];
  30267. this._updateTransform();
  30268. },
  30269. /**
  30270. * Update transform from roam and mapLocation
  30271. * @private
  30272. */
  30273. _updateTransform: function () {
  30274. var roamTransform = this._roamTransform;
  30275. var viewTransform = this._viewTransform;
  30276. viewTransform.parent = roamTransform;
  30277. roamTransform.updateTransform();
  30278. viewTransform.updateTransform();
  30279. viewTransform.transform
  30280. && matrix.copy(this.transform || (this.transform = []), viewTransform.transform);
  30281. if (this.transform) {
  30282. this.invTransform = this.invTransform || [];
  30283. matrix.invert(this.invTransform, this.transform);
  30284. }
  30285. else {
  30286. this.invTransform = null;
  30287. }
  30288. this.decomposeTransform();
  30289. },
  30290. /**
  30291. * @return {module:zrender/core/BoundingRect}
  30292. */
  30293. getViewRect: function () {
  30294. return this._viewRect;
  30295. },
  30296. /**
  30297. * Get view rect after roam transform
  30298. * @return {module:zrender/core/BoundingRect}
  30299. */
  30300. getViewRectAfterRoam: function () {
  30301. var rect = this.getBoundingRect().clone();
  30302. rect.applyTransform(this.transform);
  30303. return rect;
  30304. },
  30305. /**
  30306. * Convert a single (lon, lat) data item to (x, y) point.
  30307. * @param {Array.<number>} data
  30308. * @return {Array.<number>}
  30309. */
  30310. dataToPoint: function (data) {
  30311. var transform = this.transform;
  30312. return transform
  30313. ? v2ApplyTransform([], data, transform)
  30314. : [data[0], data[1]];
  30315. },
  30316. /**
  30317. * Convert a (x, y) point to (lon, lat) data
  30318. * @param {Array.<number>} point
  30319. * @return {Array.<number>}
  30320. */
  30321. pointToData: function (point) {
  30322. var invTransform = this.invTransform;
  30323. return invTransform
  30324. ? v2ApplyTransform([], point, invTransform)
  30325. : [point[0], point[1]];
  30326. },
  30327. /**
  30328. * @implements
  30329. * see {module:echarts/CoodinateSystem}
  30330. */
  30331. convertToPixel: zrUtil.curry(doConvert, 'dataToPoint'),
  30332. /**
  30333. * @implements
  30334. * see {module:echarts/CoodinateSystem}
  30335. */
  30336. convertFromPixel: zrUtil.curry(doConvert, 'pointToData'),
  30337. /**
  30338. * @implements
  30339. * see {module:echarts/CoodinateSystem}
  30340. */
  30341. containPoint: function (point) {
  30342. return this.getViewRectAfterRoam().contain(point[0], point[1]);
  30343. }
  30344. /**
  30345. * @return {number}
  30346. */
  30347. // getScalarScale: function () {
  30348. // // Use determinant square root of transform to mutiply scalar
  30349. // var m = this.transform;
  30350. // var det = Math.sqrt(Math.abs(m[0] * m[3] - m[2] * m[1]));
  30351. // return det;
  30352. // }
  30353. };
  30354. zrUtil.mixin(View, Transformable);
  30355. function doConvert(methodName, ecModel, finder, value) {
  30356. var seriesModel = finder.seriesModel;
  30357. var coordSys = seriesModel ? seriesModel.coordinateSystem : null; // e.g., graph.
  30358. return coordSys === this ? coordSys[methodName](value) : null;
  30359. }
  30360. module.exports = View;
  30361. /***/ },
  30362. /* 177 */
  30363. /***/ function(module, exports, __webpack_require__) {
  30364. // Fix for 南海诸岛
  30365. var Region = __webpack_require__(174);
  30366. var zrUtil = __webpack_require__(4);
  30367. var geoCoord = [126, 25];
  30368. var points = [
  30369. [[0,3.5],[7,11.2],[15,11.9],[30,7],[42,0.7],[52,0.7],
  30370. [56,7.7],[59,0.7],[64,0.7],[64,0],[5,0],[0,3.5]],
  30371. [[13,16.1],[19,14.7],[16,21.7],[11,23.1],[13,16.1]],
  30372. [[12,32.2],[14,38.5],[15,38.5],[13,32.2],[12,32.2]],
  30373. [[16,47.6],[12,53.2],[13,53.2],[18,47.6],[16,47.6]],
  30374. [[6,64.4],[8,70],[9,70],[8,64.4],[6,64.4]],
  30375. [[23,82.6],[29,79.8],[30,79.8],[25,82.6],[23,82.6]],
  30376. [[37,70.7],[43,62.3],[44,62.3],[39,70.7],[37,70.7]],
  30377. [[48,51.1],[51,45.5],[53,45.5],[50,51.1],[48,51.1]],
  30378. [[51,35],[51,28.7],[53,28.7],[53,35],[51,35]],
  30379. [[52,22.4],[55,17.5],[56,17.5],[53,22.4],[52,22.4]],
  30380. [[58,12.6],[62,7],[63,7],[60,12.6],[58,12.6]],
  30381. [[0,3.5],[0,93.1],[64,93.1],[64,0],[63,0],[63,92.4],
  30382. [1,92.4],[1,3.5],[0,3.5]]
  30383. ];
  30384. for (var i = 0; i < points.length; i++) {
  30385. for (var k = 0; k < points[i].length; k++) {
  30386. points[i][k][0] /= 10.5;
  30387. points[i][k][1] /= -10.5 / 0.75;
  30388. points[i][k][0] += geoCoord[0];
  30389. points[i][k][1] += geoCoord[1];
  30390. }
  30391. }
  30392. module.exports = function (geo) {
  30393. if (geo.map === 'china') {
  30394. geo.regions.push(new Region(
  30395. '南海诸岛',
  30396. zrUtil.map(points, function (exterior) {
  30397. return {
  30398. type: 'polygon',
  30399. exterior: exterior
  30400. };
  30401. }), geoCoord
  30402. ));
  30403. }
  30404. };
  30405. /***/ },
  30406. /* 178 */
  30407. /***/ function(module, exports, __webpack_require__) {
  30408. var zrUtil = __webpack_require__(4);
  30409. var coordsOffsetMap = {
  30410. '南海诸岛' : [32, 80],
  30411. // 全国
  30412. '广东': [0, -10],
  30413. '香港': [10, 5],
  30414. '澳门': [-10, 10],
  30415. //'北京': [-10, 0],
  30416. '天津': [5, 5]
  30417. };
  30418. module.exports = function (geo) {
  30419. zrUtil.each(geo.regions, function (region) {
  30420. var coordFix = coordsOffsetMap[region.name];
  30421. if (coordFix) {
  30422. var cp = region.center;
  30423. cp[0] += coordFix[0] / 10.5;
  30424. cp[1] += -coordFix[1] / (10.5 / 0.75);
  30425. }
  30426. });
  30427. };
  30428. /***/ },
  30429. /* 179 */
  30430. /***/ function(module, exports, __webpack_require__) {
  30431. var zrUtil = __webpack_require__(4);
  30432. var geoCoordMap = {
  30433. 'Russia': [100, 60],
  30434. 'United States': [-99, 38],
  30435. 'United States of America': [-99, 38]
  30436. };
  30437. module.exports = function (geo) {
  30438. zrUtil.each(geo.regions, function (region) {
  30439. var geoCoord = geoCoordMap[region.name];
  30440. if (geoCoord) {
  30441. var cp = region.center;
  30442. cp[0] = geoCoord[0];
  30443. cp[1] = geoCoord[1];
  30444. }
  30445. });
  30446. };
  30447. /***/ },
  30448. /* 180 */
  30449. /***/ function(module, exports, __webpack_require__) {
  30450. // var zrUtil = require('zrender/lib/core/util');
  30451. var graphic = __webpack_require__(18);
  30452. var MapDraw = __webpack_require__(181);
  30453. __webpack_require__(1).extendChartView({
  30454. type: 'map',
  30455. render: function (mapModel, ecModel, api, payload) {
  30456. // Not render if it is an toggleSelect action from self
  30457. if (payload && payload.type === 'mapToggleSelect'
  30458. && payload.from === this.uid
  30459. ) {
  30460. return;
  30461. }
  30462. var group = this.group;
  30463. group.removeAll();
  30464. if (mapModel.getHostGeoModel()) {
  30465. return;
  30466. }
  30467. // Not update map if it is an roam action from self
  30468. if (!(payload && payload.type === 'geoRoam'
  30469. && payload.componentType === 'series'
  30470. && payload.seriesId === mapModel.id
  30471. )
  30472. ) {
  30473. if (mapModel.needsDrawMap) {
  30474. var mapDraw = this._mapDraw || new MapDraw(api, true);
  30475. group.add(mapDraw.group);
  30476. mapDraw.draw(mapModel, ecModel, api, this, payload);
  30477. this._mapDraw = mapDraw;
  30478. }
  30479. else {
  30480. // Remove drawed map
  30481. this._mapDraw && this._mapDraw.remove();
  30482. this._mapDraw = null;
  30483. }
  30484. }
  30485. else {
  30486. var mapDraw = this._mapDraw;
  30487. mapDraw && group.add(mapDraw.group);
  30488. }
  30489. mapModel.get('showLegendSymbol') && ecModel.getComponent('legend')
  30490. && this._renderSymbols(mapModel, ecModel, api);
  30491. },
  30492. remove: function () {
  30493. this._mapDraw && this._mapDraw.remove();
  30494. this._mapDraw = null;
  30495. this.group.removeAll();
  30496. },
  30497. dispose: function () {
  30498. this._mapDraw && this._mapDraw.remove();
  30499. this._mapDraw = null;
  30500. },
  30501. _renderSymbols: function (mapModel, ecModel, api) {
  30502. var originalData = mapModel.originalData;
  30503. var group = this.group;
  30504. originalData.each('value', function (value, idx) {
  30505. if (isNaN(value)) {
  30506. return;
  30507. }
  30508. var layout = originalData.getItemLayout(idx);
  30509. if (!layout || !layout.point) {
  30510. // Not exists in map
  30511. return;
  30512. }
  30513. var point = layout.point;
  30514. var offset = layout.offset;
  30515. var circle = new graphic.Circle({
  30516. style: {
  30517. // Because the special of map draw.
  30518. // Which needs statistic of multiple series and draw on one map.
  30519. // And each series also need a symbol with legend color
  30520. //
  30521. // Layout and visual are put one the different data
  30522. fill: mapModel.getData().getVisual('color')
  30523. },
  30524. shape: {
  30525. cx: point[0] + offset * 9,
  30526. cy: point[1],
  30527. r: 3
  30528. },
  30529. silent: true,
  30530. z2: 10
  30531. });
  30532. // First data on the same region
  30533. if (!offset) {
  30534. var fullData = mapModel.mainSeries.getData();
  30535. var name = originalData.getName(idx);
  30536. var labelText = name;
  30537. var fullIndex = fullData.indexOfName(name);
  30538. var itemModel = originalData.getItemModel(idx);
  30539. var labelModel = itemModel.getModel('label.normal');
  30540. var hoverLabelModel = itemModel.getModel('label.emphasis');
  30541. var textStyleModel = labelModel.getModel('textStyle');
  30542. var hoverTextStyleModel = hoverLabelModel.getModel('textStyle');
  30543. var polygonGroups = fullData.getItemGraphicEl(fullIndex);
  30544. circle.setStyle({
  30545. textPosition: 'bottom'
  30546. });
  30547. var onEmphasis = function () {
  30548. circle.setStyle({
  30549. text: hoverLabelModel.get('show') ? labelText : '',
  30550. textFill: hoverTextStyleModel.getTextColor(),
  30551. textFont: hoverTextStyleModel.getFont()
  30552. });
  30553. };
  30554. var onNormal = function () {
  30555. circle.setStyle({
  30556. text: labelModel.get('show') ? labelText : '',
  30557. textFill: textStyleModel.getTextColor(),
  30558. textFont: textStyleModel.getFont()
  30559. });
  30560. };
  30561. polygonGroups.on('mouseover', onEmphasis)
  30562. .on('mouseout', onNormal)
  30563. .on('emphasis', onEmphasis)
  30564. .on('normal', onNormal);
  30565. onNormal();
  30566. }
  30567. group.add(circle);
  30568. });
  30569. }
  30570. });
  30571. /***/ },
  30572. /* 181 */
  30573. /***/ function(module, exports, __webpack_require__) {
  30574. /**
  30575. * @module echarts/component/helper/MapDraw
  30576. */
  30577. var RoamController = __webpack_require__(182);
  30578. var roamHelper = __webpack_require__(184);
  30579. var cursorHelper = __webpack_require__(185);
  30580. var graphic = __webpack_require__(18);
  30581. var zrUtil = __webpack_require__(4);
  30582. function getFixedItemStyle(model, scale) {
  30583. var itemStyle = model.getItemStyle();
  30584. var areaColor = model.get('areaColor');
  30585. // If user want the color not to be changed when hover,
  30586. // they should both set areaColor and color to be null.
  30587. if (areaColor != null) {
  30588. itemStyle.fill = areaColor;
  30589. }
  30590. return itemStyle;
  30591. }
  30592. function updateMapSelectHandler(mapDraw, mapOrGeoModel, group, api, fromView) {
  30593. group.off('click');
  30594. group.off('mousedown');
  30595. if (mapOrGeoModel.get('selectedMode')) {
  30596. group.on('mousedown', function () {
  30597. mapDraw._mouseDownFlag = true;
  30598. });
  30599. group.on('click', function (e) {
  30600. if (!mapDraw._mouseDownFlag) {
  30601. return;
  30602. }
  30603. mapDraw._mouseDownFlag = false;
  30604. var el = e.target;
  30605. while (!el.__regions) {
  30606. el = el.parent;
  30607. }
  30608. if (!el) {
  30609. return;
  30610. }
  30611. var action = {
  30612. type: (mapOrGeoModel.mainType === 'geo' ? 'geo' : 'map') + 'ToggleSelect',
  30613. batch: zrUtil.map(el.__regions, function (region) {
  30614. return {
  30615. name: region.name,
  30616. from: fromView.uid
  30617. };
  30618. })
  30619. };
  30620. action[mapOrGeoModel.mainType + 'Id'] = mapOrGeoModel.id;
  30621. api.dispatchAction(action);
  30622. updateMapSelected(mapOrGeoModel, group);
  30623. });
  30624. }
  30625. }
  30626. function updateMapSelected(mapOrGeoModel, group) {
  30627. // FIXME
  30628. group.eachChild(function (otherRegionEl) {
  30629. zrUtil.each(otherRegionEl.__regions, function (region) {
  30630. otherRegionEl.trigger(mapOrGeoModel.isSelected(region.name) ? 'emphasis' : 'normal');
  30631. });
  30632. });
  30633. }
  30634. /**
  30635. * @alias module:echarts/component/helper/MapDraw
  30636. * @param {module:echarts/ExtensionAPI} api
  30637. * @param {boolean} updateGroup
  30638. */
  30639. function MapDraw(api, updateGroup) {
  30640. var group = new graphic.Group();
  30641. /**
  30642. * @type {module:echarts/component/helper/RoamController}
  30643. * @private
  30644. */
  30645. this._controller = new RoamController(api.getZr());
  30646. /**
  30647. * @type {Object} {target, zoom, zoomLimit}
  30648. * @private
  30649. */
  30650. this._controllerHost = {target: updateGroup ? group : null};
  30651. /**
  30652. * @type {module:zrender/container/Group}
  30653. * @readOnly
  30654. */
  30655. this.group = group;
  30656. /**
  30657. * @type {boolean}
  30658. * @private
  30659. */
  30660. this._updateGroup = updateGroup;
  30661. /**
  30662. * This flag is used to make sure that only one among
  30663. * `pan`, `zoom`, `click` can occurs, otherwise 'selected'
  30664. * action may be triggered when `pan`, which is unexpected.
  30665. * @type {booelan}
  30666. */
  30667. this._mouseDownFlag;
  30668. }
  30669. MapDraw.prototype = {
  30670. constructor: MapDraw,
  30671. draw: function (mapOrGeoModel, ecModel, api, fromView, payload) {
  30672. var isGeo = mapOrGeoModel.mainType === 'geo';
  30673. // map series has data, geo model that controlled by map series
  30674. // has no data, otherwise data exists.
  30675. var data = mapOrGeoModel.getData && mapOrGeoModel.getData();
  30676. isGeo && ecModel.eachComponent({mainType: 'series', subType: 'map'}, function (mapSeries) {
  30677. if (!data && mapSeries.getHostGeoModel() === mapOrGeoModel) {
  30678. data = mapSeries.getData();
  30679. }
  30680. });
  30681. var geo = mapOrGeoModel.coordinateSystem;
  30682. var group = this.group;
  30683. var scale = geo.scale;
  30684. var groupNewProp = {
  30685. position: geo.position,
  30686. scale: scale
  30687. };
  30688. // No animation when first draw or in action
  30689. if (!group.childAt(0) || payload) {
  30690. group.attr(groupNewProp);
  30691. }
  30692. else {
  30693. graphic.updateProps(group, groupNewProp, mapOrGeoModel);
  30694. }
  30695. group.removeAll();
  30696. var itemStyleAccessPath = ['itemStyle', 'normal'];
  30697. var hoverItemStyleAccessPath = ['itemStyle', 'emphasis'];
  30698. var labelAccessPath = ['label', 'normal'];
  30699. var hoverLabelAccessPath = ['label', 'emphasis'];
  30700. var nameMap = zrUtil.createHashMap();
  30701. zrUtil.each(geo.regions, function (region) {
  30702. // Consider in GeoJson properties.name may be duplicated, for example,
  30703. // there is multiple region named "United Kindom" or "France" (so many
  30704. // colonies). And it is not appropriate to merge them in geo, which
  30705. // will make them share the same label and bring trouble in label
  30706. // location calculation.
  30707. var regionGroup = nameMap.get(region.name)
  30708. || nameMap.set(region.name, new graphic.Group());
  30709. var compoundPath = new graphic.CompoundPath({
  30710. shape: {
  30711. paths: []
  30712. }
  30713. });
  30714. regionGroup.add(compoundPath);
  30715. var regionModel = mapOrGeoModel.getRegionModel(region.name) || mapOrGeoModel;
  30716. var itemStyleModel = regionModel.getModel(itemStyleAccessPath);
  30717. var hoverItemStyleModel = regionModel.getModel(hoverItemStyleAccessPath);
  30718. var itemStyle = getFixedItemStyle(itemStyleModel, scale);
  30719. var hoverItemStyle = getFixedItemStyle(hoverItemStyleModel, scale);
  30720. var labelModel = regionModel.getModel(labelAccessPath);
  30721. var hoverLabelModel = regionModel.getModel(hoverLabelAccessPath);
  30722. var dataIdx;
  30723. // Use the itemStyle in data if has data
  30724. if (data) {
  30725. dataIdx = data.indexOfName(region.name);
  30726. // Only visual color of each item will be used. It can be encoded by dataRange
  30727. // But visual color of series is used in symbol drawing
  30728. //
  30729. // Visual color for each series is for the symbol draw
  30730. var visualColor = data.getItemVisual(dataIdx, 'color', true);
  30731. if (visualColor) {
  30732. itemStyle.fill = visualColor;
  30733. }
  30734. }
  30735. var textStyleModel = labelModel.getModel('textStyle');
  30736. var hoverTextStyleModel = hoverLabelModel.getModel('textStyle');
  30737. zrUtil.each(region.geometries, function (geometry) {
  30738. if (geometry.type !== 'polygon') {
  30739. return;
  30740. }
  30741. compoundPath.shape.paths.push(new graphic.Polygon({
  30742. shape: {
  30743. points: geometry.exterior
  30744. }
  30745. }));
  30746. for (var i = 0; i < (geometry.interiors ? geometry.interiors.length : 0); i++) {
  30747. compoundPath.shape.paths.push(new graphic.Polygon({
  30748. shape: {
  30749. points: geometry.interiors[i]
  30750. }
  30751. }));
  30752. }
  30753. });
  30754. compoundPath.setStyle(itemStyle);
  30755. compoundPath.style.strokeNoScale = true;
  30756. compoundPath.culling = true;
  30757. // Label
  30758. var showLabel = labelModel.get('show');
  30759. var hoverShowLabel = hoverLabelModel.get('show');
  30760. var isDataNaN = data && isNaN(data.get('value', dataIdx));
  30761. var itemLayout = data && data.getItemLayout(dataIdx);
  30762. // In the following cases label will be drawn
  30763. // 1. In map series and data value is NaN
  30764. // 2. In geo component
  30765. // 4. Region has no series legendSymbol, which will be add a showLabel flag in mapSymbolLayout
  30766. if (
  30767. (isGeo || isDataNaN && (showLabel || hoverShowLabel))
  30768. || (itemLayout && itemLayout.showLabel)
  30769. ) {
  30770. var query = data ? dataIdx : region.name;
  30771. var formattedStr = mapOrGeoModel.getFormattedLabel(query, 'normal');
  30772. var hoverFormattedStr = mapOrGeoModel.getFormattedLabel(query, 'emphasis');
  30773. var text = new graphic.Text({
  30774. style: {
  30775. text: showLabel ? (formattedStr || region.name) : '',
  30776. fill: textStyleModel.getTextColor(),
  30777. textFont: textStyleModel.getFont(),
  30778. textAlign: 'center',
  30779. textVerticalAlign: 'middle'
  30780. },
  30781. hoverStyle: {
  30782. text: hoverShowLabel ? (hoverFormattedStr || region.name) : '',
  30783. fill: hoverTextStyleModel.getTextColor(),
  30784. textFont: hoverTextStyleModel.getFont()
  30785. },
  30786. position: region.center.slice(),
  30787. scale: [1 / scale[0], 1 / scale[1]],
  30788. z2: 10,
  30789. silent: true
  30790. });
  30791. regionGroup.add(text);
  30792. }
  30793. // setItemGraphicEl, setHoverStyle after all polygons and labels
  30794. // are added to the rigionGroup
  30795. if (data) {
  30796. data.setItemGraphicEl(dataIdx, regionGroup);
  30797. }
  30798. else {
  30799. var regionModel = mapOrGeoModel.getRegionModel(region.name);
  30800. // Package custom mouse event for geo component
  30801. compoundPath.eventData = {
  30802. componentType: 'geo',
  30803. geoIndex: mapOrGeoModel.componentIndex,
  30804. name: region.name,
  30805. region: (regionModel && regionModel.option) || {}
  30806. };
  30807. }
  30808. var groupRegions = regionGroup.__regions || (regionGroup.__regions = []);
  30809. groupRegions.push(region);
  30810. graphic.setHoverStyle(
  30811. regionGroup,
  30812. hoverItemStyle,
  30813. {hoverSilentOnTouch: !!mapOrGeoModel.get('selectedMode')}
  30814. );
  30815. group.add(regionGroup);
  30816. });
  30817. this._updateController(mapOrGeoModel, ecModel, api);
  30818. updateMapSelectHandler(this, mapOrGeoModel, group, api, fromView);
  30819. updateMapSelected(mapOrGeoModel, group);
  30820. },
  30821. remove: function () {
  30822. this.group.removeAll();
  30823. this._controller.dispose();
  30824. this._controllerHost = {};
  30825. },
  30826. _updateController: function (mapOrGeoModel, ecModel, api) {
  30827. var geo = mapOrGeoModel.coordinateSystem;
  30828. var controller = this._controller;
  30829. var controllerHost = this._controllerHost;
  30830. controllerHost.zoomLimit = mapOrGeoModel.get('scaleLimit');
  30831. controllerHost.zoom = geo.getZoom();
  30832. // roamType is will be set default true if it is null
  30833. controller.enable(mapOrGeoModel.get('roam') || false);
  30834. var mainType = mapOrGeoModel.mainType;
  30835. function makeActionBase() {
  30836. var action = {
  30837. type: 'geoRoam',
  30838. componentType: mainType
  30839. };
  30840. action[mainType + 'Id'] = mapOrGeoModel.id;
  30841. return action;
  30842. }
  30843. controller.off('pan').on('pan', function (dx, dy) {
  30844. this._mouseDownFlag = false;
  30845. roamHelper.updateViewOnPan(controllerHost, dx, dy);
  30846. api.dispatchAction(zrUtil.extend(makeActionBase(), {
  30847. dx: dx,
  30848. dy: dy
  30849. }));
  30850. }, this);
  30851. controller.off('zoom').on('zoom', function (zoom, mouseX, mouseY) {
  30852. this._mouseDownFlag = false;
  30853. roamHelper.updateViewOnZoom(controllerHost, zoom, mouseX, mouseY);
  30854. api.dispatchAction(zrUtil.extend(makeActionBase(), {
  30855. zoom: zoom,
  30856. originX: mouseX,
  30857. originY: mouseY
  30858. }));
  30859. if (this._updateGroup) {
  30860. var group = this.group;
  30861. var scale = group.scale;
  30862. group.traverse(function (el) {
  30863. if (el.type === 'text') {
  30864. el.attr('scale', [1 / scale[0], 1 / scale[1]]);
  30865. }
  30866. });
  30867. }
  30868. }, this);
  30869. controller.setPointerChecker(function (e, x, y) {
  30870. return geo.getViewRectAfterRoam().contain(x, y)
  30871. && !cursorHelper.onIrrelevantElement(e, api, mapOrGeoModel);
  30872. });
  30873. }
  30874. };
  30875. module.exports = MapDraw;
  30876. /***/ },
  30877. /* 182 */
  30878. /***/ function(module, exports, __webpack_require__) {
  30879. /**
  30880. * @module echarts/component/helper/RoamController
  30881. */
  30882. var Eventful = __webpack_require__(25);
  30883. var zrUtil = __webpack_require__(4);
  30884. var eventTool = __webpack_require__(88);
  30885. var interactionMutex = __webpack_require__(183);
  30886. /**
  30887. * @alias module:echarts/component/helper/RoamController
  30888. * @constructor
  30889. * @mixin {module:zrender/mixin/Eventful}
  30890. *
  30891. * @param {module:zrender/zrender~ZRender} zr
  30892. */
  30893. function RoamController(zr) {
  30894. /**
  30895. * @type {Function}
  30896. */
  30897. this.pointerChecker;
  30898. /**
  30899. * @type {module:zrender}
  30900. */
  30901. this._zr = zr;
  30902. /**
  30903. * @type {Object}
  30904. */
  30905. this._opt = {};
  30906. // Avoid two roamController bind the same handler
  30907. var bind = zrUtil.bind;
  30908. var mousedownHandler = bind(mousedown, this);
  30909. var mousemoveHandler = bind(mousemove, this);
  30910. var mouseupHandler = bind(mouseup, this);
  30911. var mousewheelHandler = bind(mousewheel, this);
  30912. var pinchHandler = bind(pinch, this);
  30913. Eventful.call(this);
  30914. /**
  30915. * @param {Function} pointerChecker
  30916. * input: x, y
  30917. * output: boolean
  30918. */
  30919. this.setPointerChecker = function (pointerChecker) {
  30920. this.pointerChecker = pointerChecker;
  30921. };
  30922. /**
  30923. * Notice: only enable needed types. For example, if 'zoom'
  30924. * is not needed, 'zoom' should not be enabled, otherwise
  30925. * default mousewheel behaviour (scroll page) will be disabled.
  30926. *
  30927. * @param {boolean|string} [controlType=true] Specify the control type,
  30928. * which can be null/undefined or true/false
  30929. * or 'pan/move' or 'zoom'/'scale'
  30930. * @param {Object} [opt]
  30931. * @param {Object} [opt.zoomOnMouseWheel=true]
  30932. * @param {Object} [opt.moveOnMouseMove=true]
  30933. * @param {Object} [opt.preventDefaultMouseMove=true] When pan.
  30934. */
  30935. this.enable = function (controlType, opt) {
  30936. // Disable previous first
  30937. this.disable();
  30938. this._opt = zrUtil.defaults(zrUtil.clone(opt) || {}, {
  30939. zoomOnMouseWheel: true,
  30940. moveOnMouseMove: true,
  30941. preventDefaultMouseMove: true
  30942. });
  30943. if (controlType == null) {
  30944. controlType = true;
  30945. }
  30946. if (controlType === true || (controlType === 'move' || controlType === 'pan')) {
  30947. zr.on('mousedown', mousedownHandler);
  30948. zr.on('mousemove', mousemoveHandler);
  30949. zr.on('mouseup', mouseupHandler);
  30950. }
  30951. if (controlType === true || (controlType === 'scale' || controlType === 'zoom')) {
  30952. zr.on('mousewheel', mousewheelHandler);
  30953. zr.on('pinch', pinchHandler);
  30954. }
  30955. };
  30956. this.disable = function () {
  30957. zr.off('mousedown', mousedownHandler);
  30958. zr.off('mousemove', mousemoveHandler);
  30959. zr.off('mouseup', mouseupHandler);
  30960. zr.off('mousewheel', mousewheelHandler);
  30961. zr.off('pinch', pinchHandler);
  30962. };
  30963. this.dispose = this.disable;
  30964. this.isDragging = function () {
  30965. return this._dragging;
  30966. };
  30967. this.isPinching = function () {
  30968. return this._pinching;
  30969. };
  30970. }
  30971. zrUtil.mixin(RoamController, Eventful);
  30972. function mousedown(e) {
  30973. if (e.target && e.target.draggable) {
  30974. return;
  30975. }
  30976. var x = e.offsetX;
  30977. var y = e.offsetY;
  30978. // Only check on mosedown, but not mousemove.
  30979. // Mouse can be out of target when mouse moving.
  30980. if (this.pointerChecker && this.pointerChecker(e, x, y)) {
  30981. this._x = x;
  30982. this._y = y;
  30983. this._dragging = true;
  30984. }
  30985. }
  30986. function mousemove(e) {
  30987. if (!checkKeyBinding(this, 'moveOnMouseMove', e) || !this._dragging) {
  30988. return;
  30989. }
  30990. if (e.gestureEvent === 'pinch') {
  30991. return;
  30992. }
  30993. if (interactionMutex.isTaken(this._zr, 'globalPan')) {
  30994. return;
  30995. }
  30996. var x = e.offsetX;
  30997. var y = e.offsetY;
  30998. var oldX = this._x;
  30999. var oldY = this._y;
  31000. var dx = x - oldX;
  31001. var dy = y - oldY;
  31002. this._x = x;
  31003. this._y = y;
  31004. this._opt.preventDefaultMouseMove && eventTool.stop(e.event);
  31005. this.trigger('pan', dx, dy, oldX, oldY, x, y);
  31006. }
  31007. function mouseup(e) {
  31008. this._dragging = false;
  31009. }
  31010. function mousewheel(e) {
  31011. // wheelDelta maybe -0 in chrome mac.
  31012. if (!checkKeyBinding(this, 'zoomOnMouseWheel', e) || e.wheelDelta === 0) {
  31013. return;
  31014. }
  31015. // Convenience:
  31016. // Mac and VM Windows on Mac: scroll up: zoom out.
  31017. // Windows: scroll up: zoom in.
  31018. var zoomDelta = e.wheelDelta > 0 ? 1.1 : 1 / 1.1;
  31019. zoom.call(this, e, zoomDelta, e.offsetX, e.offsetY);
  31020. }
  31021. function pinch(e) {
  31022. if (interactionMutex.isTaken(this._zr, 'globalPan')) {
  31023. return;
  31024. }
  31025. var zoomDelta = e.pinchScale > 1 ? 1.1 : 1 / 1.1;
  31026. zoom.call(this, e, zoomDelta, e.pinchX, e.pinchY);
  31027. }
  31028. function zoom(e, zoomDelta, zoomX, zoomY) {
  31029. if (this.pointerChecker && this.pointerChecker(e, zoomX, zoomY)) {
  31030. // When mouse is out of roamController rect,
  31031. // default befavoius should not be be disabled, otherwise
  31032. // page sliding is disabled, contrary to expectation.
  31033. eventTool.stop(e.event);
  31034. this.trigger('zoom', zoomDelta, zoomX, zoomY);
  31035. }
  31036. }
  31037. function checkKeyBinding(roamController, prop, e) {
  31038. var setting = roamController._opt[prop];
  31039. return setting
  31040. && (!zrUtil.isString(setting) || e.event[setting + 'Key']);
  31041. }
  31042. module.exports = RoamController;
  31043. /***/ },
  31044. /* 183 */
  31045. /***/ function(module, exports, __webpack_require__) {
  31046. var ATTR = '\0_ec_interaction_mutex';
  31047. var interactionMutex = {
  31048. take: function (zr, resourceKey, userKey) {
  31049. var store = getStore(zr);
  31050. store[resourceKey] = userKey;
  31051. },
  31052. release: function (zr, resourceKey, userKey) {
  31053. var store = getStore(zr);
  31054. var uKey = store[resourceKey];
  31055. if (uKey === userKey) {
  31056. store[resourceKey] = null;
  31057. }
  31058. },
  31059. isTaken: function (zr, resourceKey) {
  31060. return !!getStore(zr)[resourceKey];
  31061. }
  31062. };
  31063. function getStore(zr) {
  31064. return zr[ATTR] || (zr[ATTR] = {});
  31065. }
  31066. /**
  31067. * payload: {
  31068. * type: 'takeGlobalCursor',
  31069. * key: 'dataZoomSelect', or 'brush', or ...,
  31070. * If no userKey, release global cursor.
  31071. * }
  31072. */
  31073. __webpack_require__(1).registerAction(
  31074. {type: 'takeGlobalCursor', event: 'globalCursorTaken', update: 'update'},
  31075. function () {}
  31076. );
  31077. module.exports = interactionMutex;
  31078. /***/ },
  31079. /* 184 */
  31080. /***/ function(module, exports) {
  31081. var helper = {};
  31082. /**
  31083. * For geo and graph.
  31084. *
  31085. * @param {Object} controllerHost
  31086. * @param {module:zrender/Element} controllerHost.target
  31087. */
  31088. helper.updateViewOnPan = function (controllerHost, dx, dy) {
  31089. var target = controllerHost.target;
  31090. var pos = target.position;
  31091. pos[0] += dx;
  31092. pos[1] += dy;
  31093. target.dirty();
  31094. };
  31095. /**
  31096. * For geo and graph.
  31097. *
  31098. * @param {Object} controllerHost
  31099. * @param {module:zrender/Element} controllerHost.target
  31100. * @param {number} controllerHost.zoom
  31101. * @param {number} controllerHost.zoomLimit like: {min: 1, max: 2}
  31102. */
  31103. helper.updateViewOnZoom = function (controllerHost, zoomDelta, zoomX, zoomY) {
  31104. var target = controllerHost.target;
  31105. var zoomLimit = controllerHost.zoomLimit;
  31106. var pos = target.position;
  31107. var scale = target.scale;
  31108. var newZoom = controllerHost.zoom = controllerHost.zoom || 1;
  31109. newZoom *= zoomDelta;
  31110. if (zoomLimit) {
  31111. var zoomMin = zoomLimit.min || 0;
  31112. var zoomMax = zoomLimit.max || Infinity;
  31113. newZoom = Math.max(
  31114. Math.min(zoomMax, newZoom),
  31115. zoomMin
  31116. );
  31117. }
  31118. var zoomScale = newZoom / controllerHost.zoom;
  31119. controllerHost.zoom = newZoom;
  31120. // Keep the mouse center when scaling
  31121. pos[0] -= (zoomX - pos[0]) * (zoomScale - 1);
  31122. pos[1] -= (zoomY - pos[1]) * (zoomScale - 1);
  31123. scale[0] *= zoomScale;
  31124. scale[1] *= zoomScale;
  31125. target.dirty();
  31126. };
  31127. module.exports = helper;
  31128. /***/ },
  31129. /* 185 */
  31130. /***/ function(module, exports) {
  31131. var helper = {};
  31132. var IRRELEVANT_EXCLUDES = {'axisPointer': 1, 'tooltip': 1, 'brush': 1};
  31133. /**
  31134. * Avoid that: mouse click on a elements that is over geo or graph,
  31135. * but roam is triggered.
  31136. */
  31137. helper.onIrrelevantElement = function (e, api, targetCoordSysModel) {
  31138. var model = api.getComponentByElement(e.topTarget);
  31139. // If model is axisModel, it works only if it is injected with coordinateSystem.
  31140. var coordSys = model && model.coordinateSystem;
  31141. return model
  31142. && model !== targetCoordSysModel
  31143. && !IRRELEVANT_EXCLUDES[model.mainType]
  31144. && (coordSys && coordSys.model !== targetCoordSysModel);
  31145. };
  31146. module.exports = helper;
  31147. /***/ },
  31148. /* 186 */
  31149. /***/ function(module, exports, __webpack_require__) {
  31150. var zrUtil = __webpack_require__(4);
  31151. var roamHelper = __webpack_require__(187);
  31152. var echarts = __webpack_require__(1);
  31153. /**
  31154. * @payload
  31155. * @property {string} [componentType=series]
  31156. * @property {number} [dx]
  31157. * @property {number} [dy]
  31158. * @property {number} [zoom]
  31159. * @property {number} [originX]
  31160. * @property {number} [originY]
  31161. */
  31162. echarts.registerAction({
  31163. type: 'geoRoam',
  31164. event: 'geoRoam',
  31165. update: 'updateLayout'
  31166. }, function (payload, ecModel) {
  31167. var componentType = payload.componentType || 'series';
  31168. ecModel.eachComponent(
  31169. { mainType: componentType, query: payload },
  31170. function (componentModel) {
  31171. var geo = componentModel.coordinateSystem;
  31172. if (geo.type !== 'geo') {
  31173. return;
  31174. }
  31175. var res = roamHelper.updateCenterAndZoom(
  31176. geo, payload, componentModel.get('scaleLimit')
  31177. );
  31178. componentModel.setCenter
  31179. && componentModel.setCenter(res.center);
  31180. componentModel.setZoom
  31181. && componentModel.setZoom(res.zoom);
  31182. // All map series with same `map` use the same geo coordinate system
  31183. // So the center and zoom must be in sync. Include the series not selected by legend
  31184. if (componentType === 'series') {
  31185. zrUtil.each(componentModel.seriesGroup, function (seriesModel) {
  31186. seriesModel.setCenter(res.center);
  31187. seriesModel.setZoom(res.zoom);
  31188. });
  31189. }
  31190. }
  31191. );
  31192. });
  31193. /***/ },
  31194. /* 187 */
  31195. /***/ function(module, exports) {
  31196. var roamHelper = {};
  31197. /**
  31198. * @param {module:echarts/coord/View} view
  31199. * @param {Object} payload
  31200. * @param {Object} [zoomLimit]
  31201. */
  31202. roamHelper.updateCenterAndZoom = function (
  31203. view, payload, zoomLimit
  31204. ) {
  31205. var previousZoom = view.getZoom();
  31206. var center = view.getCenter();
  31207. var zoom = payload.zoom;
  31208. var point = view.dataToPoint(center);
  31209. if (payload.dx != null && payload.dy != null) {
  31210. point[0] -= payload.dx;
  31211. point[1] -= payload.dy;
  31212. var center = view.pointToData(point);
  31213. view.setCenter(center);
  31214. }
  31215. if (zoom != null) {
  31216. if (zoomLimit) {
  31217. var zoomMin = zoomLimit.min || 0;
  31218. var zoomMax = zoomLimit.max || Infinity;
  31219. zoom = Math.max(
  31220. Math.min(previousZoom * zoom, zoomMax),
  31221. zoomMin
  31222. ) / previousZoom;
  31223. }
  31224. // Zoom on given point(originX, originY)
  31225. view.scale[0] *= zoom;
  31226. view.scale[1] *= zoom;
  31227. var position = view.position;
  31228. var fixX = (payload.originX - position[0]) * (zoom - 1);
  31229. var fixY = (payload.originY - position[1]) * (zoom - 1);
  31230. position[0] -= fixX;
  31231. position[1] -= fixY;
  31232. view.updateTransform();
  31233. // Get the new center
  31234. var center = view.pointToData(point);
  31235. view.setCenter(center);
  31236. view.setZoom(zoom * previousZoom);
  31237. }
  31238. return {
  31239. center: view.getCenter(),
  31240. zoom: view.getZoom()
  31241. };
  31242. };
  31243. module.exports = roamHelper;
  31244. /***/ },
  31245. /* 188 */
  31246. /***/ function(module, exports, __webpack_require__) {
  31247. var zrUtil = __webpack_require__(4);
  31248. module.exports = function (ecModel) {
  31249. var processedMapType = {};
  31250. ecModel.eachSeriesByType('map', function (mapSeries) {
  31251. var mapType = mapSeries.getMapType();
  31252. if (mapSeries.getHostGeoModel() || processedMapType[mapType]) {
  31253. return;
  31254. }
  31255. var mapSymbolOffsets = {};
  31256. zrUtil.each(mapSeries.seriesGroup, function (subMapSeries) {
  31257. var geo = subMapSeries.coordinateSystem;
  31258. var data = subMapSeries.originalData;
  31259. if (subMapSeries.get('showLegendSymbol') && ecModel.getComponent('legend')) {
  31260. data.each('value', function (value, idx) {
  31261. var name = data.getName(idx);
  31262. var region = geo.getRegion(name);
  31263. // If input series.data is [11, 22, '-'/null/undefined, 44],
  31264. // it will be filled with NaN: [11, 22, NaN, 44] and NaN will
  31265. // not be drawn. So here must validate if value is NaN.
  31266. if (!region || isNaN(value)) {
  31267. return;
  31268. }
  31269. var offset = mapSymbolOffsets[name] || 0;
  31270. var point = geo.dataToPoint(region.center);
  31271. mapSymbolOffsets[name] = offset + 1;
  31272. data.setItemLayout(idx, {
  31273. point: point,
  31274. offset: offset
  31275. });
  31276. });
  31277. }
  31278. });
  31279. // Show label of those region not has legendSymbol(which is offset 0)
  31280. var data = mapSeries.getData();
  31281. data.each(function (idx) {
  31282. var name = data.getName(idx);
  31283. var layout = data.getItemLayout(idx) || {};
  31284. layout.showLabel = !mapSymbolOffsets[name];
  31285. data.setItemLayout(idx, layout);
  31286. });
  31287. processedMapType[mapType] = true;
  31288. });
  31289. };
  31290. /***/ },
  31291. /* 189 */
  31292. /***/ function(module, exports) {
  31293. module.exports = function (ecModel) {
  31294. ecModel.eachSeriesByType('map', function (seriesModel) {
  31295. var colorList = seriesModel.get('color');
  31296. var itemStyleModel = seriesModel.getModel('itemStyle.normal');
  31297. var areaColor = itemStyleModel.get('areaColor');
  31298. var color = itemStyleModel.get('color')
  31299. || colorList[seriesModel.seriesIndex % colorList.length];
  31300. seriesModel.getData().setVisual({
  31301. 'areaColor': areaColor,
  31302. 'color': color
  31303. });
  31304. });
  31305. };
  31306. /***/ },
  31307. /* 190 */
  31308. /***/ function(module, exports, __webpack_require__) {
  31309. var zrUtil = __webpack_require__(4);
  31310. // FIXME 公用?
  31311. /**
  31312. * @param {Array.<module:echarts/data/List>} datas
  31313. * @param {string} statisticType 'average' 'sum'
  31314. * @inner
  31315. */
  31316. function dataStatistics(datas, statisticType) {
  31317. var dataNameMap = {};
  31318. var dims = ['value'];
  31319. zrUtil.each(datas, function (data) {
  31320. data.each(dims, function (value, idx) {
  31321. // Add prefix to avoid conflict with Object.prototype.
  31322. var mapKey = 'ec-' + data.getName(idx);
  31323. dataNameMap[mapKey] = dataNameMap[mapKey] || [];
  31324. if (!isNaN(value)) {
  31325. dataNameMap[mapKey].push(value);
  31326. }
  31327. });
  31328. });
  31329. return datas[0].map(dims, function (value, idx) {
  31330. var mapKey = 'ec-' + datas[0].getName(idx);
  31331. var sum = 0;
  31332. var min = Infinity;
  31333. var max = -Infinity;
  31334. var len = dataNameMap[mapKey].length;
  31335. for (var i = 0; i < len; i++) {
  31336. min = Math.min(min, dataNameMap[mapKey][i]);
  31337. max = Math.max(max, dataNameMap[mapKey][i]);
  31338. sum += dataNameMap[mapKey][i];
  31339. }
  31340. var result;
  31341. if (statisticType === 'min') {
  31342. result = min;
  31343. }
  31344. else if (statisticType === 'max') {
  31345. result = max;
  31346. }
  31347. else if (statisticType === 'average') {
  31348. result = sum / len;
  31349. }
  31350. else {
  31351. result = sum;
  31352. }
  31353. return len === 0 ? NaN : result;
  31354. });
  31355. }
  31356. module.exports = function (ecModel) {
  31357. var seriesGroups = {};
  31358. ecModel.eachSeriesByType('map', function (seriesModel) {
  31359. var hostGeoModel = seriesModel.getHostGeoModel();
  31360. var key = hostGeoModel ? 'o' + hostGeoModel.id : 'i' + seriesModel.getMapType();
  31361. (seriesGroups[key] = seriesGroups[key] || []).push(seriesModel);
  31362. });
  31363. zrUtil.each(seriesGroups, function (seriesList, key) {
  31364. var data = dataStatistics(
  31365. zrUtil.map(seriesList, function (seriesModel) {
  31366. return seriesModel.getData();
  31367. }),
  31368. seriesList[0].get('mapValueCalculation')
  31369. );
  31370. for (var i = 0; i < seriesList.length; i++) {
  31371. seriesList[i].originalData = seriesList[i].getData();
  31372. }
  31373. // FIXME Put where?
  31374. for (var i = 0; i < seriesList.length; i++) {
  31375. seriesList[i].seriesGroup = seriesList;
  31376. seriesList[i].needsDrawMap = i === 0 && !seriesList[i].getHostGeoModel();
  31377. seriesList[i].setData(data.cloneShallow());
  31378. seriesList[i].mainSeries = seriesList[0];
  31379. }
  31380. });
  31381. };
  31382. /***/ },
  31383. /* 191 */
  31384. /***/ function(module, exports, __webpack_require__) {
  31385. var zrUtil = __webpack_require__(4);
  31386. module.exports = function (option) {
  31387. // Save geoCoord
  31388. var mapSeries = [];
  31389. zrUtil.each(option.series, function (seriesOpt) {
  31390. if (seriesOpt.type === 'map') {
  31391. mapSeries.push(seriesOpt);
  31392. }
  31393. });
  31394. zrUtil.each(mapSeries, function (seriesOpt) {
  31395. seriesOpt.map = seriesOpt.map || seriesOpt.mapType;
  31396. // Put x, y, width, height, x2, y2 in the top level
  31397. zrUtil.defaults(seriesOpt, seriesOpt.mapLocation);
  31398. });
  31399. };
  31400. /***/ },
  31401. /* 192 */
  31402. /***/ function(module, exports, __webpack_require__) {
  31403. var echarts = __webpack_require__(1);
  31404. __webpack_require__(193);
  31405. __webpack_require__(197);
  31406. __webpack_require__(200);
  31407. echarts.registerVisual(__webpack_require__(201));
  31408. echarts.registerLayout(__webpack_require__(203));
  31409. /***/ },
  31410. /* 193 */
  31411. /***/ function(module, exports, __webpack_require__) {
  31412. var SeriesModel = __webpack_require__(78);
  31413. var Tree = __webpack_require__(194);
  31414. var zrUtil = __webpack_require__(4);
  31415. var Model = __webpack_require__(12);
  31416. var formatUtil = __webpack_require__(6);
  31417. var helper = __webpack_require__(196);
  31418. var encodeHTML = formatUtil.encodeHTML;
  31419. var addCommas = formatUtil.addCommas;
  31420. module.exports = SeriesModel.extend({
  31421. type: 'series.treemap',
  31422. layoutMode: 'box',
  31423. dependencies: ['grid', 'polar'],
  31424. /**
  31425. * @type {module:echarts/data/Tree~Node}
  31426. */
  31427. _viewRoot: null,
  31428. defaultOption: {
  31429. // Disable progressive rendering
  31430. progressive: 0,
  31431. hoverLayerThreshold: Infinity,
  31432. // center: ['50%', '50%'], // not supported in ec3.
  31433. // size: ['80%', '80%'], // deprecated, compatible with ec2.
  31434. left: 'center',
  31435. top: 'middle',
  31436. right: null,
  31437. bottom: null,
  31438. width: '80%',
  31439. height: '80%',
  31440. sort: true, // Can be null or false or true
  31441. // (order by desc default, asc not supported yet (strange effect))
  31442. clipWindow: 'origin', // Size of clipped window when zooming. 'origin' or 'fullscreen'
  31443. squareRatio: 0.5 * (1 + Math.sqrt(5)), // golden ratio
  31444. leafDepth: null, // Nodes on depth from root are regarded as leaves.
  31445. // Count from zero (zero represents only view root).
  31446. drillDownIcon: '▶', // Use html character temporarily because it is complicated
  31447. // to align specialized icon. ▷▶❒❐▼✚
  31448. zoomToNodeRatio: 0.32 * 0.32, // Be effective when using zoomToNode. Specify the proportion of the
  31449. // target node area in the view area.
  31450. roam: true, // true, false, 'scale' or 'zoom', 'move'.
  31451. nodeClick: 'zoomToNode', // Leaf node click behaviour: 'zoomToNode', 'link', false.
  31452. // If leafDepth is set and clicking a node which has children but
  31453. // be on left depth, the behaviour would be changing root. Otherwise
  31454. // use behavious defined above.
  31455. animation: true,
  31456. animationDurationUpdate: 900,
  31457. animationEasing: 'quinticInOut',
  31458. breadcrumb: {
  31459. show: true,
  31460. height: 22,
  31461. left: 'center',
  31462. top: 'bottom',
  31463. // right
  31464. // bottom
  31465. emptyItemWidth: 25, // Width of empty node.
  31466. itemStyle: {
  31467. normal: {
  31468. color: 'rgba(0,0,0,0.7)', //'#5793f3',
  31469. borderColor: 'rgba(255,255,255,0.7)',
  31470. borderWidth: 1,
  31471. shadowColor: 'rgba(150,150,150,1)',
  31472. shadowBlur: 3,
  31473. shadowOffsetX: 0,
  31474. shadowOffsetY: 0,
  31475. textStyle: {
  31476. color: '#fff'
  31477. }
  31478. },
  31479. emphasis: {
  31480. textStyle: {}
  31481. }
  31482. }
  31483. },
  31484. label: {
  31485. normal: {
  31486. show: true,
  31487. position: 'inside', // Can be [5, '5%'] or position stirng like 'insideTopLeft', ...
  31488. textStyle: {
  31489. color: '#fff',
  31490. ellipsis: true
  31491. }
  31492. }
  31493. },
  31494. itemStyle: {
  31495. normal: {
  31496. color: null, // Can be 'none' if not necessary.
  31497. colorAlpha: null, // Can be 'none' if not necessary.
  31498. colorSaturation: null, // Can be 'none' if not necessary.
  31499. borderWidth: 0,
  31500. gapWidth: 0,
  31501. borderColor: '#fff',
  31502. borderColorSaturation: null // If specified, borderColor will be ineffective, and the
  31503. // border color is evaluated by color of current node and
  31504. // borderColorSaturation.
  31505. },
  31506. emphasis: {
  31507. }
  31508. },
  31509. visualDimension: 0, // Can be 0, 1, 2, 3.
  31510. visualMin: null,
  31511. visualMax: null,
  31512. color: [], // + treemapSeries.color should not be modified. Please only modified
  31513. // level[n].color (if necessary).
  31514. // + Specify color list of each level. level[0].color would be global
  31515. // color list if not specified. (see method `setDefault`).
  31516. // + But set as a empty array to forbid fetch color from global palette
  31517. // when using nodeModel.get('color'), otherwise nodes on deep level
  31518. // will always has color palette set and are not able to inherit color
  31519. // from parent node.
  31520. // + TreemapSeries.color can not be set as 'none', otherwise effect
  31521. // legend color fetching (see seriesColor.js).
  31522. colorAlpha: null, // Array. Specify color alpha range of each level, like [0.2, 0.8]
  31523. colorSaturation: null, // Array. Specify color saturation of each level, like [0.2, 0.5]
  31524. colorMappingBy: 'index', // 'value' or 'index' or 'id'.
  31525. visibleMin: 10, // If area less than this threshold (unit: pixel^2), node will not
  31526. // be rendered. Only works when sort is 'asc' or 'desc'.
  31527. childrenVisibleMin: null, // If area of a node less than this threshold (unit: pixel^2),
  31528. // grandchildren will not show.
  31529. // Why grandchildren? If not grandchildren but children,
  31530. // some siblings show children and some not,
  31531. // the appearance may be mess and not consistent,
  31532. levels: [] // Each item: {
  31533. // visibleMin, itemStyle, visualDimension, label
  31534. // }
  31535. // data: {
  31536. // value: [],
  31537. // children: [],
  31538. // link: 'http://xxx.xxx.xxx',
  31539. // target: 'blank' or 'self'
  31540. // }
  31541. },
  31542. /**
  31543. * @override
  31544. */
  31545. getInitialData: function (option, ecModel) {
  31546. var rootName = option.name;
  31547. rootName == null && (rootName = option.name);
  31548. // Create a virtual root.
  31549. var root = {name: rootName, children: option.data};
  31550. completeTreeValue(root);
  31551. var levels = option.levels || [];
  31552. levels = option.levels = setDefault(levels, ecModel);
  31553. // Make sure always a new tree is created when setOption,
  31554. // in TreemapView, we check whether oldTree === newTree
  31555. // to choose mappings approach among old shapes and new shapes.
  31556. return Tree.createTree(root, this, levels).data;
  31557. },
  31558. optionUpdated: function () {
  31559. this.resetViewRoot();
  31560. },
  31561. /**
  31562. * @override
  31563. * @param {number} dataIndex
  31564. * @param {boolean} [mutipleSeries=false]
  31565. */
  31566. formatTooltip: function (dataIndex) {
  31567. var data = this.getData();
  31568. var value = this.getRawValue(dataIndex);
  31569. var formattedValue = zrUtil.isArray(value)
  31570. ? addCommas(value[0]) : addCommas(value);
  31571. var name = data.getName(dataIndex);
  31572. return encodeHTML(name + ': ' + formattedValue);
  31573. },
  31574. /**
  31575. * Add tree path to tooltip param
  31576. *
  31577. * @override
  31578. * @param {number} dataIndex
  31579. * @return {Object}
  31580. */
  31581. getDataParams: function (dataIndex) {
  31582. var params = SeriesModel.prototype.getDataParams.apply(this, arguments);
  31583. var node = this.getData().tree.getNodeByDataIndex(dataIndex);
  31584. params.treePathInfo = helper.wrapTreePathInfo(node, this);
  31585. return params;
  31586. },
  31587. /**
  31588. * @public
  31589. * @param {Object} layoutInfo {
  31590. * x: containerGroup x
  31591. * y: containerGroup y
  31592. * width: containerGroup width
  31593. * height: containerGroup height
  31594. * }
  31595. */
  31596. setLayoutInfo: function (layoutInfo) {
  31597. /**
  31598. * @readOnly
  31599. * @type {Object}
  31600. */
  31601. this.layoutInfo = this.layoutInfo || {};
  31602. zrUtil.extend(this.layoutInfo, layoutInfo);
  31603. },
  31604. /**
  31605. * @param {string} id
  31606. * @return {number} index
  31607. */
  31608. mapIdToIndex: function (id) {
  31609. // A feature is implemented:
  31610. // index is monotone increasing with the sequence of
  31611. // input id at the first time.
  31612. // This feature can make sure that each data item and its
  31613. // mapped color have the same index between data list and
  31614. // color list at the beginning, which is useful for user
  31615. // to adjust data-color mapping.
  31616. /**
  31617. * @private
  31618. * @type {Object}
  31619. */
  31620. var idIndexMap = this._idIndexMap;
  31621. if (!idIndexMap) {
  31622. idIndexMap = this._idIndexMap = zrUtil.createHashMap();
  31623. /**
  31624. * @private
  31625. * @type {number}
  31626. */
  31627. this._idIndexMapCount = 0;
  31628. }
  31629. var index = idIndexMap.get(id);
  31630. if (index == null) {
  31631. idIndexMap.set(id, index = this._idIndexMapCount++);
  31632. }
  31633. return index;
  31634. },
  31635. getViewRoot: function () {
  31636. return this._viewRoot;
  31637. },
  31638. /**
  31639. * @param {module:echarts/data/Tree~Node} [viewRoot]
  31640. */
  31641. resetViewRoot: function (viewRoot) {
  31642. viewRoot
  31643. ? (this._viewRoot = viewRoot)
  31644. : (viewRoot = this._viewRoot);
  31645. var root = this.getData().tree.root;
  31646. if (!viewRoot
  31647. || (viewRoot !== root && !root.contains(viewRoot))
  31648. ) {
  31649. this._viewRoot = root;
  31650. }
  31651. }
  31652. });
  31653. /**
  31654. * @param {Object} dataNode
  31655. */
  31656. function completeTreeValue(dataNode) {
  31657. // Postorder travel tree.
  31658. // If value of none-leaf node is not set,
  31659. // calculate it by suming up the value of all children.
  31660. var sum = 0;
  31661. zrUtil.each(dataNode.children, function (child) {
  31662. completeTreeValue(child);
  31663. var childValue = child.value;
  31664. zrUtil.isArray(childValue) && (childValue = childValue[0]);
  31665. sum += childValue;
  31666. });
  31667. var thisValue = dataNode.value;
  31668. if (zrUtil.isArray(thisValue)) {
  31669. thisValue = thisValue[0];
  31670. }
  31671. if (thisValue == null || isNaN(thisValue)) {
  31672. thisValue = sum;
  31673. }
  31674. // Value should not less than 0.
  31675. if (thisValue < 0) {
  31676. thisValue = 0;
  31677. }
  31678. zrUtil.isArray(dataNode.value)
  31679. ? (dataNode.value[0] = thisValue)
  31680. : (dataNode.value = thisValue);
  31681. }
  31682. /**
  31683. * set default to level configuration
  31684. */
  31685. function setDefault(levels, ecModel) {
  31686. var globalColorList = ecModel.get('color');
  31687. if (!globalColorList) {
  31688. return;
  31689. }
  31690. levels = levels || [];
  31691. var hasColorDefine;
  31692. zrUtil.each(levels, function (levelDefine) {
  31693. var model = new Model(levelDefine);
  31694. var modelColor = model.get('color');
  31695. if (model.get('itemStyle.normal.color')
  31696. || (modelColor && modelColor !== 'none')
  31697. ) {
  31698. hasColorDefine = true;
  31699. }
  31700. });
  31701. if (!hasColorDefine) {
  31702. var level0 = levels[0] || (levels[0] = {});
  31703. level0.color = globalColorList.slice();
  31704. }
  31705. return levels;
  31706. }
  31707. /***/ },
  31708. /* 194 */
  31709. /***/ function(module, exports, __webpack_require__) {
  31710. /**
  31711. * Tree data structure
  31712. *
  31713. * @module echarts/data/Tree
  31714. */
  31715. var zrUtil = __webpack_require__(4);
  31716. var Model = __webpack_require__(12);
  31717. var List = __webpack_require__(98);
  31718. var linkList = __webpack_require__(195);
  31719. var completeDimensions = __webpack_require__(110);
  31720. /**
  31721. * @constructor module:echarts/data/Tree~TreeNode
  31722. * @param {string} name
  31723. * @param {module:echarts/data/Tree} hostTree
  31724. */
  31725. var TreeNode = function (name, hostTree) {
  31726. /**
  31727. * @type {string}
  31728. */
  31729. this.name = name || '';
  31730. /**
  31731. * Depth of node
  31732. *
  31733. * @type {number}
  31734. * @readOnly
  31735. */
  31736. this.depth = 0;
  31737. /**
  31738. * Height of the subtree rooted at this node.
  31739. * @type {number}
  31740. * @readOnly
  31741. */
  31742. this.height = 0;
  31743. /**
  31744. * @type {module:echarts/data/Tree~TreeNode}
  31745. * @readOnly
  31746. */
  31747. this.parentNode = null;
  31748. /**
  31749. * Reference to list item.
  31750. * Do not persistent dataIndex outside,
  31751. * besause it may be changed by list.
  31752. * If dataIndex -1,
  31753. * this node is logical deleted (filtered) in list.
  31754. *
  31755. * @type {Object}
  31756. * @readOnly
  31757. */
  31758. this.dataIndex = -1;
  31759. /**
  31760. * @type {Array.<module:echarts/data/Tree~TreeNode>}
  31761. * @readOnly
  31762. */
  31763. this.children = [];
  31764. /**
  31765. * @type {Array.<module:echarts/data/Tree~TreeNode>}
  31766. * @pubilc
  31767. */
  31768. this.viewChildren = [];
  31769. /**
  31770. * @type {moduel:echarts/data/Tree}
  31771. * @readOnly
  31772. */
  31773. this.hostTree = hostTree;
  31774. };
  31775. TreeNode.prototype = {
  31776. constructor: TreeNode,
  31777. /**
  31778. * The node is removed.
  31779. * @return {boolean} is removed.
  31780. */
  31781. isRemoved: function () {
  31782. return this.dataIndex < 0;
  31783. },
  31784. /**
  31785. * Travel this subtree (include this node).
  31786. * Usage:
  31787. * node.eachNode(function () { ... }); // preorder
  31788. * node.eachNode('preorder', function () { ... }); // preorder
  31789. * node.eachNode('postorder', function () { ... }); // postorder
  31790. * node.eachNode(
  31791. * {order: 'postorder', attr: 'viewChildren'},
  31792. * function () { ... }
  31793. * ); // postorder
  31794. *
  31795. * @param {(Object|string)} options If string, means order.
  31796. * @param {string=} options.order 'preorder' or 'postorder'
  31797. * @param {string=} options.attr 'children' or 'viewChildren'
  31798. * @param {Function} cb If in preorder and return false,
  31799. * its subtree will not be visited.
  31800. * @param {Object} [context]
  31801. */
  31802. eachNode: function (options, cb, context) {
  31803. if (typeof options === 'function') {
  31804. context = cb;
  31805. cb = options;
  31806. options = null;
  31807. }
  31808. options = options || {};
  31809. if (zrUtil.isString(options)) {
  31810. options = {order: options};
  31811. }
  31812. var order = options.order || 'preorder';
  31813. var children = this[options.attr || 'children'];
  31814. var suppressVisitSub;
  31815. order === 'preorder' && (suppressVisitSub = cb.call(context, this));
  31816. for (var i = 0; !suppressVisitSub && i < children.length; i++) {
  31817. children[i].eachNode(options, cb, context);
  31818. }
  31819. order === 'postorder' && cb.call(context, this);
  31820. },
  31821. /**
  31822. * Update depth and height of this subtree.
  31823. *
  31824. * @param {number} depth
  31825. */
  31826. updateDepthAndHeight: function (depth) {
  31827. var height = 0;
  31828. this.depth = depth;
  31829. for (var i = 0; i < this.children.length; i++) {
  31830. var child = this.children[i];
  31831. child.updateDepthAndHeight(depth + 1);
  31832. if (child.height > height) {
  31833. height = child.height;
  31834. }
  31835. }
  31836. this.height = height + 1;
  31837. },
  31838. /**
  31839. * @param {string} id
  31840. * @return {module:echarts/data/Tree~TreeNode}
  31841. */
  31842. getNodeById: function (id) {
  31843. if (this.getId() === id) {
  31844. return this;
  31845. }
  31846. for (var i = 0, children = this.children, len = children.length; i < len; i++) {
  31847. var res = children[i].getNodeById(id);
  31848. if (res) {
  31849. return res;
  31850. }
  31851. }
  31852. },
  31853. /**
  31854. * @param {module:echarts/data/Tree~TreeNode} node
  31855. * @return {boolean}
  31856. */
  31857. contains: function (node) {
  31858. if (node === this) {
  31859. return true;
  31860. }
  31861. for (var i = 0, children = this.children, len = children.length; i < len; i++) {
  31862. var res = children[i].contains(node);
  31863. if (res) {
  31864. return res;
  31865. }
  31866. }
  31867. },
  31868. /**
  31869. * @param {boolean} includeSelf Default false.
  31870. * @return {Array.<module:echarts/data/Tree~TreeNode>} order: [root, child, grandchild, ...]
  31871. */
  31872. getAncestors: function (includeSelf) {
  31873. var ancestors = [];
  31874. var node = includeSelf ? this : this.parentNode;
  31875. while (node) {
  31876. ancestors.push(node);
  31877. node = node.parentNode;
  31878. }
  31879. ancestors.reverse();
  31880. return ancestors;
  31881. },
  31882. /**
  31883. * @param {string|Array=} [dimension='value'] Default 'value'. can be 0, 1, 2, 3
  31884. * @return {number} Value.
  31885. */
  31886. getValue: function (dimension) {
  31887. var data = this.hostTree.data;
  31888. return data.get(data.getDimension(dimension || 'value'), this.dataIndex);
  31889. },
  31890. /**
  31891. * @param {Object} layout
  31892. * @param {boolean=} [merge=false]
  31893. */
  31894. setLayout: function (layout, merge) {
  31895. this.dataIndex >= 0
  31896. && this.hostTree.data.setItemLayout(this.dataIndex, layout, merge);
  31897. },
  31898. /**
  31899. * @return {Object} layout
  31900. */
  31901. getLayout: function () {
  31902. return this.hostTree.data.getItemLayout(this.dataIndex);
  31903. },
  31904. /**
  31905. * @param {string} path
  31906. * @return {module:echarts/model/Model}
  31907. */
  31908. getModel: function (path) {
  31909. if (this.dataIndex < 0) {
  31910. return;
  31911. }
  31912. var hostTree = this.hostTree;
  31913. var itemModel = hostTree.data.getItemModel(this.dataIndex);
  31914. var levelModel = this.getLevelModel();
  31915. return itemModel.getModel(path, (levelModel || hostTree.hostModel).getModel(path));
  31916. },
  31917. /**
  31918. * @return {module:echarts/model/Model}
  31919. */
  31920. getLevelModel: function () {
  31921. return (this.hostTree.levelModels || [])[this.depth];
  31922. },
  31923. /**
  31924. * @example
  31925. * setItemVisual('color', color);
  31926. * setItemVisual({
  31927. * 'color': color
  31928. * });
  31929. */
  31930. setVisual: function (key, value) {
  31931. this.dataIndex >= 0
  31932. && this.hostTree.data.setItemVisual(this.dataIndex, key, value);
  31933. },
  31934. /**
  31935. * Get item visual
  31936. */
  31937. getVisual: function (key, ignoreParent) {
  31938. return this.hostTree.data.getItemVisual(this.dataIndex, key, ignoreParent);
  31939. },
  31940. /**
  31941. * @public
  31942. * @return {number}
  31943. */
  31944. getRawIndex: function () {
  31945. return this.hostTree.data.getRawIndex(this.dataIndex);
  31946. },
  31947. /**
  31948. * @public
  31949. * @return {string}
  31950. */
  31951. getId: function () {
  31952. return this.hostTree.data.getId(this.dataIndex);
  31953. }
  31954. };
  31955. /**
  31956. * @constructor
  31957. * @alias module:echarts/data/Tree
  31958. * @param {module:echarts/model/Model} hostModel
  31959. * @param {Array.<Object>} levelOptions
  31960. */
  31961. function Tree(hostModel, levelOptions) {
  31962. /**
  31963. * @type {module:echarts/data/Tree~TreeNode}
  31964. * @readOnly
  31965. */
  31966. this.root;
  31967. /**
  31968. * @type {module:echarts/data/List}
  31969. * @readOnly
  31970. */
  31971. this.data;
  31972. /**
  31973. * Index of each item is the same as the raw index of coresponding list item.
  31974. * @private
  31975. * @type {Array.<module:echarts/data/Tree~TreeNode}
  31976. */
  31977. this._nodes = [];
  31978. /**
  31979. * @private
  31980. * @readOnly
  31981. * @type {module:echarts/model/Model}
  31982. */
  31983. this.hostModel = hostModel;
  31984. /**
  31985. * @private
  31986. * @readOnly
  31987. * @type {Array.<module:echarts/model/Model}
  31988. */
  31989. this.levelModels = zrUtil.map(levelOptions || [], function (levelDefine) {
  31990. return new Model(levelDefine, hostModel, hostModel.ecModel);
  31991. });
  31992. }
  31993. Tree.prototype = {
  31994. constructor: Tree,
  31995. type: 'tree',
  31996. /**
  31997. * Travel this subtree (include this node).
  31998. * Usage:
  31999. * node.eachNode(function () { ... }); // preorder
  32000. * node.eachNode('preorder', function () { ... }); // preorder
  32001. * node.eachNode('postorder', function () { ... }); // postorder
  32002. * node.eachNode(
  32003. * {order: 'postorder', attr: 'viewChildren'},
  32004. * function () { ... }
  32005. * ); // postorder
  32006. *
  32007. * @param {(Object|string)} options If string, means order.
  32008. * @param {string=} options.order 'preorder' or 'postorder'
  32009. * @param {string=} options.attr 'children' or 'viewChildren'
  32010. * @param {Function} cb
  32011. * @param {Object} [context]
  32012. */
  32013. eachNode: function(options, cb, context) {
  32014. this.root.eachNode(options, cb, context);
  32015. },
  32016. /**
  32017. * @param {number} dataIndex
  32018. * @return {module:echarts/data/Tree~TreeNode}
  32019. */
  32020. getNodeByDataIndex: function (dataIndex) {
  32021. var rawIndex = this.data.getRawIndex(dataIndex);
  32022. return this._nodes[rawIndex];
  32023. },
  32024. /**
  32025. * @param {string} name
  32026. * @return {module:echarts/data/Tree~TreeNode}
  32027. */
  32028. getNodeByName: function (name) {
  32029. return this.root.getNodeByName(name);
  32030. },
  32031. /**
  32032. * Update item available by list,
  32033. * when list has been performed options like 'filterSelf' or 'map'.
  32034. */
  32035. update: function () {
  32036. var data = this.data;
  32037. var nodes = this._nodes;
  32038. for (var i = 0, len = nodes.length; i < len; i++) {
  32039. nodes[i].dataIndex = -1;
  32040. }
  32041. for (var i = 0, len = data.count(); i < len; i++) {
  32042. nodes[data.getRawIndex(i)].dataIndex = i;
  32043. }
  32044. },
  32045. /**
  32046. * Clear all layouts
  32047. */
  32048. clearLayouts: function () {
  32049. this.data.clearItemLayouts();
  32050. }
  32051. };
  32052. /**
  32053. * data node format:
  32054. * {
  32055. * name: ...
  32056. * value: ...
  32057. * children: [
  32058. * {
  32059. * name: ...
  32060. * value: ...
  32061. * children: ...
  32062. * },
  32063. * ...
  32064. * ]
  32065. * }
  32066. *
  32067. * @static
  32068. * @param {Objec} dataRoot Root node.
  32069. * @param {module:echarts/model/Model} hostModel
  32070. * @param {Array.<Object>} levelOptions
  32071. * @return module:echarts/data/Tree
  32072. */
  32073. Tree.createTree = function (dataRoot, hostModel, levelOptions) {
  32074. var tree = new Tree(hostModel, levelOptions);
  32075. var listData = [];
  32076. var dimMax = 1;
  32077. buildHierarchy(dataRoot);
  32078. function buildHierarchy(dataNode, parentNode) {
  32079. var value = dataNode.value;
  32080. dimMax = Math.max(dimMax, zrUtil.isArray(value) ? value.length : 1);
  32081. listData.push(dataNode);
  32082. var node = new TreeNode(dataNode.name, tree);
  32083. parentNode
  32084. ? addChild(node, parentNode)
  32085. : (tree.root = node);
  32086. tree._nodes.push(node);
  32087. var children = dataNode.children;
  32088. if (children) {
  32089. for (var i = 0; i < children.length; i++) {
  32090. buildHierarchy(children[i], node);
  32091. }
  32092. }
  32093. }
  32094. tree.root.updateDepthAndHeight(0);
  32095. var dimensions = completeDimensions([{name: 'value'}], listData, {dimCount: dimMax});
  32096. var list = new List(dimensions, hostModel);
  32097. list.initData(listData);
  32098. linkList({
  32099. mainData: list,
  32100. struct: tree,
  32101. structAttr: 'tree'
  32102. });
  32103. tree.update();
  32104. return tree;
  32105. };
  32106. /**
  32107. * It is needed to consider the mess of 'list', 'hostModel' when creating a TreeNote,
  32108. * so this function is not ready and not necessary to be public.
  32109. *
  32110. * @param {(module:echarts/data/Tree~TreeNode|Object)} child
  32111. */
  32112. function addChild(child, node) {
  32113. var children = node.children;
  32114. if (child.parentNode === node) {
  32115. return;
  32116. }
  32117. children.push(child);
  32118. child.parentNode = node;
  32119. }
  32120. module.exports = Tree;
  32121. /***/ },
  32122. /* 195 */
  32123. /***/ function(module, exports, __webpack_require__) {
  32124. /**
  32125. * Link lists and struct (graph or tree)
  32126. */
  32127. var zrUtil = __webpack_require__(4);
  32128. var each = zrUtil.each;
  32129. var DATAS = '\0__link_datas';
  32130. var MAIN_DATA = '\0__link_mainData';
  32131. // Caution:
  32132. // In most case, either list or its shallow clones (see list.cloneShallow)
  32133. // is active in echarts process. So considering heap memory consumption,
  32134. // we do not clone tree or graph, but share them among list and its shallow clones.
  32135. // But in some rare case, we have to keep old list (like do animation in chart). So
  32136. // please take care that both the old list and the new list share the same tree/graph.
  32137. /**
  32138. * @param {Object} opt
  32139. * @param {module:echarts/data/List} opt.mainData
  32140. * @param {Object} [opt.struct] For example, instance of Graph or Tree.
  32141. * @param {string} [opt.structAttr] designation: list[structAttr] = struct;
  32142. * @param {Object} [opt.datas] {dataType: data},
  32143. * like: {node: nodeList, edge: edgeList}.
  32144. * Should contain mainData.
  32145. * @param {Object} [opt.datasAttr] {dataType: attr},
  32146. * designation: struct[datasAttr[dataType]] = list;
  32147. */
  32148. function linkList(opt) {
  32149. var mainData = opt.mainData;
  32150. var datas = opt.datas;
  32151. if (!datas) {
  32152. datas = {main: mainData};
  32153. opt.datasAttr = {main: 'data'};
  32154. }
  32155. opt.datas = opt.mainData = null;
  32156. linkAll(mainData, datas, opt);
  32157. // Porxy data original methods.
  32158. each(datas, function (data) {
  32159. each(mainData.TRANSFERABLE_METHODS, function (methodName) {
  32160. data.wrapMethod(methodName, zrUtil.curry(transferInjection, opt));
  32161. });
  32162. });
  32163. // Beyond transfer, additional features should be added to `cloneShallow`.
  32164. mainData.wrapMethod('cloneShallow', zrUtil.curry(cloneShallowInjection, opt));
  32165. // Only mainData trigger change, because struct.update may trigger
  32166. // another changable methods, which may bring about dead lock.
  32167. each(mainData.CHANGABLE_METHODS, function (methodName) {
  32168. mainData.wrapMethod(methodName, zrUtil.curry(changeInjection, opt));
  32169. });
  32170. // Make sure datas contains mainData.
  32171. zrUtil.assert(datas[mainData.dataType] === mainData);
  32172. }
  32173. function transferInjection(opt, res) {
  32174. if (isMainData(this)) {
  32175. // Transfer datas to new main data.
  32176. var datas = zrUtil.extend({}, this[DATAS]);
  32177. datas[this.dataType] = res;
  32178. linkAll(res, datas, opt);
  32179. }
  32180. else {
  32181. // Modify the reference in main data to point newData.
  32182. linkSingle(res, this.dataType, this[MAIN_DATA], opt);
  32183. }
  32184. return res;
  32185. }
  32186. function changeInjection(opt, res) {
  32187. opt.struct && opt.struct.update(this);
  32188. return res;
  32189. }
  32190. function cloneShallowInjection(opt, res) {
  32191. // cloneShallow, which brings about some fragilities, may be inappropriate
  32192. // to be exposed as an API. So for implementation simplicity we can make
  32193. // the restriction that cloneShallow of not-mainData should not be invoked
  32194. // outside, but only be invoked here.
  32195. each(res[DATAS], function (data, dataType) {
  32196. data !== res && linkSingle(data.cloneShallow(), dataType, res, opt);
  32197. });
  32198. return res;
  32199. }
  32200. /**
  32201. * Supplement method to List.
  32202. *
  32203. * @public
  32204. * @param {string} [dataType] If not specified, return mainData.
  32205. * @return {module:echarts/data/List}
  32206. */
  32207. function getLinkedData(dataType) {
  32208. var mainData = this[MAIN_DATA];
  32209. return (dataType == null || mainData == null)
  32210. ? mainData
  32211. : mainData[DATAS][dataType];
  32212. }
  32213. function isMainData(data) {
  32214. return data[MAIN_DATA] === data;
  32215. }
  32216. function linkAll(mainData, datas, opt) {
  32217. mainData[DATAS] = {};
  32218. each(datas, function (data, dataType) {
  32219. linkSingle(data, dataType, mainData, opt);
  32220. });
  32221. }
  32222. function linkSingle(data, dataType, mainData, opt) {
  32223. mainData[DATAS][dataType] = data;
  32224. data[MAIN_DATA] = mainData;
  32225. data.dataType = dataType;
  32226. if (opt.struct) {
  32227. data[opt.structAttr] = opt.struct;
  32228. opt.struct[opt.datasAttr[dataType]] = data;
  32229. }
  32230. // Supplement method.
  32231. data.getLinkedData = getLinkedData;
  32232. }
  32233. module.exports = linkList;
  32234. /***/ },
  32235. /* 196 */
  32236. /***/ function(module, exports, __webpack_require__) {
  32237. var zrUtil = __webpack_require__(4);
  32238. var helper = {
  32239. retrieveTargetInfo: function (payload, seriesModel) {
  32240. if (payload
  32241. && (
  32242. payload.type === 'treemapZoomToNode'
  32243. || payload.type === 'treemapRootToNode'
  32244. )
  32245. ) {
  32246. var root = seriesModel.getData().tree.root;
  32247. var targetNode = payload.targetNode;
  32248. if (targetNode && root.contains(targetNode)) {
  32249. return {node: targetNode};
  32250. }
  32251. var targetNodeId = payload.targetNodeId;
  32252. if (targetNodeId != null && (targetNode = root.getNodeById(targetNodeId))) {
  32253. return {node: targetNode};
  32254. }
  32255. }
  32256. },
  32257. // Not includes the given node at the last item.
  32258. getPathToRoot: function (node) {
  32259. var path = [];
  32260. while (node) {
  32261. node = node.parentNode;
  32262. node && path.push(node);
  32263. }
  32264. return path.reverse();
  32265. },
  32266. aboveViewRoot: function (viewRoot, node) {
  32267. var viewPath = helper.getPathToRoot(viewRoot);
  32268. return zrUtil.indexOf(viewPath, node) >= 0;
  32269. },
  32270. // From root to the input node (the input node will be included).
  32271. wrapTreePathInfo: function (node, seriesModel) {
  32272. var treePathInfo = [];
  32273. while (node) {
  32274. var nodeDataIndex = node.dataIndex;
  32275. treePathInfo.push({
  32276. name: node.name,
  32277. dataIndex: nodeDataIndex,
  32278. value: seriesModel.getRawValue(nodeDataIndex)
  32279. });
  32280. node = node.parentNode;
  32281. }
  32282. treePathInfo.reverse();
  32283. return treePathInfo;
  32284. }
  32285. };
  32286. module.exports = helper;
  32287. /***/ },
  32288. /* 197 */
  32289. /***/ function(module, exports, __webpack_require__) {
  32290. var zrUtil = __webpack_require__(4);
  32291. var graphic = __webpack_require__(18);
  32292. var DataDiffer = __webpack_require__(99);
  32293. var helper = __webpack_require__(196);
  32294. var Breadcrumb = __webpack_require__(198);
  32295. var RoamController = __webpack_require__(182);
  32296. var BoundingRect = __webpack_require__(9);
  32297. var matrix = __webpack_require__(11);
  32298. var animationUtil = __webpack_require__(199);
  32299. var bind = zrUtil.bind;
  32300. var Group = graphic.Group;
  32301. var Rect = graphic.Rect;
  32302. var each = zrUtil.each;
  32303. var DRAG_THRESHOLD = 3;
  32304. var PATH_LABEL_NORMAL = ['label', 'normal'];
  32305. var PATH_LABEL_EMPHASIS = ['label', 'emphasis'];
  32306. var Z_BASE = 10; // Should bigger than every z.
  32307. var Z_BG = 1;
  32308. var Z_CONTENT = 2;
  32309. module.exports = __webpack_require__(1).extendChartView({
  32310. type: 'treemap',
  32311. /**
  32312. * @override
  32313. */
  32314. init: function (o, api) {
  32315. /**
  32316. * @private
  32317. * @type {module:zrender/container/Group}
  32318. */
  32319. this._containerGroup;
  32320. /**
  32321. * @private
  32322. * @type {Object.<string, Array.<module:zrender/container/Group>>}
  32323. */
  32324. this._storage = createStorage();
  32325. /**
  32326. * @private
  32327. * @type {module:echarts/data/Tree}
  32328. */
  32329. this._oldTree;
  32330. /**
  32331. * @private
  32332. * @type {module:echarts/chart/treemap/Breadcrumb}
  32333. */
  32334. this._breadcrumb;
  32335. /**
  32336. * @private
  32337. * @type {module:echarts/component/helper/RoamController}
  32338. */
  32339. this._controller;
  32340. /**
  32341. * 'ready', 'animating'
  32342. * @private
  32343. */
  32344. this._state = 'ready';
  32345. /**
  32346. * @private
  32347. * @type {boolean}
  32348. */
  32349. this._mayClick;
  32350. },
  32351. /**
  32352. * @override
  32353. */
  32354. render: function (seriesModel, ecModel, api, payload) {
  32355. var models = ecModel.findComponents({
  32356. mainType: 'series', subType: 'treemap', query: payload
  32357. });
  32358. if (zrUtil.indexOf(models, seriesModel) < 0) {
  32359. return;
  32360. }
  32361. this.seriesModel = seriesModel;
  32362. this.api = api;
  32363. this.ecModel = ecModel;
  32364. var targetInfo = helper.retrieveTargetInfo(payload, seriesModel);
  32365. var payloadType = payload && payload.type;
  32366. var layoutInfo = seriesModel.layoutInfo;
  32367. var isInit = !this._oldTree;
  32368. var thisStorage = this._storage;
  32369. // Mark new root when action is treemapRootToNode.
  32370. var reRoot = (payloadType === 'treemapRootToNode' && targetInfo && thisStorage)
  32371. ? {
  32372. rootNodeGroup: thisStorage.nodeGroup[targetInfo.node.getRawIndex()],
  32373. direction: payload.direction
  32374. }
  32375. : null;
  32376. var containerGroup = this._giveContainerGroup(layoutInfo);
  32377. var renderResult = this._doRender(containerGroup, seriesModel, reRoot);
  32378. (
  32379. !isInit && (
  32380. !payloadType
  32381. || payloadType === 'treemapZoomToNode'
  32382. || payloadType === 'treemapRootToNode'
  32383. )
  32384. )
  32385. ? this._doAnimation(containerGroup, renderResult, seriesModel, reRoot)
  32386. : renderResult.renderFinally();
  32387. this._resetController(api);
  32388. this._renderBreadcrumb(seriesModel, api, targetInfo);
  32389. },
  32390. /**
  32391. * @private
  32392. */
  32393. _giveContainerGroup: function (layoutInfo) {
  32394. var containerGroup = this._containerGroup;
  32395. if (!containerGroup) {
  32396. // FIXME
  32397. // 加一层containerGroup是为了clip,但是现在clip功能并没有实现。
  32398. containerGroup = this._containerGroup = new Group();
  32399. this._initEvents(containerGroup);
  32400. this.group.add(containerGroup);
  32401. }
  32402. containerGroup.attr('position', [layoutInfo.x, layoutInfo.y]);
  32403. return containerGroup;
  32404. },
  32405. /**
  32406. * @private
  32407. */
  32408. _doRender: function (containerGroup, seriesModel, reRoot) {
  32409. var thisTree = seriesModel.getData().tree;
  32410. var oldTree = this._oldTree;
  32411. // Clear last shape records.
  32412. var lastsForAnimation = createStorage();
  32413. var thisStorage = createStorage();
  32414. var oldStorage = this._storage;
  32415. var willInvisibleEls = [];
  32416. var doRenderNode = zrUtil.curry(
  32417. renderNode, seriesModel,
  32418. thisStorage, oldStorage, reRoot,
  32419. lastsForAnimation, willInvisibleEls
  32420. );
  32421. // Notice: when thisTree and oldTree are the same tree (see list.cloneShadow),
  32422. // the oldTree is actually losted, so we can not find all of the old graphic
  32423. // elements from tree. So we use this stragegy: make element storage, move
  32424. // from old storage to new storage, clear old storage.
  32425. dualTravel(
  32426. thisTree.root ? [thisTree.root] : [],
  32427. (oldTree && oldTree.root) ? [oldTree.root] : [],
  32428. containerGroup,
  32429. thisTree === oldTree || !oldTree,
  32430. 0
  32431. );
  32432. // Process all removing.
  32433. var willDeleteEls = clearStorage(oldStorage);
  32434. this._oldTree = thisTree;
  32435. this._storage = thisStorage;
  32436. return {
  32437. lastsForAnimation: lastsForAnimation,
  32438. willDeleteEls: willDeleteEls,
  32439. renderFinally: renderFinally
  32440. };
  32441. function dualTravel(thisViewChildren, oldViewChildren, parentGroup, sameTree, depth) {
  32442. // When 'render' is triggered by action,
  32443. // 'this' and 'old' may be the same tree,
  32444. // we use rawIndex in that case.
  32445. if (sameTree) {
  32446. oldViewChildren = thisViewChildren;
  32447. each(thisViewChildren, function (child, index) {
  32448. !child.isRemoved() && processNode(index, index);
  32449. });
  32450. }
  32451. // Diff hierarchically (diff only in each subtree, but not whole).
  32452. // because, consistency of view is important.
  32453. else {
  32454. (new DataDiffer(oldViewChildren, thisViewChildren, getKey, getKey))
  32455. .add(processNode)
  32456. .update(processNode)
  32457. .remove(zrUtil.curry(processNode, null))
  32458. .execute();
  32459. }
  32460. function getKey(node) {
  32461. // Identify by name or raw index.
  32462. return node.getId();
  32463. }
  32464. function processNode(newIndex, oldIndex) {
  32465. var thisNode = newIndex != null ? thisViewChildren[newIndex] : null;
  32466. var oldNode = oldIndex != null ? oldViewChildren[oldIndex] : null;
  32467. var group = doRenderNode(thisNode, oldNode, parentGroup, depth);
  32468. group && dualTravel(
  32469. thisNode && thisNode.viewChildren || [],
  32470. oldNode && oldNode.viewChildren || [],
  32471. group,
  32472. sameTree,
  32473. depth + 1
  32474. );
  32475. }
  32476. }
  32477. function clearStorage(storage) {
  32478. var willDeleteEls = createStorage();
  32479. storage && each(storage, function (store, storageName) {
  32480. var delEls = willDeleteEls[storageName];
  32481. each(store, function (el) {
  32482. el && (delEls.push(el), el.__tmWillDelete = 1);
  32483. });
  32484. });
  32485. return willDeleteEls;
  32486. }
  32487. function renderFinally() {
  32488. each(willDeleteEls, function (els) {
  32489. each(els, function (el) {
  32490. el.parent && el.parent.remove(el);
  32491. });
  32492. });
  32493. each(willInvisibleEls, function (el) {
  32494. el.invisible = true;
  32495. // Setting invisible is for optimizing, so no need to set dirty,
  32496. // just mark as invisible.
  32497. el.dirty();
  32498. });
  32499. }
  32500. },
  32501. /**
  32502. * @private
  32503. */
  32504. _doAnimation: function (containerGroup, renderResult, seriesModel, reRoot) {
  32505. if (!seriesModel.get('animation')) {
  32506. return;
  32507. }
  32508. var duration = seriesModel.get('animationDurationUpdate');
  32509. var easing = seriesModel.get('animationEasing');
  32510. var animationWrap = animationUtil.createWrap();
  32511. // Make delete animations.
  32512. each(renderResult.willDeleteEls, function (store, storageName) {
  32513. each(store, function (el, rawIndex) {
  32514. if (el.invisible) {
  32515. return;
  32516. }
  32517. var parent = el.parent; // Always has parent, and parent is nodeGroup.
  32518. var target;
  32519. if (reRoot && reRoot.direction === 'drillDown') {
  32520. target = parent === reRoot.rootNodeGroup
  32521. // This is the content element of view root.
  32522. // Only `content` will enter this branch, because
  32523. // `background` and `nodeGroup` will not be deleted.
  32524. ? {
  32525. shape: {
  32526. x: 0,
  32527. y: 0,
  32528. width: parent.__tmNodeWidth,
  32529. height: parent.__tmNodeHeight
  32530. },
  32531. style: {
  32532. opacity: 0
  32533. }
  32534. }
  32535. // Others.
  32536. : {style: {opacity: 0}};
  32537. }
  32538. else {
  32539. var targetX = 0;
  32540. var targetY = 0;
  32541. if (!parent.__tmWillDelete) {
  32542. // Let node animate to right-bottom corner, cooperating with fadeout,
  32543. // which is appropriate for user understanding.
  32544. // Divided by 2 for reRoot rolling up effect.
  32545. targetX = parent.__tmNodeWidth / 2;
  32546. targetY = parent.__tmNodeHeight / 2;
  32547. }
  32548. target = storageName === 'nodeGroup'
  32549. ? {position: [targetX, targetY], style: {opacity: 0}}
  32550. : {
  32551. shape: {x: targetX, y: targetY, width: 0, height: 0},
  32552. style: {opacity: 0}
  32553. };
  32554. }
  32555. target && animationWrap.add(el, target, duration, easing);
  32556. });
  32557. });
  32558. // Make other animations
  32559. each(this._storage, function (store, storageName) {
  32560. each(store, function (el, rawIndex) {
  32561. var last = renderResult.lastsForAnimation[storageName][rawIndex];
  32562. var target = {};
  32563. if (!last) {
  32564. return;
  32565. }
  32566. if (storageName === 'nodeGroup') {
  32567. if (last.old) {
  32568. target.position = el.position.slice();
  32569. el.attr('position', last.old);
  32570. }
  32571. }
  32572. else {
  32573. if (last.old) {
  32574. target.shape = zrUtil.extend({}, el.shape);
  32575. el.setShape(last.old);
  32576. }
  32577. if (last.fadein) {
  32578. el.setStyle('opacity', 0);
  32579. target.style = {opacity: 1};
  32580. }
  32581. // When animation is stopped for succedent animation starting,
  32582. // el.style.opacity might not be 1
  32583. else if (el.style.opacity !== 1) {
  32584. target.style = {opacity: 1};
  32585. }
  32586. }
  32587. animationWrap.add(el, target, duration, easing);
  32588. });
  32589. }, this);
  32590. this._state = 'animating';
  32591. animationWrap
  32592. .done(bind(function () {
  32593. this._state = 'ready';
  32594. renderResult.renderFinally();
  32595. }, this))
  32596. .start();
  32597. },
  32598. /**
  32599. * @private
  32600. */
  32601. _resetController: function (api) {
  32602. var controller = this._controller;
  32603. // Init controller.
  32604. if (!controller) {
  32605. controller = this._controller = new RoamController(api.getZr());
  32606. controller.enable(this.seriesModel.get('roam'));
  32607. controller.on('pan', bind(this._onPan, this));
  32608. controller.on('zoom', bind(this._onZoom, this));
  32609. }
  32610. var rect = new BoundingRect(0, 0, api.getWidth(), api.getHeight());
  32611. controller.setPointerChecker(function (e, x, y) {
  32612. return rect.contain(x, y);
  32613. });
  32614. },
  32615. /**
  32616. * @private
  32617. */
  32618. _clearController: function () {
  32619. var controller = this._controller;
  32620. if (controller) {
  32621. controller.dispose();
  32622. controller = null;
  32623. }
  32624. },
  32625. /**
  32626. * @private
  32627. */
  32628. _onPan: function (dx, dy) {
  32629. this._mayClick = false;
  32630. if (this._state !== 'animating'
  32631. && (Math.abs(dx) > DRAG_THRESHOLD || Math.abs(dy) > DRAG_THRESHOLD)
  32632. ) {
  32633. // These param must not be cached.
  32634. var root = this.seriesModel.getData().tree.root;
  32635. if (!root) {
  32636. return;
  32637. }
  32638. var rootLayout = root.getLayout();
  32639. if (!rootLayout) {
  32640. return;
  32641. }
  32642. this.api.dispatchAction({
  32643. type: 'treemapMove',
  32644. from: this.uid,
  32645. seriesId: this.seriesModel.id,
  32646. rootRect: {
  32647. x: rootLayout.x + dx, y: rootLayout.y + dy,
  32648. width: rootLayout.width, height: rootLayout.height
  32649. }
  32650. });
  32651. }
  32652. },
  32653. /**
  32654. * @private
  32655. */
  32656. _onZoom: function (scale, mouseX, mouseY) {
  32657. this._mayClick = false;
  32658. if (this._state !== 'animating') {
  32659. // These param must not be cached.
  32660. var root = this.seriesModel.getData().tree.root;
  32661. if (!root) {
  32662. return;
  32663. }
  32664. var rootLayout = root.getLayout();
  32665. if (!rootLayout) {
  32666. return;
  32667. }
  32668. var rect = new BoundingRect(
  32669. rootLayout.x, rootLayout.y, rootLayout.width, rootLayout.height
  32670. );
  32671. var layoutInfo = this.seriesModel.layoutInfo;
  32672. // Transform mouse coord from global to containerGroup.
  32673. mouseX -= layoutInfo.x;
  32674. mouseY -= layoutInfo.y;
  32675. // Scale root bounding rect.
  32676. var m = matrix.create();
  32677. matrix.translate(m, m, [-mouseX, -mouseY]);
  32678. matrix.scale(m, m, [scale, scale]);
  32679. matrix.translate(m, m, [mouseX, mouseY]);
  32680. rect.applyTransform(m);
  32681. this.api.dispatchAction({
  32682. type: 'treemapRender',
  32683. from: this.uid,
  32684. seriesId: this.seriesModel.id,
  32685. rootRect: {
  32686. x: rect.x, y: rect.y,
  32687. width: rect.width, height: rect.height
  32688. }
  32689. });
  32690. }
  32691. },
  32692. /**
  32693. * @private
  32694. */
  32695. _initEvents: function (containerGroup) {
  32696. // FIXME
  32697. // 不用click以及silent的原因是,animate时视图设置silent true来避免click生效,
  32698. // 但是animate中,按下鼠标,animate结束后(silent设回为false)松开鼠标,
  32699. // 还是会触发click,期望是不触发。
  32700. // Mousedown occurs when drag start, and mouseup occurs when drag end,
  32701. // click event should not be triggered in that case.
  32702. containerGroup.on('mousedown', function (e) {
  32703. this._state === 'ready' && (this._mayClick = true);
  32704. }, this);
  32705. containerGroup.on('mouseup', function (e) {
  32706. if (this._mayClick) {
  32707. this._mayClick = false;
  32708. this._state === 'ready' && onClick.call(this, e);
  32709. }
  32710. }, this);
  32711. function onClick(e) {
  32712. var nodeClick = this.seriesModel.get('nodeClick', true);
  32713. if (!nodeClick) {
  32714. return;
  32715. }
  32716. var targetInfo = this.findTarget(e.offsetX, e.offsetY);
  32717. if (!targetInfo) {
  32718. return;
  32719. }
  32720. var node = targetInfo.node;
  32721. if (node.getLayout().isLeafRoot) {
  32722. this._rootToNode(targetInfo);
  32723. }
  32724. else {
  32725. if (nodeClick === 'zoomToNode') {
  32726. this._zoomToNode(targetInfo);
  32727. }
  32728. else if (nodeClick === 'link') {
  32729. var itemModel = node.hostTree.data.getItemModel(node.dataIndex);
  32730. var link = itemModel.get('link', true);
  32731. var linkTarget = itemModel.get('target', true) || 'blank';
  32732. link && window.open(link, linkTarget);
  32733. }
  32734. }
  32735. }
  32736. },
  32737. /**
  32738. * @private
  32739. */
  32740. _renderBreadcrumb: function (seriesModel, api, targetInfo) {
  32741. if (!targetInfo) {
  32742. targetInfo = seriesModel.get('leafDepth', true) != null
  32743. ? {node: seriesModel.getViewRoot()}
  32744. // FIXME
  32745. // better way?
  32746. // Find breadcrumb tail on center of containerGroup.
  32747. : this.findTarget(api.getWidth() / 2, api.getHeight() / 2);
  32748. if (!targetInfo) {
  32749. targetInfo = {node: seriesModel.getData().tree.root};
  32750. }
  32751. }
  32752. (this._breadcrumb || (this._breadcrumb = new Breadcrumb(this.group)))
  32753. .render(seriesModel, api, targetInfo.node, bind(onSelect, this));
  32754. function onSelect(node) {
  32755. if (this._state !== 'animating') {
  32756. helper.aboveViewRoot(seriesModel.getViewRoot(), node)
  32757. ? this._rootToNode({node: node})
  32758. : this._zoomToNode({node: node});
  32759. }
  32760. }
  32761. },
  32762. /**
  32763. * @override
  32764. */
  32765. remove: function () {
  32766. this._clearController();
  32767. this._containerGroup && this._containerGroup.removeAll();
  32768. this._storage = createStorage();
  32769. this._state = 'ready';
  32770. this._breadcrumb && this._breadcrumb.remove();
  32771. },
  32772. dispose: function () {
  32773. this._clearController();
  32774. },
  32775. /**
  32776. * @private
  32777. */
  32778. _zoomToNode: function (targetInfo) {
  32779. this.api.dispatchAction({
  32780. type: 'treemapZoomToNode',
  32781. from: this.uid,
  32782. seriesId: this.seriesModel.id,
  32783. targetNode: targetInfo.node
  32784. });
  32785. },
  32786. /**
  32787. * @private
  32788. */
  32789. _rootToNode: function (targetInfo) {
  32790. this.api.dispatchAction({
  32791. type: 'treemapRootToNode',
  32792. from: this.uid,
  32793. seriesId: this.seriesModel.id,
  32794. targetNode: targetInfo.node
  32795. });
  32796. },
  32797. /**
  32798. * @public
  32799. * @param {number} x Global coord x.
  32800. * @param {number} y Global coord y.
  32801. * @return {Object} info If not found, return undefined;
  32802. * @return {number} info.node Target node.
  32803. * @return {number} info.offsetX x refer to target node.
  32804. * @return {number} info.offsetY y refer to target node.
  32805. */
  32806. findTarget: function (x, y) {
  32807. var targetInfo;
  32808. var viewRoot = this.seriesModel.getViewRoot();
  32809. viewRoot.eachNode({attr: 'viewChildren', order: 'preorder'}, function (node) {
  32810. var bgEl = this._storage.background[node.getRawIndex()];
  32811. // If invisible, there might be no element.
  32812. if (bgEl) {
  32813. var point = bgEl.transformCoordToLocal(x, y);
  32814. var shape = bgEl.shape;
  32815. // For performance consideration, dont use 'getBoundingRect'.
  32816. if (shape.x <= point[0]
  32817. && point[0] <= shape.x + shape.width
  32818. && shape.y <= point[1]
  32819. && point[1] <= shape.y + shape.height
  32820. ) {
  32821. targetInfo = {node: node, offsetX: point[0], offsetY: point[1]};
  32822. }
  32823. else {
  32824. return false; // Suppress visit subtree.
  32825. }
  32826. }
  32827. }, this);
  32828. return targetInfo;
  32829. }
  32830. });
  32831. /**
  32832. * @inner
  32833. */
  32834. function createStorage() {
  32835. return {nodeGroup: [], background: [], content: []};
  32836. }
  32837. /**
  32838. * @inner
  32839. * @return Return undefined means do not travel further.
  32840. */
  32841. function renderNode(
  32842. seriesModel, thisStorage, oldStorage, reRoot,
  32843. lastsForAnimation, willInvisibleEls,
  32844. thisNode, oldNode, parentGroup, depth
  32845. ) {
  32846. // Whether under viewRoot.
  32847. if (!thisNode) {
  32848. // Deleting nodes will be performed finally. This method just find
  32849. // element from old storage, or create new element, set them to new
  32850. // storage, and set styles.
  32851. return;
  32852. }
  32853. var thisLayout = thisNode.getLayout();
  32854. if (!thisLayout || !thisLayout.isInView) {
  32855. return;
  32856. }
  32857. var thisWidth = thisLayout.width;
  32858. var thisHeight = thisLayout.height;
  32859. var thisInvisible = thisLayout.invisible;
  32860. var thisRawIndex = thisNode.getRawIndex();
  32861. var oldRawIndex = oldNode && oldNode.getRawIndex();
  32862. // Node group
  32863. var group = giveGraphic('nodeGroup', Group);
  32864. if (!group) {
  32865. return;
  32866. }
  32867. parentGroup.add(group);
  32868. // x,y are not set when el is above view root.
  32869. group.attr('position', [thisLayout.x || 0, thisLayout.y || 0]);
  32870. group.__tmNodeWidth = thisWidth;
  32871. group.__tmNodeHeight = thisHeight;
  32872. if (thisLayout.isAboveViewRoot) {
  32873. return group;
  32874. }
  32875. // Background
  32876. var bg = giveGraphic('background', Rect, depth, Z_BG);
  32877. if (bg) {
  32878. bg.setShape({x: 0, y: 0, width: thisWidth, height: thisHeight});
  32879. updateStyle(bg, function () {
  32880. bg.setStyle('fill', thisNode.getVisual('borderColor', true));
  32881. });
  32882. group.add(bg);
  32883. }
  32884. var thisViewChildren = thisNode.viewChildren;
  32885. // No children, render content.
  32886. if (!thisViewChildren || !thisViewChildren.length) {
  32887. var content = giveGraphic('content', Rect, depth, Z_CONTENT);
  32888. content && renderContent(group);
  32889. }
  32890. return group;
  32891. // ----------------------------
  32892. // | Procedures in renderNode |
  32893. // ----------------------------
  32894. function renderContent(group) {
  32895. // For tooltip.
  32896. content.dataIndex = thisNode.dataIndex;
  32897. content.seriesIndex = seriesModel.seriesIndex;
  32898. var borderWidth = thisLayout.borderWidth;
  32899. var contentWidth = Math.max(thisWidth - 2 * borderWidth, 0);
  32900. var contentHeight = Math.max(thisHeight - 2 * borderWidth, 0);
  32901. content.culling = true;
  32902. content.setShape({
  32903. x: borderWidth,
  32904. y: borderWidth,
  32905. width: contentWidth,
  32906. height: contentHeight
  32907. });
  32908. var visualColor = thisNode.getVisual('color', true);
  32909. updateStyle(content, function () {
  32910. var normalStyle = {fill: visualColor};
  32911. var emphasisStyle = thisNode.getModel('itemStyle.emphasis').getItemStyle();
  32912. prepareText(normalStyle, emphasisStyle, visualColor, contentWidth, contentHeight);
  32913. content.setStyle(normalStyle);
  32914. graphic.setHoverStyle(content, emphasisStyle);
  32915. });
  32916. group.add(content);
  32917. }
  32918. function updateStyle(element, cb) {
  32919. if (!thisInvisible) {
  32920. // If invisible, do not set visual, otherwise the element will
  32921. // change immediately before animation. We think it is OK to
  32922. // remain its origin color when moving out of the view window.
  32923. cb();
  32924. if (!element.__tmWillVisible) {
  32925. element.invisible = false;
  32926. }
  32927. }
  32928. else {
  32929. // Delay invisible setting utill animation finished,
  32930. // avoid element vanish suddenly before animation.
  32931. !element.invisible && willInvisibleEls.push(element);
  32932. }
  32933. }
  32934. function prepareText(normalStyle, emphasisStyle, visualColor, contentWidth, contentHeight) {
  32935. var nodeModel = thisNode.getModel();
  32936. var text = nodeModel.get('name');
  32937. if (thisLayout.isLeafRoot) {
  32938. var iconChar = seriesModel.get('drillDownIcon', true);
  32939. text = iconChar ? iconChar + ' ' + text : text;
  32940. }
  32941. setText(
  32942. text, normalStyle, nodeModel, PATH_LABEL_NORMAL,
  32943. visualColor, contentWidth, contentHeight
  32944. );
  32945. setText(
  32946. text, emphasisStyle, nodeModel, PATH_LABEL_EMPHASIS,
  32947. visualColor, contentWidth, contentHeight
  32948. );
  32949. }
  32950. function setText(text, style, nodeModel, labelPath, visualColor, contentWidth, contentHeight) {
  32951. var labelModel = nodeModel.getModel(labelPath);
  32952. var labelTextStyleModel = labelModel.getModel('textStyle');
  32953. graphic.setText(style, labelModel, visualColor);
  32954. // text.align and text.baseline is not included by graphic.setText,
  32955. // because in most cases the two attributes are not exposed to user,
  32956. // except in treemap.
  32957. style.textAlign = labelTextStyleModel.get('align');
  32958. style.textVerticalAlign = labelTextStyleModel.get('baseline');
  32959. var textRect = labelTextStyleModel.getTextRect(text);
  32960. if (!labelModel.getShallow('show') || textRect.height > contentHeight) {
  32961. style.text = '';
  32962. }
  32963. else if (textRect.width > contentWidth) {
  32964. style.text = labelTextStyleModel.get('ellipsis')
  32965. ? labelTextStyleModel.truncateText(
  32966. text, contentWidth, null, {minChar: 2}
  32967. )
  32968. : '';
  32969. }
  32970. else {
  32971. style.text = text;
  32972. }
  32973. }
  32974. function giveGraphic(storageName, Ctor, depth, z) {
  32975. var element = oldRawIndex != null && oldStorage[storageName][oldRawIndex];
  32976. var lasts = lastsForAnimation[storageName];
  32977. if (element) {
  32978. // Remove from oldStorage
  32979. oldStorage[storageName][oldRawIndex] = null;
  32980. prepareAnimationWhenHasOld(lasts, element, storageName);
  32981. }
  32982. // If invisible and no old element, do not create new element (for optimizing).
  32983. else if (!thisInvisible) {
  32984. element = new Ctor({z: calculateZ(depth, z)});
  32985. element.__tmDepth = depth;
  32986. element.__tmStorageName = storageName;
  32987. prepareAnimationWhenNoOld(lasts, element, storageName);
  32988. }
  32989. // Set to thisStorage
  32990. return (thisStorage[storageName][thisRawIndex] = element);
  32991. }
  32992. function prepareAnimationWhenHasOld(lasts, element, storageName) {
  32993. var lastCfg = lasts[thisRawIndex] = {};
  32994. lastCfg.old = storageName === 'nodeGroup'
  32995. ? element.position.slice()
  32996. : zrUtil.extend({}, element.shape);
  32997. }
  32998. // If a element is new, we need to find the animation start point carefully,
  32999. // otherwise it will looks strange when 'zoomToNode'.
  33000. function prepareAnimationWhenNoOld(lasts, element, storageName) {
  33001. var lastCfg = lasts[thisRawIndex] = {};
  33002. var parentNode = thisNode.parentNode;
  33003. if (parentNode && (!reRoot || reRoot.direction === 'drillDown')) {
  33004. var parentOldX = 0;
  33005. var parentOldY = 0;
  33006. // New nodes appear from right-bottom corner in 'zoomToNode' animation.
  33007. // For convenience, get old bounding rect from background.
  33008. var parentOldBg = lastsForAnimation.background[parentNode.getRawIndex()];
  33009. if (!reRoot && parentOldBg && parentOldBg.old) {
  33010. parentOldX = parentOldBg.old.width;
  33011. parentOldY = parentOldBg.old.height;
  33012. }
  33013. // When no parent old shape found, its parent is new too,
  33014. // so we can just use {x:0, y:0}.
  33015. lastCfg.old = storageName === 'nodeGroup'
  33016. ? [0, parentOldY]
  33017. : {x: parentOldX, y: parentOldY, width: 0, height: 0};
  33018. }
  33019. // Fade in, user can be aware that these nodes are new.
  33020. lastCfg.fadein = storageName !== 'nodeGroup';
  33021. }
  33022. }
  33023. // We can not set all backgroud with the same z, Because the behaviour of
  33024. // drill down and roll up differ background creation sequence from tree
  33025. // hierarchy sequence, which cause that lowser background element overlap
  33026. // upper ones. So we calculate z based on depth.
  33027. // Moreover, we try to shrink down z interval to [0, 1] to avoid that
  33028. // treemap with large z overlaps other components.
  33029. function calculateZ(depth, zInLevel) {
  33030. var zb = depth * Z_BASE + zInLevel;
  33031. return (zb - 1) / zb;
  33032. }
  33033. /***/ },
  33034. /* 198 */
  33035. /***/ function(module, exports, __webpack_require__) {
  33036. var graphic = __webpack_require__(18);
  33037. var layout = __webpack_require__(71);
  33038. var zrUtil = __webpack_require__(4);
  33039. var helper = __webpack_require__(196);
  33040. var TEXT_PADDING = 8;
  33041. var ITEM_GAP = 8;
  33042. var ARRAY_LENGTH = 5;
  33043. function Breadcrumb(containerGroup) {
  33044. /**
  33045. * @private
  33046. * @type {module:zrender/container/Group}
  33047. */
  33048. this.group = new graphic.Group();
  33049. containerGroup.add(this.group);
  33050. }
  33051. Breadcrumb.prototype = {
  33052. constructor: Breadcrumb,
  33053. render: function (seriesModel, api, targetNode, onSelect) {
  33054. var model = seriesModel.getModel('breadcrumb');
  33055. var thisGroup = this.group;
  33056. thisGroup.removeAll();
  33057. if (!model.get('show') || !targetNode) {
  33058. return;
  33059. }
  33060. var normalStyleModel = model.getModel('itemStyle.normal');
  33061. // var emphasisStyleModel = model.getModel('itemStyle.emphasis');
  33062. var textStyleModel = normalStyleModel.getModel('textStyle');
  33063. var layoutParam = {
  33064. pos: {
  33065. left: model.get('left'),
  33066. right: model.get('right'),
  33067. top: model.get('top'),
  33068. bottom: model.get('bottom')
  33069. },
  33070. box: {
  33071. width: api.getWidth(),
  33072. height: api.getHeight()
  33073. },
  33074. emptyItemWidth: model.get('emptyItemWidth'),
  33075. totalWidth: 0,
  33076. renderList: []
  33077. };
  33078. this._prepare(targetNode, layoutParam, textStyleModel);
  33079. this._renderContent(seriesModel, layoutParam, normalStyleModel, textStyleModel, onSelect);
  33080. layout.positionElement(thisGroup, layoutParam.pos, layoutParam.box);
  33081. },
  33082. /**
  33083. * Prepare render list and total width
  33084. * @private
  33085. */
  33086. _prepare: function (targetNode, layoutParam, textStyleModel) {
  33087. for (var node = targetNode; node; node = node.parentNode) {
  33088. var text = node.getModel().get('name');
  33089. var textRect = textStyleModel.getTextRect(text);
  33090. var itemWidth = Math.max(
  33091. textRect.width + TEXT_PADDING * 2,
  33092. layoutParam.emptyItemWidth
  33093. );
  33094. layoutParam.totalWidth += itemWidth + ITEM_GAP;
  33095. layoutParam.renderList.push({node: node, text: text, width: itemWidth});
  33096. }
  33097. },
  33098. /**
  33099. * @private
  33100. */
  33101. _renderContent: function (
  33102. seriesModel, layoutParam, normalStyleModel, textStyleModel, onSelect
  33103. ) {
  33104. // Start rendering.
  33105. var lastX = 0;
  33106. var emptyItemWidth = layoutParam.emptyItemWidth;
  33107. var height = seriesModel.get('breadcrumb.height');
  33108. var availableSize = layout.getAvailableSize(layoutParam.pos, layoutParam.box);
  33109. var totalWidth = layoutParam.totalWidth;
  33110. var renderList = layoutParam.renderList;
  33111. for (var i = renderList.length - 1; i >= 0; i--) {
  33112. var item = renderList[i];
  33113. var itemNode = item.node;
  33114. var itemWidth = item.width;
  33115. var text = item.text;
  33116. // Hdie text and shorten width if necessary.
  33117. if (totalWidth > availableSize.width) {
  33118. totalWidth -= itemWidth - emptyItemWidth;
  33119. itemWidth = emptyItemWidth;
  33120. text = '';
  33121. }
  33122. var el = new graphic.Polygon({
  33123. shape: {
  33124. points: makeItemPoints(
  33125. lastX, 0, itemWidth, height,
  33126. i === renderList.length - 1, i === 0
  33127. )
  33128. },
  33129. style: zrUtil.defaults(
  33130. normalStyleModel.getItemStyle(),
  33131. {
  33132. lineJoin: 'bevel',
  33133. text: text,
  33134. textFill: textStyleModel.getTextColor(),
  33135. textFont: textStyleModel.getFont()
  33136. }
  33137. ),
  33138. z: 10,
  33139. onclick: zrUtil.curry(onSelect, itemNode)
  33140. });
  33141. this.group.add(el);
  33142. packEventData(el, seriesModel, itemNode);
  33143. lastX += itemWidth + ITEM_GAP;
  33144. }
  33145. },
  33146. /**
  33147. * @override
  33148. */
  33149. remove: function () {
  33150. this.group.removeAll();
  33151. }
  33152. };
  33153. function makeItemPoints(x, y, itemWidth, itemHeight, head, tail) {
  33154. var points = [
  33155. [head ? x : x - ARRAY_LENGTH, y],
  33156. [x + itemWidth, y],
  33157. [x + itemWidth, y + itemHeight],
  33158. [head ? x : x - ARRAY_LENGTH, y + itemHeight]
  33159. ];
  33160. !tail && points.splice(2, 0, [x + itemWidth + ARRAY_LENGTH, y + itemHeight / 2]);
  33161. !head && points.push([x, y + itemHeight / 2]);
  33162. return points;
  33163. }
  33164. // Package custom mouse event.
  33165. function packEventData(el, seriesModel, itemNode) {
  33166. el.eventData = {
  33167. componentType: 'series',
  33168. componentSubType: 'treemap',
  33169. seriesIndex: seriesModel.componentIndex,
  33170. seriesName: seriesModel.name,
  33171. seriesType: 'treemap',
  33172. selfType: 'breadcrumb', // Distinguish with click event on treemap node.
  33173. nodeData: {
  33174. dataIndex: itemNode && itemNode.dataIndex,
  33175. name: itemNode && itemNode.name
  33176. },
  33177. treePathInfo: itemNode && helper.wrapTreePathInfo(itemNode, seriesModel)
  33178. };
  33179. }
  33180. module.exports = Breadcrumb;
  33181. /***/ },
  33182. /* 199 */
  33183. /***/ function(module, exports, __webpack_require__) {
  33184. var zrUtil = __webpack_require__(4);
  33185. /**
  33186. * @param {number} [time=500] Time in ms
  33187. * @param {string} [easing='linear']
  33188. * @param {number} [delay=0]
  33189. * @param {Function} [callback]
  33190. *
  33191. * @example
  33192. * // Animate position
  33193. * animation
  33194. * .createWrap()
  33195. * .add(el1, {position: [10, 10]})
  33196. * .add(el2, {shape: {width: 500}, style: {fill: 'red'}}, 400)
  33197. * .done(function () { // done })
  33198. * .start('cubicOut');
  33199. */
  33200. function createWrap() {
  33201. var storage = [];
  33202. var elExistsMap = {};
  33203. var doneCallback;
  33204. return {
  33205. /**
  33206. * Caution: a el can only be added once, otherwise 'done'
  33207. * might not be called. This method checks this (by el.id),
  33208. * suppresses adding and returns false when existing el found.
  33209. *
  33210. * @param {modele:zrender/Element} el
  33211. * @param {Object} target
  33212. * @param {number} [time=500]
  33213. * @param {number} [delay=0]
  33214. * @param {string} [easing='linear']
  33215. * @return {boolean} Whether adding succeeded.
  33216. *
  33217. * @example
  33218. * add(el, target, time, delay, easing);
  33219. * add(el, target, time, easing);
  33220. * add(el, target, time);
  33221. * add(el, target);
  33222. */
  33223. add: function (el, target, time, delay, easing) {
  33224. if (zrUtil.isString(delay)) {
  33225. easing = delay;
  33226. delay = 0;
  33227. }
  33228. if (elExistsMap[el.id]) {
  33229. return false;
  33230. }
  33231. elExistsMap[el.id] = 1;
  33232. storage.push(
  33233. {el: el, target: target, time: time, delay: delay, easing: easing}
  33234. );
  33235. return true;
  33236. },
  33237. /**
  33238. * Only execute when animation finished. Will not execute when any
  33239. * of 'stop' or 'stopAnimation' called.
  33240. *
  33241. * @param {Function} callback
  33242. */
  33243. done: function (callback) {
  33244. doneCallback = callback;
  33245. return this;
  33246. },
  33247. /**
  33248. * Will stop exist animation firstly.
  33249. */
  33250. start: function () {
  33251. var count = storage.length;
  33252. for (var i = 0, len = storage.length; i < len; i++) {
  33253. var item = storage[i];
  33254. item.el.animateTo(item.target, item.time, item.delay, item.easing, done);
  33255. }
  33256. return this;
  33257. function done() {
  33258. count--;
  33259. if (!count) {
  33260. storage.length = 0;
  33261. elExistsMap = {};
  33262. doneCallback && doneCallback();
  33263. }
  33264. }
  33265. }
  33266. };
  33267. }
  33268. module.exports = {createWrap: createWrap};
  33269. /***/ },
  33270. /* 200 */
  33271. /***/ function(module, exports, __webpack_require__) {
  33272. /**
  33273. * @file Treemap action
  33274. */
  33275. var echarts = __webpack_require__(1);
  33276. var helper = __webpack_require__(196);
  33277. var noop = function () {};
  33278. var actionTypes = [
  33279. 'treemapZoomToNode',
  33280. 'treemapRender',
  33281. 'treemapMove'
  33282. ];
  33283. for (var i = 0; i < actionTypes.length; i++) {
  33284. echarts.registerAction({type: actionTypes[i], update: 'updateView'}, noop);
  33285. }
  33286. echarts.registerAction(
  33287. {type: 'treemapRootToNode', update: 'updateView'},
  33288. function (payload, ecModel) {
  33289. ecModel.eachComponent(
  33290. {mainType: 'series', subType: 'treemap', query: payload},
  33291. handleRootToNode
  33292. );
  33293. function handleRootToNode(model, index) {
  33294. var targetInfo = helper.retrieveTargetInfo(payload, model);
  33295. if (targetInfo) {
  33296. var originViewRoot = model.getViewRoot();
  33297. if (originViewRoot) {
  33298. payload.direction = helper.aboveViewRoot(originViewRoot, targetInfo.node)
  33299. ? 'rollUp' : 'drillDown';
  33300. }
  33301. model.resetViewRoot(targetInfo.node);
  33302. }
  33303. }
  33304. }
  33305. );
  33306. /***/ },
  33307. /* 201 */
  33308. /***/ function(module, exports, __webpack_require__) {
  33309. var VisualMapping = __webpack_require__(202);
  33310. var zrColor = __webpack_require__(31);
  33311. var zrUtil = __webpack_require__(4);
  33312. var isArray = zrUtil.isArray;
  33313. var ITEM_STYLE_NORMAL = 'itemStyle.normal';
  33314. module.exports = function (ecModel, api, payload) {
  33315. var condition = {mainType: 'series', subType: 'treemap', query: payload};
  33316. ecModel.eachComponent(condition, function (seriesModel) {
  33317. var tree = seriesModel.getData().tree;
  33318. var root = tree.root;
  33319. var seriesItemStyleModel = seriesModel.getModel(ITEM_STYLE_NORMAL);
  33320. if (root.isRemoved()) {
  33321. return;
  33322. }
  33323. var levelItemStyles = zrUtil.map(tree.levelModels, function (levelModel) {
  33324. return levelModel ? levelModel.get(ITEM_STYLE_NORMAL) : null;
  33325. });
  33326. travelTree(
  33327. root, // Visual should calculate from tree root but not view root.
  33328. {},
  33329. levelItemStyles,
  33330. seriesItemStyleModel,
  33331. seriesModel.getViewRoot().getAncestors(),
  33332. seriesModel
  33333. );
  33334. });
  33335. };
  33336. function travelTree(
  33337. node, designatedVisual, levelItemStyles, seriesItemStyleModel,
  33338. viewRootAncestors, seriesModel
  33339. ) {
  33340. var nodeModel = node.getModel();
  33341. var nodeLayout = node.getLayout();
  33342. // Optimize
  33343. if (!nodeLayout || nodeLayout.invisible || !nodeLayout.isInView) {
  33344. return;
  33345. }
  33346. var nodeItemStyleModel = node.getModel(ITEM_STYLE_NORMAL);
  33347. var levelItemStyle = levelItemStyles[node.depth];
  33348. var visuals = buildVisuals(
  33349. nodeItemStyleModel, designatedVisual, levelItemStyle, seriesItemStyleModel
  33350. );
  33351. // calculate border color
  33352. var borderColor = nodeItemStyleModel.get('borderColor');
  33353. var borderColorSaturation = nodeItemStyleModel.get('borderColorSaturation');
  33354. var thisNodeColor;
  33355. if (borderColorSaturation != null) {
  33356. // For performance, do not always execute 'calculateColor'.
  33357. thisNodeColor = calculateColor(visuals, node);
  33358. borderColor = calculateBorderColor(borderColorSaturation, thisNodeColor);
  33359. }
  33360. node.setVisual('borderColor', borderColor);
  33361. var viewChildren = node.viewChildren;
  33362. if (!viewChildren || !viewChildren.length) {
  33363. thisNodeColor = calculateColor(visuals, node);
  33364. // Apply visual to this node.
  33365. node.setVisual('color', thisNodeColor);
  33366. }
  33367. else {
  33368. var mapping = buildVisualMapping(
  33369. node, nodeModel, nodeLayout, nodeItemStyleModel, visuals, viewChildren
  33370. );
  33371. // Designate visual to children.
  33372. zrUtil.each(viewChildren, function (child, index) {
  33373. // If higher than viewRoot, only ancestors of viewRoot is needed to visit.
  33374. if (child.depth >= viewRootAncestors.length
  33375. || child === viewRootAncestors[child.depth]
  33376. ) {
  33377. var childVisual = mapVisual(
  33378. nodeModel, visuals, child, index, mapping, seriesModel
  33379. );
  33380. travelTree(
  33381. child, childVisual, levelItemStyles, seriesItemStyleModel,
  33382. viewRootAncestors, seriesModel
  33383. );
  33384. }
  33385. });
  33386. }
  33387. }
  33388. function buildVisuals(
  33389. nodeItemStyleModel, designatedVisual, levelItemStyle, seriesItemStyleModel
  33390. ) {
  33391. var visuals = zrUtil.extend({}, designatedVisual);
  33392. zrUtil.each(['color', 'colorAlpha', 'colorSaturation'], function (visualName) {
  33393. // Priority: thisNode > thisLevel > parentNodeDesignated > seriesModel
  33394. var val = nodeItemStyleModel.get(visualName, true); // Ignore parent
  33395. val == null && levelItemStyle && (val = levelItemStyle[visualName]);
  33396. val == null && (val = designatedVisual[visualName]);
  33397. val == null && (val = seriesItemStyleModel.get(visualName));
  33398. val != null && (visuals[visualName] = val);
  33399. });
  33400. return visuals;
  33401. }
  33402. function calculateColor(visuals) {
  33403. var color = getValueVisualDefine(visuals, 'color');
  33404. if (color) {
  33405. var colorAlpha = getValueVisualDefine(visuals, 'colorAlpha');
  33406. var colorSaturation = getValueVisualDefine(visuals, 'colorSaturation');
  33407. if (colorSaturation) {
  33408. color = zrColor.modifyHSL(color, null, null, colorSaturation);
  33409. }
  33410. if (colorAlpha) {
  33411. color = zrColor.modifyAlpha(color, colorAlpha);
  33412. }
  33413. return color;
  33414. }
  33415. }
  33416. function calculateBorderColor(borderColorSaturation, thisNodeColor) {
  33417. return thisNodeColor != null
  33418. ? zrColor.modifyHSL(thisNodeColor, null, null, borderColorSaturation)
  33419. : null;
  33420. }
  33421. function getValueVisualDefine(visuals, name) {
  33422. var value = visuals[name];
  33423. if (value != null && value !== 'none') {
  33424. return value;
  33425. }
  33426. }
  33427. function buildVisualMapping(
  33428. node, nodeModel, nodeLayout, nodeItemStyleModel, visuals, viewChildren
  33429. ) {
  33430. if (!viewChildren || !viewChildren.length) {
  33431. return;
  33432. }
  33433. var rangeVisual = getRangeVisual(nodeModel, 'color')
  33434. || (
  33435. visuals.color != null
  33436. && visuals.color !== 'none'
  33437. && (
  33438. getRangeVisual(nodeModel, 'colorAlpha')
  33439. || getRangeVisual(nodeModel, 'colorSaturation')
  33440. )
  33441. );
  33442. if (!rangeVisual) {
  33443. return;
  33444. }
  33445. var visualMin = nodeModel.get('visualMin');
  33446. var visualMax = nodeModel.get('visualMax');
  33447. var dataExtent = nodeLayout.dataExtent.slice();
  33448. visualMin != null && visualMin < dataExtent[0] && (dataExtent[0] = visualMin);
  33449. visualMax != null && visualMax > dataExtent[1] && (dataExtent[1] = visualMax);
  33450. var colorMappingBy = nodeModel.get('colorMappingBy');
  33451. var opt = {
  33452. type: rangeVisual.name,
  33453. dataExtent: dataExtent,
  33454. visual: rangeVisual.range
  33455. };
  33456. if (opt.type === 'color'
  33457. && (colorMappingBy === 'index' || colorMappingBy === 'id')
  33458. ) {
  33459. opt.mappingMethod = 'category';
  33460. opt.loop = true;
  33461. // categories is ordinal, so do not set opt.categories.
  33462. }
  33463. else {
  33464. opt.mappingMethod = 'linear';
  33465. }
  33466. var mapping = new VisualMapping(opt);
  33467. mapping.__drColorMappingBy = colorMappingBy;
  33468. return mapping;
  33469. }
  33470. // Notice: If we dont have the attribute 'colorRange', but only use
  33471. // attribute 'color' to represent both concepts of 'colorRange' and 'color',
  33472. // (It means 'colorRange' when 'color' is Array, means 'color' when not array),
  33473. // this problem will be encountered:
  33474. // If a level-1 node dont have children, and its siblings has children,
  33475. // and colorRange is set on level-1, then the node can not be colored.
  33476. // So we separate 'colorRange' and 'color' to different attributes.
  33477. function getRangeVisual(nodeModel, name) {
  33478. // 'colorRange', 'colorARange', 'colorSRange'.
  33479. // If not exsits on this node, fetch from levels and series.
  33480. var range = nodeModel.get(name);
  33481. return (isArray(range) && range.length) ? {name: name, range: range} : null;
  33482. }
  33483. function mapVisual(nodeModel, visuals, child, index, mapping, seriesModel) {
  33484. var childVisuals = zrUtil.extend({}, visuals);
  33485. if (mapping) {
  33486. var mappingType = mapping.type;
  33487. var colorMappingBy = mappingType === 'color' && mapping.__drColorMappingBy;
  33488. var value =
  33489. colorMappingBy === 'index'
  33490. ? index
  33491. : colorMappingBy === 'id'
  33492. ? seriesModel.mapIdToIndex(child.getId())
  33493. : child.getValue(nodeModel.get('visualDimension'));
  33494. childVisuals[mappingType] = mapping.mapValueToVisual(value);
  33495. }
  33496. return childVisuals;
  33497. }
  33498. /***/ },
  33499. /* 202 */
  33500. /***/ function(module, exports, __webpack_require__) {
  33501. /**
  33502. * @file Visual mapping.
  33503. */
  33504. var zrUtil = __webpack_require__(4);
  33505. var zrColor = __webpack_require__(31);
  33506. var linearMap = __webpack_require__(7).linearMap;
  33507. var each = zrUtil.each;
  33508. var isObject = zrUtil.isObject;
  33509. var CATEGORY_DEFAULT_VISUAL_INDEX = -1;
  33510. /**
  33511. * @param {Object} option
  33512. * @param {string} [option.type] See visualHandlers.
  33513. * @param {string} [option.mappingMethod] 'linear' or 'piecewise' or 'category' or 'fixed'
  33514. * @param {Array.<number>=} [option.dataExtent] [minExtent, maxExtent],
  33515. * required when mappingMethod is 'linear'
  33516. * @param {Array.<Object>=} [option.pieceList] [
  33517. * {value: someValue},
  33518. * {interval: [min1, max1], visual: {...}},
  33519. * {interval: [min2, max2]}
  33520. * ],
  33521. * required when mappingMethod is 'piecewise'.
  33522. * Visual for only each piece can be specified.
  33523. * @param {Array.<string|Object>=} [option.categories] ['cate1', 'cate2']
  33524. * required when mappingMethod is 'category'.
  33525. * If no option.categories, categories is set
  33526. * as [0, 1, 2, ...].
  33527. * @param {boolean} [option.loop=false] Whether loop mapping when mappingMethod is 'category'.
  33528. * @param {(Array|Object|*)} [option.visual] Visual data.
  33529. * when mappingMethod is 'category',
  33530. * visual data can be array or object
  33531. * (like: {cate1: '#222', none: '#fff'})
  33532. * or primary types (which represents
  33533. * defualt category visual), otherwise visual
  33534. * can be array or primary (which will be
  33535. * normalized to array).
  33536. *
  33537. */
  33538. var VisualMapping = function (option) {
  33539. var mappingMethod = option.mappingMethod;
  33540. var visualType = option.type;
  33541. /**
  33542. * @readOnly
  33543. * @type {Object}
  33544. */
  33545. var thisOption = this.option = zrUtil.clone(option);
  33546. /**
  33547. * @readOnly
  33548. * @type {string}
  33549. */
  33550. this.type = visualType;
  33551. /**
  33552. * @readOnly
  33553. * @type {string}
  33554. */
  33555. this.mappingMethod = mappingMethod;
  33556. /**
  33557. * @private
  33558. * @type {Function}
  33559. */
  33560. this._normalizeData = normalizers[mappingMethod];
  33561. var visualHandler = visualHandlers[visualType];
  33562. /**
  33563. * @public
  33564. * @type {Function}
  33565. */
  33566. this.applyVisual = visualHandler.applyVisual;
  33567. /**
  33568. * @public
  33569. * @type {Function}
  33570. */
  33571. this.getColorMapper = visualHandler.getColorMapper;
  33572. /**
  33573. * @private
  33574. * @type {Function}
  33575. */
  33576. this._doMap = visualHandler._doMap[mappingMethod];
  33577. if (mappingMethod === 'piecewise') {
  33578. normalizeVisualRange(thisOption);
  33579. preprocessForPiecewise(thisOption);
  33580. }
  33581. else if (mappingMethod === 'category') {
  33582. thisOption.categories
  33583. ? preprocessForSpecifiedCategory(thisOption)
  33584. // categories is ordinal when thisOption.categories not specified,
  33585. // which need no more preprocess except normalize visual.
  33586. : normalizeVisualRange(thisOption, true);
  33587. }
  33588. else { // mappingMethod === 'linear' or 'fixed'
  33589. zrUtil.assert(mappingMethod !== 'linear' || thisOption.dataExtent);
  33590. normalizeVisualRange(thisOption);
  33591. }
  33592. };
  33593. VisualMapping.prototype = {
  33594. constructor: VisualMapping,
  33595. mapValueToVisual: function (value) {
  33596. var normalized = this._normalizeData(value);
  33597. return this._doMap(normalized, value);
  33598. },
  33599. getNormalizer: function () {
  33600. return zrUtil.bind(this._normalizeData, this);
  33601. }
  33602. };
  33603. var visualHandlers = VisualMapping.visualHandlers = {
  33604. color: {
  33605. applyVisual: makeApplyVisual('color'),
  33606. /**
  33607. * Create a mapper function
  33608. * @return {Function}
  33609. */
  33610. getColorMapper: function () {
  33611. var thisOption = this.option;
  33612. return zrUtil.bind(
  33613. thisOption.mappingMethod === 'category'
  33614. ? function (value, isNormalized) {
  33615. !isNormalized && (value = this._normalizeData(value));
  33616. return doMapCategory.call(this, value);
  33617. }
  33618. : function (value, isNormalized, out) {
  33619. // If output rgb array
  33620. // which will be much faster and useful in pixel manipulation
  33621. var returnRGBArray = !!out;
  33622. !isNormalized && (value = this._normalizeData(value));
  33623. out = zrColor.fastMapToColor(value, thisOption.parsedVisual, out);
  33624. return returnRGBArray ? out : zrColor.stringify(out, 'rgba');
  33625. },
  33626. this
  33627. );
  33628. },
  33629. _doMap: {
  33630. linear: function (normalized) {
  33631. return zrColor.stringify(
  33632. zrColor.fastMapToColor(normalized, this.option.parsedVisual),
  33633. 'rgba'
  33634. );
  33635. },
  33636. category: doMapCategory,
  33637. piecewise: function (normalized, value) {
  33638. var result = getSpecifiedVisual.call(this, value);
  33639. if (result == null) {
  33640. result = zrColor.stringify(
  33641. zrColor.fastMapToColor(normalized, this.option.parsedVisual),
  33642. 'rgba'
  33643. );
  33644. }
  33645. return result;
  33646. },
  33647. fixed: doMapFixed
  33648. }
  33649. },
  33650. colorHue: makePartialColorVisualHandler(function (color, value) {
  33651. return zrColor.modifyHSL(color, value);
  33652. }),
  33653. colorSaturation: makePartialColorVisualHandler(function (color, value) {
  33654. return zrColor.modifyHSL(color, null, value);
  33655. }),
  33656. colorLightness: makePartialColorVisualHandler(function (color, value) {
  33657. return zrColor.modifyHSL(color, null, null, value);
  33658. }),
  33659. colorAlpha: makePartialColorVisualHandler(function (color, value) {
  33660. return zrColor.modifyAlpha(color, value);
  33661. }),
  33662. opacity: {
  33663. applyVisual: makeApplyVisual('opacity'),
  33664. _doMap: makeDoMap([0, 1])
  33665. },
  33666. symbol: {
  33667. applyVisual: function (value, getter, setter) {
  33668. var symbolCfg = this.mapValueToVisual(value);
  33669. if (zrUtil.isString(symbolCfg)) {
  33670. setter('symbol', symbolCfg);
  33671. }
  33672. else if (isObject(symbolCfg)) {
  33673. for (var name in symbolCfg) {
  33674. if (symbolCfg.hasOwnProperty(name)) {
  33675. setter(name, symbolCfg[name]);
  33676. }
  33677. }
  33678. }
  33679. },
  33680. _doMap: {
  33681. linear: doMapToArray,
  33682. category: doMapCategory,
  33683. piecewise: function (normalized, value) {
  33684. var result = getSpecifiedVisual.call(this, value);
  33685. if (result == null) {
  33686. result = doMapToArray.call(this, normalized);
  33687. }
  33688. return result;
  33689. },
  33690. fixed: doMapFixed
  33691. }
  33692. },
  33693. symbolSize: {
  33694. applyVisual: makeApplyVisual('symbolSize'),
  33695. _doMap: makeDoMap([0, 1])
  33696. }
  33697. };
  33698. function preprocessForPiecewise(thisOption) {
  33699. var pieceList = thisOption.pieceList;
  33700. thisOption.hasSpecialVisual = false;
  33701. zrUtil.each(pieceList, function (piece, index) {
  33702. piece.originIndex = index;
  33703. // piece.visual is "result visual value" but not
  33704. // a visual range, so it does not need to be normalized.
  33705. if (piece.visual != null) {
  33706. thisOption.hasSpecialVisual = true;
  33707. }
  33708. });
  33709. }
  33710. function preprocessForSpecifiedCategory(thisOption) {
  33711. // Hash categories.
  33712. var categories = thisOption.categories;
  33713. var visual = thisOption.visual;
  33714. var categoryMap = thisOption.categoryMap = {};
  33715. each(categories, function (cate, index) {
  33716. categoryMap[cate] = index;
  33717. });
  33718. // Process visual map input.
  33719. if (!zrUtil.isArray(visual)) {
  33720. var visualArr = [];
  33721. if (zrUtil.isObject(visual)) {
  33722. each(visual, function (v, cate) {
  33723. var index = categoryMap[cate];
  33724. visualArr[index != null ? index : CATEGORY_DEFAULT_VISUAL_INDEX] = v;
  33725. });
  33726. }
  33727. else { // Is primary type, represents default visual.
  33728. visualArr[CATEGORY_DEFAULT_VISUAL_INDEX] = visual;
  33729. }
  33730. visual = setVisualToOption(thisOption, visualArr);
  33731. }
  33732. // Remove categories that has no visual,
  33733. // then we can mapping them to CATEGORY_DEFAULT_VISUAL_INDEX.
  33734. for (var i = categories.length - 1; i >= 0; i--) {
  33735. if (visual[i] == null) {
  33736. delete categoryMap[categories[i]];
  33737. categories.pop();
  33738. }
  33739. }
  33740. }
  33741. function normalizeVisualRange(thisOption, isCategory) {
  33742. var visual = thisOption.visual;
  33743. var visualArr = [];
  33744. if (zrUtil.isObject(visual)) {
  33745. each(visual, function (v) {
  33746. visualArr.push(v);
  33747. });
  33748. }
  33749. else if (visual != null) {
  33750. visualArr.push(visual);
  33751. }
  33752. var doNotNeedPair = {color: 1, symbol: 1};
  33753. if (!isCategory
  33754. && visualArr.length === 1
  33755. && !doNotNeedPair.hasOwnProperty(thisOption.type)
  33756. ) {
  33757. // Do not care visualArr.length === 0, which is illegal.
  33758. visualArr[1] = visualArr[0];
  33759. }
  33760. setVisualToOption(thisOption, visualArr);
  33761. }
  33762. function makePartialColorVisualHandler(applyValue) {
  33763. return {
  33764. applyVisual: function (value, getter, setter) {
  33765. value = this.mapValueToVisual(value);
  33766. // Must not be array value
  33767. setter('color', applyValue(getter('color'), value));
  33768. },
  33769. _doMap: makeDoMap([0, 1])
  33770. };
  33771. }
  33772. function doMapToArray(normalized) {
  33773. var visual = this.option.visual;
  33774. return visual[
  33775. Math.round(linearMap(normalized, [0, 1], [0, visual.length - 1], true))
  33776. ] || {};
  33777. }
  33778. function makeApplyVisual(visualType) {
  33779. return function (value, getter, setter) {
  33780. setter(visualType, this.mapValueToVisual(value));
  33781. };
  33782. }
  33783. function doMapCategory(normalized) {
  33784. var visual = this.option.visual;
  33785. return visual[
  33786. (this.option.loop && normalized !== CATEGORY_DEFAULT_VISUAL_INDEX)
  33787. ? normalized % visual.length
  33788. : normalized
  33789. ];
  33790. }
  33791. function doMapFixed() {
  33792. return this.option.visual[0];
  33793. }
  33794. function makeDoMap(sourceExtent) {
  33795. return {
  33796. linear: function (normalized) {
  33797. return linearMap(normalized, sourceExtent, this.option.visual, true);
  33798. },
  33799. category: doMapCategory,
  33800. piecewise: function (normalized, value) {
  33801. var result = getSpecifiedVisual.call(this, value);
  33802. if (result == null) {
  33803. result = linearMap(normalized, sourceExtent, this.option.visual, true);
  33804. }
  33805. return result;
  33806. },
  33807. fixed: doMapFixed
  33808. };
  33809. }
  33810. function getSpecifiedVisual(value) {
  33811. var thisOption = this.option;
  33812. var pieceList = thisOption.pieceList;
  33813. if (thisOption.hasSpecialVisual) {
  33814. var pieceIndex = VisualMapping.findPieceIndex(value, pieceList);
  33815. var piece = pieceList[pieceIndex];
  33816. if (piece && piece.visual) {
  33817. return piece.visual[this.type];
  33818. }
  33819. }
  33820. }
  33821. function setVisualToOption(thisOption, visualArr) {
  33822. thisOption.visual = visualArr;
  33823. if (thisOption.type === 'color') {
  33824. thisOption.parsedVisual = zrUtil.map(visualArr, function (item) {
  33825. return zrColor.parse(item);
  33826. });
  33827. }
  33828. return visualArr;
  33829. }
  33830. /**
  33831. * Normalizers by mapping methods.
  33832. */
  33833. var normalizers = {
  33834. linear: function (value) {
  33835. return linearMap(value, this.option.dataExtent, [0, 1], true);
  33836. },
  33837. piecewise: function (value) {
  33838. var pieceList = this.option.pieceList;
  33839. var pieceIndex = VisualMapping.findPieceIndex(value, pieceList, true);
  33840. if (pieceIndex != null) {
  33841. return linearMap(pieceIndex, [0, pieceList.length - 1], [0, 1], true);
  33842. }
  33843. },
  33844. category: function (value) {
  33845. var index = this.option.categories
  33846. ? this.option.categoryMap[value]
  33847. : value; // ordinal
  33848. return index == null ? CATEGORY_DEFAULT_VISUAL_INDEX : index;
  33849. },
  33850. fixed: zrUtil.noop
  33851. };
  33852. /**
  33853. * List available visual types.
  33854. *
  33855. * @public
  33856. * @return {Array.<string>}
  33857. */
  33858. VisualMapping.listVisualTypes = function () {
  33859. var visualTypes = [];
  33860. zrUtil.each(visualHandlers, function (handler, key) {
  33861. visualTypes.push(key);
  33862. });
  33863. return visualTypes;
  33864. };
  33865. /**
  33866. * @public
  33867. */
  33868. VisualMapping.addVisualHandler = function (name, handler) {
  33869. visualHandlers[name] = handler;
  33870. };
  33871. /**
  33872. * @public
  33873. */
  33874. VisualMapping.isValidType = function (visualType) {
  33875. return visualHandlers.hasOwnProperty(visualType);
  33876. };
  33877. /**
  33878. * Convinent method.
  33879. * Visual can be Object or Array or primary type.
  33880. *
  33881. * @public
  33882. */
  33883. VisualMapping.eachVisual = function (visual, callback, context) {
  33884. if (zrUtil.isObject(visual)) {
  33885. zrUtil.each(visual, callback, context);
  33886. }
  33887. else {
  33888. callback.call(context, visual);
  33889. }
  33890. };
  33891. VisualMapping.mapVisual = function (visual, callback, context) {
  33892. var isPrimary;
  33893. var newVisual = zrUtil.isArray(visual)
  33894. ? []
  33895. : zrUtil.isObject(visual)
  33896. ? {}
  33897. : (isPrimary = true, null);
  33898. VisualMapping.eachVisual(visual, function (v, key) {
  33899. var newVal = callback.call(context, v, key);
  33900. isPrimary ? (newVisual = newVal) : (newVisual[key] = newVal);
  33901. });
  33902. return newVisual;
  33903. };
  33904. /**
  33905. * @public
  33906. * @param {Object} obj
  33907. * @return {Oject} new object containers visual values.
  33908. * If no visuals, return null.
  33909. */
  33910. VisualMapping.retrieveVisuals = function (obj) {
  33911. var ret = {};
  33912. var hasVisual;
  33913. obj && each(visualHandlers, function (h, visualType) {
  33914. if (obj.hasOwnProperty(visualType)) {
  33915. ret[visualType] = obj[visualType];
  33916. hasVisual = true;
  33917. }
  33918. });
  33919. return hasVisual ? ret : null;
  33920. };
  33921. /**
  33922. * Give order to visual types, considering colorSaturation, colorAlpha depends on color.
  33923. *
  33924. * @public
  33925. * @param {(Object|Array)} visualTypes If Object, like: {color: ..., colorSaturation: ...}
  33926. * IF Array, like: ['color', 'symbol', 'colorSaturation']
  33927. * @return {Array.<string>} Sorted visual types.
  33928. */
  33929. VisualMapping.prepareVisualTypes = function (visualTypes) {
  33930. if (isObject(visualTypes)) {
  33931. var types = [];
  33932. each(visualTypes, function (item, type) {
  33933. types.push(type);
  33934. });
  33935. visualTypes = types;
  33936. }
  33937. else if (zrUtil.isArray(visualTypes)) {
  33938. visualTypes = visualTypes.slice();
  33939. }
  33940. else {
  33941. return [];
  33942. }
  33943. visualTypes.sort(function (type1, type2) {
  33944. // color should be front of colorSaturation, colorAlpha, ...
  33945. // symbol and symbolSize do not matter.
  33946. return (type2 === 'color' && type1 !== 'color' && type1.indexOf('color') === 0)
  33947. ? 1 : -1;
  33948. });
  33949. return visualTypes;
  33950. };
  33951. /**
  33952. * 'color', 'colorSaturation', 'colorAlpha', ... are depends on 'color'.
  33953. * Other visuals are only depends on themself.
  33954. *
  33955. * @public
  33956. * @param {string} visualType1
  33957. * @param {string} visualType2
  33958. * @return {boolean}
  33959. */
  33960. VisualMapping.dependsOn = function (visualType1, visualType2) {
  33961. return visualType2 === 'color'
  33962. ? !!(visualType1 && visualType1.indexOf(visualType2) === 0)
  33963. : visualType1 === visualType2;
  33964. };
  33965. /**
  33966. * @param {number} value
  33967. * @param {Array.<Object>} pieceList [{value: ..., interval: [min, max]}, ...]
  33968. * Always from small to big.
  33969. * @param {boolean} [findClosestWhenOutside=false]
  33970. * @return {number} index
  33971. */
  33972. VisualMapping.findPieceIndex = function (value, pieceList, findClosestWhenOutside) {
  33973. var possibleI;
  33974. var abs = Infinity;
  33975. // value has the higher priority.
  33976. for (var i = 0, len = pieceList.length; i < len; i++) {
  33977. var pieceValue = pieceList[i].value;
  33978. if (pieceValue != null) {
  33979. if (pieceValue === value
  33980. // FIXME
  33981. // It is supposed to compare value according to value type of dimension,
  33982. // but currently value type can exactly be string or number.
  33983. // Compromise for numeric-like string (like '12'), especially
  33984. // in the case that visualMap.categories is ['22', '33'].
  33985. || (typeof pieceValue === 'string' && pieceValue === value + '')
  33986. ) {
  33987. return i;
  33988. }
  33989. findClosestWhenOutside && updatePossible(pieceValue, i);
  33990. }
  33991. }
  33992. for (var i = 0, len = pieceList.length; i < len; i++) {
  33993. var piece = pieceList[i];
  33994. var interval = piece.interval;
  33995. var close = piece.close;
  33996. if (interval) {
  33997. if (interval[0] === -Infinity) {
  33998. if (littleThan(close[1], value, interval[1])) {
  33999. return i;
  34000. }
  34001. }
  34002. else if (interval[1] === Infinity) {
  34003. if (littleThan(close[0], interval[0], value)) {
  34004. return i;
  34005. }
  34006. }
  34007. else if (
  34008. littleThan(close[0], interval[0], value)
  34009. && littleThan(close[1], value, interval[1])
  34010. ) {
  34011. return i;
  34012. }
  34013. findClosestWhenOutside && updatePossible(interval[0], i);
  34014. findClosestWhenOutside && updatePossible(interval[1], i);
  34015. }
  34016. }
  34017. if (findClosestWhenOutside) {
  34018. return value === Infinity
  34019. ? pieceList.length - 1
  34020. : value === -Infinity
  34021. ? 0
  34022. : possibleI;
  34023. }
  34024. function updatePossible(val, index) {
  34025. var newAbs = Math.abs(val - value);
  34026. if (newAbs < abs) {
  34027. abs = newAbs;
  34028. possibleI = index;
  34029. }
  34030. }
  34031. };
  34032. function littleThan(close, a, b) {
  34033. return close ? a <= b : a < b;
  34034. }
  34035. module.exports = VisualMapping;
  34036. /***/ },
  34037. /* 203 */
  34038. /***/ function(module, exports, __webpack_require__) {
  34039. var zrUtil = __webpack_require__(4);
  34040. var numberUtil = __webpack_require__(7);
  34041. var layout = __webpack_require__(71);
  34042. var helper = __webpack_require__(196);
  34043. var BoundingRect = __webpack_require__(9);
  34044. var helper = __webpack_require__(196);
  34045. var mathMax = Math.max;
  34046. var mathMin = Math.min;
  34047. var parsePercent = numberUtil.parsePercent;
  34048. var retrieveValue = zrUtil.retrieve;
  34049. var each = zrUtil.each;
  34050. /**
  34051. * @public
  34052. */
  34053. function update(ecModel, api, payload) {
  34054. // Layout result in each node:
  34055. // {x, y, width, height, area, borderWidth}
  34056. var condition = {mainType: 'series', subType: 'treemap', query: payload};
  34057. ecModel.eachComponent(condition, function (seriesModel) {
  34058. var ecWidth = api.getWidth();
  34059. var ecHeight = api.getHeight();
  34060. var seriesOption = seriesModel.option;
  34061. var layoutInfo = layout.getLayoutRect(
  34062. seriesModel.getBoxLayoutParams(),
  34063. {
  34064. width: api.getWidth(),
  34065. height: api.getHeight()
  34066. }
  34067. );
  34068. var size = seriesOption.size || []; // Compatible with ec2.
  34069. var containerWidth = parsePercent(
  34070. retrieveValue(layoutInfo.width, size[0]),
  34071. ecWidth
  34072. );
  34073. var containerHeight = parsePercent(
  34074. retrieveValue(layoutInfo.height, size[1]),
  34075. ecHeight
  34076. );
  34077. // Fetch payload info.
  34078. var payloadType = payload && payload.type;
  34079. var targetInfo = helper.retrieveTargetInfo(payload, seriesModel);
  34080. var rootRect = (payloadType === 'treemapRender' || payloadType === 'treemapMove')
  34081. ? payload.rootRect : null;
  34082. var viewRoot = seriesModel.getViewRoot();
  34083. var viewAbovePath = helper.getPathToRoot(viewRoot);
  34084. if (payloadType !== 'treemapMove') {
  34085. var rootSize = payloadType === 'treemapZoomToNode'
  34086. ? estimateRootSize(
  34087. seriesModel, targetInfo, viewRoot, containerWidth, containerHeight
  34088. )
  34089. : rootRect
  34090. ? [rootRect.width, rootRect.height]
  34091. : [containerWidth, containerHeight];
  34092. var sort = seriesOption.sort;
  34093. if (sort && sort !== 'asc' && sort !== 'desc') {
  34094. sort = 'desc';
  34095. }
  34096. var options = {
  34097. squareRatio: seriesOption.squareRatio,
  34098. sort: sort,
  34099. leafDepth: seriesOption.leafDepth
  34100. };
  34101. // layout should be cleared because using updateView but not update.
  34102. viewRoot.hostTree.clearLayouts();
  34103. // TODO
  34104. // optimize: if out of view clip, do not layout.
  34105. // But take care that if do not render node out of view clip,
  34106. // how to calculate start po
  34107. var viewRootLayout = {
  34108. x: 0, y: 0,
  34109. width: rootSize[0], height: rootSize[1],
  34110. area: rootSize[0] * rootSize[1]
  34111. };
  34112. viewRoot.setLayout(viewRootLayout);
  34113. squarify(viewRoot, options, false, 0);
  34114. // Supplement layout.
  34115. var viewRootLayout = viewRoot.getLayout();
  34116. each(viewAbovePath, function (node, index) {
  34117. var childValue = (viewAbovePath[index + 1] || viewRoot).getValue();
  34118. node.setLayout(zrUtil.extend(
  34119. {dataExtent: [childValue, childValue], borderWidth: 0},
  34120. viewRootLayout
  34121. ));
  34122. });
  34123. }
  34124. var treeRoot = seriesModel.getData().tree.root;
  34125. treeRoot.setLayout(
  34126. calculateRootPosition(layoutInfo, rootRect, targetInfo),
  34127. true
  34128. );
  34129. seriesModel.setLayoutInfo(layoutInfo);
  34130. // FIXME
  34131. // 现在没有clip功能,暂时取ec高宽。
  34132. prunning(
  34133. treeRoot,
  34134. // Transform to base element coordinate system.
  34135. new BoundingRect(-layoutInfo.x, -layoutInfo.y, ecWidth, ecHeight),
  34136. viewAbovePath,
  34137. viewRoot,
  34138. 0
  34139. );
  34140. });
  34141. }
  34142. /**
  34143. * Layout treemap with squarify algorithm.
  34144. * @see https://graphics.ethz.ch/teaching/scivis_common/Literature/squarifiedTreeMaps.pdf
  34145. * @see https://github.com/mbostock/d3/blob/master/src/layout/treemap.js
  34146. *
  34147. * @protected
  34148. * @param {module:echarts/data/Tree~TreeNode} node
  34149. * @param {Object} options
  34150. * @param {string} options.sort 'asc' or 'desc'
  34151. * @param {number} options.squareRatio
  34152. * @param {boolean} hideChildren
  34153. * @param {number} depth
  34154. */
  34155. function squarify(node, options, hideChildren, depth) {
  34156. var width;
  34157. var height;
  34158. if (node.isRemoved()) {
  34159. return;
  34160. }
  34161. var thisLayout = node.getLayout();
  34162. width = thisLayout.width;
  34163. height = thisLayout.height;
  34164. // Considering border and gap
  34165. var itemStyleModel = node.getModel('itemStyle.normal');
  34166. var borderWidth = itemStyleModel.get('borderWidth');
  34167. var halfGapWidth = itemStyleModel.get('gapWidth') / 2;
  34168. var layoutOffset = borderWidth - halfGapWidth;
  34169. var nodeModel = node.getModel();
  34170. node.setLayout({borderWidth: borderWidth}, true);
  34171. width = mathMax(width - 2 * layoutOffset, 0);
  34172. height = mathMax(height - 2 * layoutOffset, 0);
  34173. var totalArea = width * height;
  34174. var viewChildren = initChildren(
  34175. node, nodeModel, totalArea, options, hideChildren, depth
  34176. );
  34177. if (!viewChildren.length) {
  34178. return;
  34179. }
  34180. var rect = {x: layoutOffset, y: layoutOffset, width: width, height: height};
  34181. var rowFixedLength = mathMin(width, height);
  34182. var best = Infinity; // the best row score so far
  34183. var row = [];
  34184. row.area = 0;
  34185. for (var i = 0, len = viewChildren.length; i < len;) {
  34186. var child = viewChildren[i];
  34187. row.push(child);
  34188. row.area += child.getLayout().area;
  34189. var score = worst(row, rowFixedLength, options.squareRatio);
  34190. // continue with this orientation
  34191. if (score <= best) {
  34192. i++;
  34193. best = score;
  34194. }
  34195. // abort, and try a different orientation
  34196. else {
  34197. row.area -= row.pop().getLayout().area;
  34198. position(row, rowFixedLength, rect, halfGapWidth, false);
  34199. rowFixedLength = mathMin(rect.width, rect.height);
  34200. row.length = row.area = 0;
  34201. best = Infinity;
  34202. }
  34203. }
  34204. if (row.length) {
  34205. position(row, rowFixedLength, rect, halfGapWidth, true);
  34206. }
  34207. if (!hideChildren) {
  34208. var childrenVisibleMin = nodeModel.get('childrenVisibleMin');
  34209. if (childrenVisibleMin != null && totalArea < childrenVisibleMin) {
  34210. hideChildren = true;
  34211. }
  34212. }
  34213. for (var i = 0, len = viewChildren.length; i < len; i++) {
  34214. squarify(viewChildren[i], options, hideChildren, depth + 1);
  34215. }
  34216. }
  34217. /**
  34218. * Set area to each child, and calculate data extent for visual coding.
  34219. */
  34220. function initChildren(node, nodeModel, totalArea, options, hideChildren, depth) {
  34221. var viewChildren = node.children || [];
  34222. var orderBy = options.sort;
  34223. orderBy !== 'asc' && orderBy !== 'desc' && (orderBy = null);
  34224. var overLeafDepth = options.leafDepth != null && options.leafDepth <= depth;
  34225. // leafDepth has higher priority.
  34226. if (hideChildren && !overLeafDepth) {
  34227. return (node.viewChildren = []);
  34228. }
  34229. // Sort children, order by desc.
  34230. viewChildren = zrUtil.filter(viewChildren, function (child) {
  34231. return !child.isRemoved();
  34232. });
  34233. sort(viewChildren, orderBy);
  34234. var info = statistic(nodeModel, viewChildren, orderBy);
  34235. if (info.sum === 0) {
  34236. return (node.viewChildren = []);
  34237. }
  34238. info.sum = filterByThreshold(nodeModel, totalArea, info.sum, orderBy, viewChildren);
  34239. if (info.sum === 0) {
  34240. return (node.viewChildren = []);
  34241. }
  34242. // Set area to each child.
  34243. for (var i = 0, len = viewChildren.length; i < len; i++) {
  34244. var area = viewChildren[i].getValue() / info.sum * totalArea;
  34245. // Do not use setLayout({...}, true), because it is needed to clear last layout.
  34246. viewChildren[i].setLayout({area: area});
  34247. }
  34248. if (overLeafDepth) {
  34249. viewChildren.length && node.setLayout({isLeafRoot: true}, true);
  34250. viewChildren.length = 0;
  34251. }
  34252. node.viewChildren = viewChildren;
  34253. node.setLayout({dataExtent: info.dataExtent}, true);
  34254. return viewChildren;
  34255. }
  34256. /**
  34257. * Consider 'visibleMin'. Modify viewChildren and get new sum.
  34258. */
  34259. function filterByThreshold(nodeModel, totalArea, sum, orderBy, orderedChildren) {
  34260. // visibleMin is not supported yet when no option.sort.
  34261. if (!orderBy) {
  34262. return sum;
  34263. }
  34264. var visibleMin = nodeModel.get('visibleMin');
  34265. var len = orderedChildren.length;
  34266. var deletePoint = len;
  34267. // Always travel from little value to big value.
  34268. for (var i = len - 1; i >= 0; i--) {
  34269. var value = orderedChildren[
  34270. orderBy === 'asc' ? len - i - 1 : i
  34271. ].getValue();
  34272. if (value / sum * totalArea < visibleMin) {
  34273. deletePoint = i;
  34274. sum -= value;
  34275. }
  34276. }
  34277. orderBy === 'asc'
  34278. ? orderedChildren.splice(0, len - deletePoint)
  34279. : orderedChildren.splice(deletePoint, len - deletePoint);
  34280. return sum;
  34281. }
  34282. /**
  34283. * Sort
  34284. */
  34285. function sort(viewChildren, orderBy) {
  34286. if (orderBy) {
  34287. viewChildren.sort(function (a, b) {
  34288. var diff = orderBy === 'asc'
  34289. ? a.getValue() - b.getValue() : b.getValue() - a.getValue();
  34290. return diff === 0
  34291. ? (orderBy === 'asc'
  34292. ? a.dataIndex - b.dataIndex : b.dataIndex - a.dataIndex
  34293. )
  34294. : diff;
  34295. });
  34296. }
  34297. return viewChildren;
  34298. }
  34299. /**
  34300. * Statistic
  34301. */
  34302. function statistic(nodeModel, children, orderBy) {
  34303. // Calculate sum.
  34304. var sum = 0;
  34305. for (var i = 0, len = children.length; i < len; i++) {
  34306. sum += children[i].getValue();
  34307. }
  34308. // Statistic data extent for latter visual coding.
  34309. // Notice: data extent should be calculate based on raw children
  34310. // but not filtered view children, otherwise visual mapping will not
  34311. // be stable when zoom (where children is filtered by visibleMin).
  34312. var dimension = nodeModel.get('visualDimension');
  34313. var dataExtent;
  34314. // The same as area dimension.
  34315. if (!children || !children.length) {
  34316. dataExtent = [NaN, NaN];
  34317. }
  34318. else if (dimension === 'value' && orderBy) {
  34319. dataExtent = [
  34320. children[children.length - 1].getValue(),
  34321. children[0].getValue()
  34322. ];
  34323. orderBy === 'asc' && dataExtent.reverse();
  34324. }
  34325. // Other dimension.
  34326. else {
  34327. var dataExtent = [Infinity, -Infinity];
  34328. each(children, function (child) {
  34329. var value = child.getValue(dimension);
  34330. value < dataExtent[0] && (dataExtent[0] = value);
  34331. value > dataExtent[1] && (dataExtent[1] = value);
  34332. });
  34333. }
  34334. return {sum: sum, dataExtent: dataExtent};
  34335. }
  34336. /**
  34337. * Computes the score for the specified row,
  34338. * as the worst aspect ratio.
  34339. */
  34340. function worst(row, rowFixedLength, ratio) {
  34341. var areaMax = 0;
  34342. var areaMin = Infinity;
  34343. for (var i = 0, area, len = row.length; i < len; i++) {
  34344. area = row[i].getLayout().area;
  34345. if (area) {
  34346. area < areaMin && (areaMin = area);
  34347. area > areaMax && (areaMax = area);
  34348. }
  34349. }
  34350. var squareArea = row.area * row.area;
  34351. var f = rowFixedLength * rowFixedLength * ratio;
  34352. return squareArea
  34353. ? mathMax(
  34354. (f * areaMax) / squareArea,
  34355. squareArea / (f * areaMin)
  34356. )
  34357. : Infinity;
  34358. }
  34359. /**
  34360. * Positions the specified row of nodes. Modifies `rect`.
  34361. */
  34362. function position(row, rowFixedLength, rect, halfGapWidth, flush) {
  34363. // When rowFixedLength === rect.width,
  34364. // it is horizontal subdivision,
  34365. // rowFixedLength is the width of the subdivision,
  34366. // rowOtherLength is the height of the subdivision,
  34367. // and nodes will be positioned from left to right.
  34368. // wh[idx0WhenH] means: when horizontal,
  34369. // wh[idx0WhenH] => wh[0] => 'width'.
  34370. // xy[idx1WhenH] => xy[1] => 'y'.
  34371. var idx0WhenH = rowFixedLength === rect.width ? 0 : 1;
  34372. var idx1WhenH = 1 - idx0WhenH;
  34373. var xy = ['x', 'y'];
  34374. var wh = ['width', 'height'];
  34375. var last = rect[xy[idx0WhenH]];
  34376. var rowOtherLength = rowFixedLength
  34377. ? row.area / rowFixedLength : 0;
  34378. if (flush || rowOtherLength > rect[wh[idx1WhenH]]) {
  34379. rowOtherLength = rect[wh[idx1WhenH]]; // over+underflow
  34380. }
  34381. for (var i = 0, rowLen = row.length; i < rowLen; i++) {
  34382. var node = row[i];
  34383. var nodeLayout = {};
  34384. var step = rowOtherLength
  34385. ? node.getLayout().area / rowOtherLength : 0;
  34386. var wh1 = nodeLayout[wh[idx1WhenH]] = mathMax(rowOtherLength - 2 * halfGapWidth, 0);
  34387. // We use Math.max/min to avoid negative width/height when considering gap width.
  34388. var remain = rect[xy[idx0WhenH]] + rect[wh[idx0WhenH]] - last;
  34389. var modWH = (i === rowLen - 1 || remain < step) ? remain : step;
  34390. var wh0 = nodeLayout[wh[idx0WhenH]] = mathMax(modWH - 2 * halfGapWidth, 0);
  34391. nodeLayout[xy[idx1WhenH]] = rect[xy[idx1WhenH]] + mathMin(halfGapWidth, wh1 / 2);
  34392. nodeLayout[xy[idx0WhenH]] = last + mathMin(halfGapWidth, wh0 / 2);
  34393. last += modWH;
  34394. node.setLayout(nodeLayout, true);
  34395. }
  34396. rect[xy[idx1WhenH]] += rowOtherLength;
  34397. rect[wh[idx1WhenH]] -= rowOtherLength;
  34398. }
  34399. // Return [containerWidth, containerHeight] as defualt.
  34400. function estimateRootSize(seriesModel, targetInfo, viewRoot, containerWidth, containerHeight) {
  34401. // If targetInfo.node exists, we zoom to the node,
  34402. // so estimate whold width and heigth by target node.
  34403. var currNode = (targetInfo || {}).node;
  34404. var defaultSize = [containerWidth, containerHeight];
  34405. if (!currNode || currNode === viewRoot) {
  34406. return defaultSize;
  34407. }
  34408. var parent;
  34409. var viewArea = containerWidth * containerHeight;
  34410. var area = viewArea * seriesModel.option.zoomToNodeRatio;
  34411. while (parent = currNode.parentNode) { // jshint ignore:line
  34412. var sum = 0;
  34413. var siblings = parent.children;
  34414. for (var i = 0, len = siblings.length; i < len; i++) {
  34415. sum += siblings[i].getValue();
  34416. }
  34417. var currNodeValue = currNode.getValue();
  34418. if (currNodeValue === 0) {
  34419. return defaultSize;
  34420. }
  34421. area *= sum / currNodeValue;
  34422. var borderWidth = parent.getModel('itemStyle.normal').get('borderWidth');
  34423. if (isFinite(borderWidth)) {
  34424. // Considering border, suppose aspect ratio is 1.
  34425. area += 4 * borderWidth * borderWidth + 4 * borderWidth * Math.pow(area, 0.5);
  34426. }
  34427. area > numberUtil.MAX_SAFE_INTEGER && (area = numberUtil.MAX_SAFE_INTEGER);
  34428. currNode = parent;
  34429. }
  34430. area < viewArea && (area = viewArea);
  34431. var scale = Math.pow(area / viewArea, 0.5);
  34432. return [containerWidth * scale, containerHeight * scale];
  34433. }
  34434. // Root postion base on coord of containerGroup
  34435. function calculateRootPosition(layoutInfo, rootRect, targetInfo) {
  34436. if (rootRect) {
  34437. return {x: rootRect.x, y: rootRect.y};
  34438. }
  34439. var defaultPosition = {x: 0, y: 0};
  34440. if (!targetInfo) {
  34441. return defaultPosition;
  34442. }
  34443. // If targetInfo is fetched by 'retrieveTargetInfo',
  34444. // old tree and new tree are the same tree,
  34445. // so the node still exists and we can visit it.
  34446. var targetNode = targetInfo.node;
  34447. var layout = targetNode.getLayout();
  34448. if (!layout) {
  34449. return defaultPosition;
  34450. }
  34451. // Transform coord from local to container.
  34452. var targetCenter = [layout.width / 2, layout.height / 2];
  34453. var node = targetNode;
  34454. while (node) {
  34455. var nodeLayout = node.getLayout();
  34456. targetCenter[0] += nodeLayout.x;
  34457. targetCenter[1] += nodeLayout.y;
  34458. node = node.parentNode;
  34459. }
  34460. return {
  34461. x: layoutInfo.width / 2 - targetCenter[0],
  34462. y: layoutInfo.height / 2 - targetCenter[1]
  34463. };
  34464. }
  34465. // Mark nodes visible for prunning when visual coding and rendering.
  34466. // Prunning depends on layout and root position, so we have to do it after layout.
  34467. function prunning(node, clipRect, viewAbovePath, viewRoot, depth) {
  34468. var nodeLayout = node.getLayout();
  34469. var nodeInViewAbovePath = viewAbovePath[depth];
  34470. var isAboveViewRoot = nodeInViewAbovePath && nodeInViewAbovePath === node;
  34471. if (
  34472. (nodeInViewAbovePath && !isAboveViewRoot)
  34473. || (depth === viewAbovePath.length && node !== viewRoot)
  34474. ) {
  34475. return;
  34476. }
  34477. node.setLayout({
  34478. // isInView means: viewRoot sub tree + viewAbovePath
  34479. isInView: true,
  34480. // invisible only means: outside view clip so that the node can not
  34481. // see but still layout for animation preparation but not render.
  34482. invisible: !isAboveViewRoot && !clipRect.intersect(nodeLayout),
  34483. isAboveViewRoot: isAboveViewRoot
  34484. }, true);
  34485. // Transform to child coordinate.
  34486. var childClipRect = new BoundingRect(
  34487. clipRect.x - nodeLayout.x,
  34488. clipRect.y - nodeLayout.y,
  34489. clipRect.width,
  34490. clipRect.height
  34491. );
  34492. each(node.viewChildren || [], function (child) {
  34493. prunning(child, childClipRect, viewAbovePath, viewRoot, depth + 1);
  34494. });
  34495. }
  34496. module.exports = update;
  34497. /***/ },
  34498. /* 204 */
  34499. /***/ function(module, exports, __webpack_require__) {
  34500. var echarts = __webpack_require__(1);
  34501. var zrUtil = __webpack_require__(4);
  34502. __webpack_require__(205);
  34503. __webpack_require__(208);
  34504. __webpack_require__(213);
  34505. echarts.registerProcessor(__webpack_require__(214));
  34506. echarts.registerVisual(zrUtil.curry(
  34507. __webpack_require__(121), 'graph', 'circle', null
  34508. ));
  34509. echarts.registerVisual(__webpack_require__(215));
  34510. echarts.registerVisual(__webpack_require__(216));
  34511. echarts.registerLayout(__webpack_require__(217));
  34512. echarts.registerLayout(__webpack_require__(220));
  34513. echarts.registerLayout(__webpack_require__(222));
  34514. // Graph view coordinate system
  34515. echarts.registerCoordinateSystem('graphView', {
  34516. create: __webpack_require__(224)
  34517. });
  34518. /***/ },
  34519. /* 205 */
  34520. /***/ function(module, exports, __webpack_require__) {
  34521. 'use strict';
  34522. var List = __webpack_require__(98);
  34523. var zrUtil = __webpack_require__(4);
  34524. var modelUtil = __webpack_require__(5);
  34525. var Model = __webpack_require__(12);
  34526. var formatUtil = __webpack_require__(6);
  34527. var createGraphFromNodeEdge = __webpack_require__(206);
  34528. var GraphSeries = __webpack_require__(1).extendSeriesModel({
  34529. type: 'series.graph',
  34530. init: function (option) {
  34531. GraphSeries.superApply(this, 'init', arguments);
  34532. // Provide data for legend select
  34533. this.legendDataProvider = function () {
  34534. return this._categoriesData;
  34535. };
  34536. this.fillDataTextStyle(option.edges || option.links);
  34537. this._updateCategoriesData();
  34538. },
  34539. mergeOption: function (option) {
  34540. GraphSeries.superApply(this, 'mergeOption', arguments);
  34541. this.fillDataTextStyle(option.edges || option.links);
  34542. this._updateCategoriesData();
  34543. },
  34544. mergeDefaultAndTheme: function (option) {
  34545. GraphSeries.superApply(this, 'mergeDefaultAndTheme', arguments);
  34546. modelUtil.defaultEmphasis(option.edgeLabel, modelUtil.LABEL_OPTIONS);
  34547. },
  34548. getInitialData: function (option, ecModel) {
  34549. var edges = option.edges || option.links || [];
  34550. var nodes = option.data || option.nodes || [];
  34551. var self = this;
  34552. if (nodes && edges) {
  34553. return createGraphFromNodeEdge(nodes, edges, this, true, beforeLink).data;
  34554. }
  34555. function beforeLink(nodeData, edgeData) {
  34556. // Overwrite nodeData.getItemModel to
  34557. nodeData.wrapMethod('getItemModel', function (model) {
  34558. var categoriesModels = self._categoriesModels;
  34559. var categoryIdx = model.getShallow('category');
  34560. var categoryModel = categoriesModels[categoryIdx];
  34561. if (categoryModel) {
  34562. categoryModel.parentModel = model.parentModel;
  34563. model.parentModel = categoryModel;
  34564. }
  34565. return model;
  34566. });
  34567. var edgeLabelModel = self.getModel('edgeLabel');
  34568. // For option `edgeLabel` can be found by label.xxx.xxx on item mode.
  34569. var fakeSeriesModel = new Model(
  34570. {label: edgeLabelModel.option},
  34571. edgeLabelModel.parentModel,
  34572. ecModel
  34573. );
  34574. edgeData.wrapMethod('getItemModel', function (model) {
  34575. model.customizeGetParent(edgeGetParent);
  34576. return model;
  34577. });
  34578. function edgeGetParent(path) {
  34579. path = this.parsePath(path);
  34580. return (path && path[0] === 'label')
  34581. ? fakeSeriesModel
  34582. : this.parentModel;
  34583. }
  34584. }
  34585. },
  34586. /**
  34587. * @return {module:echarts/data/Graph}
  34588. */
  34589. getGraph: function () {
  34590. return this.getData().graph;
  34591. },
  34592. /**
  34593. * @return {module:echarts/data/List}
  34594. */
  34595. getEdgeData: function () {
  34596. return this.getGraph().edgeData;
  34597. },
  34598. /**
  34599. * @return {module:echarts/data/List}
  34600. */
  34601. getCategoriesData: function () {
  34602. return this._categoriesData;
  34603. },
  34604. /**
  34605. * @override
  34606. */
  34607. formatTooltip: function (dataIndex, multipleSeries, dataType) {
  34608. if (dataType === 'edge') {
  34609. var nodeData = this.getData();
  34610. var params = this.getDataParams(dataIndex, dataType);
  34611. var edge = nodeData.graph.getEdgeByIndex(dataIndex);
  34612. var sourceName = nodeData.getName(edge.node1.dataIndex);
  34613. var targetName = nodeData.getName(edge.node2.dataIndex);
  34614. var html = [];
  34615. sourceName != null && html.push(sourceName);
  34616. targetName != null && html.push(targetName);
  34617. html = formatUtil.encodeHTML(html.join(' > '));
  34618. if (params.value) {
  34619. html += ' : ' + formatUtil.encodeHTML(params.value);
  34620. }
  34621. return html;
  34622. }
  34623. else { // dataType === 'node' or empty
  34624. return GraphSeries.superApply(this, 'formatTooltip', arguments);
  34625. }
  34626. },
  34627. _updateCategoriesData: function () {
  34628. var categories = zrUtil.map(this.option.categories || [], function (category) {
  34629. // Data must has value
  34630. return category.value != null ? category : zrUtil.extend({
  34631. value: 0
  34632. }, category);
  34633. });
  34634. var categoriesData = new List(['value'], this);
  34635. categoriesData.initData(categories);
  34636. this._categoriesData = categoriesData;
  34637. this._categoriesModels = categoriesData.mapArray(function (idx) {
  34638. return categoriesData.getItemModel(idx, true);
  34639. });
  34640. },
  34641. setZoom: function (zoom) {
  34642. this.option.zoom = zoom;
  34643. },
  34644. setCenter: function (center) {
  34645. this.option.center = center;
  34646. },
  34647. isAnimationEnabled: function () {
  34648. return GraphSeries.superCall(this, 'isAnimationEnabled')
  34649. // Not enable animation when do force layout
  34650. && !(this.get('layout') === 'force' && this.get('force.layoutAnimation'));
  34651. },
  34652. defaultOption: {
  34653. zlevel: 0,
  34654. z: 2,
  34655. coordinateSystem: 'view',
  34656. // Default option for all coordinate systems
  34657. // xAxisIndex: 0,
  34658. // yAxisIndex: 0,
  34659. // polarIndex: 0,
  34660. // geoIndex: 0,
  34661. legendHoverLink: true,
  34662. hoverAnimation: true,
  34663. layout: null,
  34664. focusNodeAdjacency: false,
  34665. // Configuration of circular layout
  34666. circular: {
  34667. rotateLabel: false
  34668. },
  34669. // Configuration of force directed layout
  34670. force: {
  34671. initLayout: null,
  34672. // Node repulsion. Can be an array to represent range.
  34673. repulsion: [0, 50],
  34674. gravity: 0.1,
  34675. // Edge length. Can be an array to represent range.
  34676. edgeLength: 30,
  34677. layoutAnimation: true
  34678. },
  34679. left: 'center',
  34680. top: 'center',
  34681. // right: null,
  34682. // bottom: null,
  34683. // width: '80%',
  34684. // height: '80%',
  34685. symbol: 'circle',
  34686. symbolSize: 10,
  34687. edgeSymbol: ['none', 'none'],
  34688. edgeSymbolSize: 10,
  34689. edgeLabel: {
  34690. normal: {
  34691. position: 'middle'
  34692. },
  34693. emphasis: {}
  34694. },
  34695. draggable: false,
  34696. roam: false,
  34697. // Default on center of graph
  34698. center: null,
  34699. zoom: 1,
  34700. // Symbol size scale ratio in roam
  34701. nodeScaleRatio: 0.6,
  34702. // categories: [],
  34703. // data: []
  34704. // Or
  34705. // nodes: []
  34706. //
  34707. // links: []
  34708. // Or
  34709. // edges: []
  34710. label: {
  34711. normal: {
  34712. show: false,
  34713. formatter: '{b}'
  34714. },
  34715. emphasis: {
  34716. show: true
  34717. }
  34718. },
  34719. itemStyle: {
  34720. normal: {},
  34721. emphasis: {}
  34722. },
  34723. lineStyle: {
  34724. normal: {
  34725. color: '#aaa',
  34726. width: 1,
  34727. curveness: 0,
  34728. opacity: 0.5
  34729. },
  34730. emphasis: {}
  34731. }
  34732. }
  34733. });
  34734. module.exports = GraphSeries;
  34735. /***/ },
  34736. /* 206 */
  34737. /***/ function(module, exports, __webpack_require__) {
  34738. var List = __webpack_require__(98);
  34739. var Graph = __webpack_require__(207);
  34740. var linkList = __webpack_require__(195);
  34741. var completeDimensions = __webpack_require__(110);
  34742. var CoordinateSystem = __webpack_require__(76);
  34743. var zrUtil = __webpack_require__(4);
  34744. var createListFromArray = __webpack_require__(109);
  34745. module.exports = function (nodes, edges, hostModel, directed, beforeLink) {
  34746. var graph = new Graph(directed);
  34747. for (var i = 0; i < nodes.length; i++) {
  34748. graph.addNode(zrUtil.retrieve(
  34749. // Id, name, dataIndex
  34750. nodes[i].id, nodes[i].name, i
  34751. ), i);
  34752. }
  34753. var linkNameList = [];
  34754. var validEdges = [];
  34755. var linkCount = 0;
  34756. for (var i = 0; i < edges.length; i++) {
  34757. var link = edges[i];
  34758. var source = link.source;
  34759. var target = link.target;
  34760. // addEdge may fail when source or target not exists
  34761. if (graph.addEdge(source, target, linkCount)) {
  34762. validEdges.push(link);
  34763. linkNameList.push(zrUtil.retrieve(link.id, source + ' > ' + target));
  34764. linkCount++;
  34765. }
  34766. }
  34767. var coordSys = hostModel.get('coordinateSystem');
  34768. var nodeData;
  34769. if (coordSys === 'cartesian2d' || coordSys === 'polar') {
  34770. nodeData = createListFromArray(nodes, hostModel, hostModel.ecModel);
  34771. }
  34772. else {
  34773. // FIXME
  34774. var coordSysCtor = CoordinateSystem.get(coordSys);
  34775. // FIXME
  34776. var dimensionNames = completeDimensions(
  34777. ((coordSysCtor && coordSysCtor.type !== 'view') ? (coordSysCtor.dimensions || []) : []).concat(['value']),
  34778. nodes
  34779. );
  34780. nodeData = new List(dimensionNames, hostModel);
  34781. nodeData.initData(nodes);
  34782. }
  34783. var edgeData = new List(['value'], hostModel);
  34784. edgeData.initData(validEdges, linkNameList);
  34785. beforeLink && beforeLink(nodeData, edgeData);
  34786. linkList({
  34787. mainData: nodeData,
  34788. struct: graph,
  34789. structAttr: 'graph',
  34790. datas: {node: nodeData, edge: edgeData},
  34791. datasAttr: {node: 'data', edge: 'edgeData'}
  34792. });
  34793. // Update dataIndex of nodes and edges because invalid edge may be removed
  34794. graph.update();
  34795. return graph;
  34796. };
  34797. /***/ },
  34798. /* 207 */
  34799. /***/ function(module, exports, __webpack_require__) {
  34800. 'use strict';
  34801. /**
  34802. * Graph data structure
  34803. *
  34804. * @module echarts/data/Graph
  34805. * @author Yi Shen(https://www.github.com/pissang)
  34806. */
  34807. var zrUtil = __webpack_require__(4);
  34808. // id may be function name of Object, add a prefix to avoid this problem.
  34809. function generateNodeKey (id) {
  34810. return '_EC_' + id;
  34811. }
  34812. /**
  34813. * @alias module:echarts/data/Graph
  34814. * @constructor
  34815. * @param {boolean} directed
  34816. */
  34817. var Graph = function(directed) {
  34818. /**
  34819. * 是否是有向图
  34820. * @type {boolean}
  34821. * @private
  34822. */
  34823. this._directed = directed || false;
  34824. /**
  34825. * @type {Array.<module:echarts/data/Graph.Node>}
  34826. * @readOnly
  34827. */
  34828. this.nodes = [];
  34829. /**
  34830. * @type {Array.<module:echarts/data/Graph.Edge>}
  34831. * @readOnly
  34832. */
  34833. this.edges = [];
  34834. /**
  34835. * @type {Object.<string, module:echarts/data/Graph.Node>}
  34836. * @private
  34837. */
  34838. this._nodesMap = {};
  34839. /**
  34840. * @type {Object.<string, module:echarts/data/Graph.Edge>}
  34841. * @private
  34842. */
  34843. this._edgesMap = {};
  34844. /**
  34845. * @type {module:echarts/data/List}
  34846. * @readOnly
  34847. */
  34848. this.data;
  34849. /**
  34850. * @type {module:echarts/data/List}
  34851. * @readOnly
  34852. */
  34853. this.edgeData;
  34854. };
  34855. var graphProto = Graph.prototype;
  34856. /**
  34857. * @type {string}
  34858. */
  34859. graphProto.type = 'graph';
  34860. /**
  34861. * If is directed graph
  34862. * @return {boolean}
  34863. */
  34864. graphProto.isDirected = function () {
  34865. return this._directed;
  34866. };
  34867. /**
  34868. * Add a new node
  34869. * @param {string} id
  34870. * @param {number} [dataIndex]
  34871. */
  34872. graphProto.addNode = function (id, dataIndex) {
  34873. id = id || ('' + dataIndex);
  34874. var nodesMap = this._nodesMap;
  34875. if (nodesMap[generateNodeKey(id)]) {
  34876. return;
  34877. }
  34878. var node = new Node(id, dataIndex);
  34879. node.hostGraph = this;
  34880. this.nodes.push(node);
  34881. nodesMap[generateNodeKey(id)] = node;
  34882. return node;
  34883. };
  34884. /**
  34885. * Get node by data index
  34886. * @param {number} dataIndex
  34887. * @return {module:echarts/data/Graph~Node}
  34888. */
  34889. graphProto.getNodeByIndex = function (dataIndex) {
  34890. var rawIdx = this.data.getRawIndex(dataIndex);
  34891. return this.nodes[rawIdx];
  34892. };
  34893. /**
  34894. * Get node by id
  34895. * @param {string} id
  34896. * @return {module:echarts/data/Graph.Node}
  34897. */
  34898. graphProto.getNodeById = function (id) {
  34899. return this._nodesMap[generateNodeKey(id)];
  34900. };
  34901. /**
  34902. * Add a new edge
  34903. * @param {number|string|module:echarts/data/Graph.Node} n1
  34904. * @param {number|string|module:echarts/data/Graph.Node} n2
  34905. * @param {number} [dataIndex=-1]
  34906. * @return {module:echarts/data/Graph.Edge}
  34907. */
  34908. graphProto.addEdge = function (n1, n2, dataIndex) {
  34909. var nodesMap = this._nodesMap;
  34910. var edgesMap = this._edgesMap;
  34911. // PNEDING
  34912. if (typeof n1 === 'number') {
  34913. n1 = this.nodes[n1];
  34914. }
  34915. if (typeof n2 === 'number') {
  34916. n2 = this.nodes[n2];
  34917. }
  34918. if (!(n1 instanceof Node)) {
  34919. n1 = nodesMap[generateNodeKey(n1)];
  34920. }
  34921. if (!(n2 instanceof Node)) {
  34922. n2 = nodesMap[generateNodeKey(n2)];
  34923. }
  34924. if (!n1 || !n2) {
  34925. return;
  34926. }
  34927. var key = n1.id + '-' + n2.id;
  34928. // PENDING
  34929. if (edgesMap[key]) {
  34930. return;
  34931. }
  34932. var edge = new Edge(n1, n2, dataIndex);
  34933. edge.hostGraph = this;
  34934. if (this._directed) {
  34935. n1.outEdges.push(edge);
  34936. n2.inEdges.push(edge);
  34937. }
  34938. n1.edges.push(edge);
  34939. if (n1 !== n2) {
  34940. n2.edges.push(edge);
  34941. }
  34942. this.edges.push(edge);
  34943. edgesMap[key] = edge;
  34944. return edge;
  34945. };
  34946. /**
  34947. * Get edge by data index
  34948. * @param {number} dataIndex
  34949. * @return {module:echarts/data/Graph~Node}
  34950. */
  34951. graphProto.getEdgeByIndex = function (dataIndex) {
  34952. var rawIdx = this.edgeData.getRawIndex(dataIndex);
  34953. return this.edges[rawIdx];
  34954. };
  34955. /**
  34956. * Get edge by two linked nodes
  34957. * @param {module:echarts/data/Graph.Node|string} n1
  34958. * @param {module:echarts/data/Graph.Node|string} n2
  34959. * @return {module:echarts/data/Graph.Edge}
  34960. */
  34961. graphProto.getEdge = function (n1, n2) {
  34962. if (n1 instanceof Node) {
  34963. n1 = n1.id;
  34964. }
  34965. if (n2 instanceof Node) {
  34966. n2 = n2.id;
  34967. }
  34968. var edgesMap = this._edgesMap;
  34969. if (this._directed) {
  34970. return edgesMap[n1 + '-' + n2];
  34971. } else {
  34972. return edgesMap[n1 + '-' + n2]
  34973. || edgesMap[n2 + '-' + n1];
  34974. }
  34975. };
  34976. /**
  34977. * Iterate all nodes
  34978. * @param {Function} cb
  34979. * @param {*} [context]
  34980. */
  34981. graphProto.eachNode = function (cb, context) {
  34982. var nodes = this.nodes;
  34983. var len = nodes.length;
  34984. for (var i = 0; i < len; i++) {
  34985. if (nodes[i].dataIndex >= 0) {
  34986. cb.call(context, nodes[i], i);
  34987. }
  34988. }
  34989. };
  34990. /**
  34991. * Iterate all edges
  34992. * @param {Function} cb
  34993. * @param {*} [context]
  34994. */
  34995. graphProto.eachEdge = function (cb, context) {
  34996. var edges = this.edges;
  34997. var len = edges.length;
  34998. for (var i = 0; i < len; i++) {
  34999. if (edges[i].dataIndex >= 0
  35000. && edges[i].node1.dataIndex >= 0
  35001. && edges[i].node2.dataIndex >= 0
  35002. ) {
  35003. cb.call(context, edges[i], i);
  35004. }
  35005. }
  35006. };
  35007. /**
  35008. * Breadth first traverse
  35009. * @param {Function} cb
  35010. * @param {module:echarts/data/Graph.Node} startNode
  35011. * @param {string} [direction='none'] 'none'|'in'|'out'
  35012. * @param {*} [context]
  35013. */
  35014. graphProto.breadthFirstTraverse = function (
  35015. cb, startNode, direction, context
  35016. ) {
  35017. if (!(startNode instanceof Node)) {
  35018. startNode = this._nodesMap[generateNodeKey(startNode)];
  35019. }
  35020. if (!startNode) {
  35021. return;
  35022. }
  35023. var edgeType = direction === 'out'
  35024. ? 'outEdges' : (direction === 'in' ? 'inEdges' : 'edges');
  35025. for (var i = 0; i < this.nodes.length; i++) {
  35026. this.nodes[i].__visited = false;
  35027. }
  35028. if (cb.call(context, startNode, null)) {
  35029. return;
  35030. }
  35031. var queue = [startNode];
  35032. while (queue.length) {
  35033. var currentNode = queue.shift();
  35034. var edges = currentNode[edgeType];
  35035. for (var i = 0; i < edges.length; i++) {
  35036. var e = edges[i];
  35037. var otherNode = e.node1 === currentNode
  35038. ? e.node2 : e.node1;
  35039. if (!otherNode.__visited) {
  35040. if (cb.call(context, otherNode, currentNode)) {
  35041. // Stop traversing
  35042. return;
  35043. }
  35044. queue.push(otherNode);
  35045. otherNode.__visited = true;
  35046. }
  35047. }
  35048. }
  35049. };
  35050. // TODO
  35051. // graphProto.depthFirstTraverse = function (
  35052. // cb, startNode, direction, context
  35053. // ) {
  35054. // };
  35055. // Filter update
  35056. graphProto.update = function () {
  35057. var data = this.data;
  35058. var edgeData = this.edgeData;
  35059. var nodes = this.nodes;
  35060. var edges = this.edges;
  35061. for (var i = 0, len = nodes.length; i < len; i++) {
  35062. nodes[i].dataIndex = -1;
  35063. }
  35064. for (var i = 0, len = data.count(); i < len; i++) {
  35065. nodes[data.getRawIndex(i)].dataIndex = i;
  35066. }
  35067. edgeData.filterSelf(function (idx) {
  35068. var edge = edges[edgeData.getRawIndex(idx)];
  35069. return edge.node1.dataIndex >= 0 && edge.node2.dataIndex >= 0;
  35070. });
  35071. // Update edge
  35072. for (var i = 0, len = edges.length; i < len; i++) {
  35073. edges[i].dataIndex = -1;
  35074. }
  35075. for (var i = 0, len = edgeData.count(); i < len; i++) {
  35076. edges[edgeData.getRawIndex(i)].dataIndex = i;
  35077. }
  35078. };
  35079. /**
  35080. * @return {module:echarts/data/Graph}
  35081. */
  35082. graphProto.clone = function () {
  35083. var graph = new Graph(this._directed);
  35084. var nodes = this.nodes;
  35085. var edges = this.edges;
  35086. for (var i = 0; i < nodes.length; i++) {
  35087. graph.addNode(nodes[i].id, nodes[i].dataIndex);
  35088. }
  35089. for (var i = 0; i < edges.length; i++) {
  35090. var e = edges[i];
  35091. graph.addEdge(e.node1.id, e.node2.id, e.dataIndex);
  35092. }
  35093. return graph;
  35094. };
  35095. /**
  35096. * @alias module:echarts/data/Graph.Node
  35097. */
  35098. function Node(id, dataIndex) {
  35099. /**
  35100. * @type {string}
  35101. */
  35102. this.id = id == null ? '' : id;
  35103. /**
  35104. * @type {Array.<module:echarts/data/Graph.Edge>}
  35105. */
  35106. this.inEdges = [];
  35107. /**
  35108. * @type {Array.<module:echarts/data/Graph.Edge>}
  35109. */
  35110. this.outEdges = [];
  35111. /**
  35112. * @type {Array.<module:echarts/data/Graph.Edge>}
  35113. */
  35114. this.edges = [];
  35115. /**
  35116. * @type {module:echarts/data/Graph}
  35117. */
  35118. this.hostGraph;
  35119. /**
  35120. * @type {number}
  35121. */
  35122. this.dataIndex = dataIndex == null ? -1 : dataIndex;
  35123. }
  35124. Node.prototype = {
  35125. constructor: Node,
  35126. /**
  35127. * @return {number}
  35128. */
  35129. degree: function () {
  35130. return this.edges.length;
  35131. },
  35132. /**
  35133. * @return {number}
  35134. */
  35135. inDegree: function () {
  35136. return this.inEdges.length;
  35137. },
  35138. /**
  35139. * @return {number}
  35140. */
  35141. outDegree: function () {
  35142. return this.outEdges.length;
  35143. },
  35144. /**
  35145. * @param {string} [path]
  35146. * @return {module:echarts/model/Model}
  35147. */
  35148. getModel: function (path) {
  35149. if (this.dataIndex < 0) {
  35150. return;
  35151. }
  35152. var graph = this.hostGraph;
  35153. var itemModel = graph.data.getItemModel(this.dataIndex);
  35154. return itemModel.getModel(path);
  35155. }
  35156. };
  35157. /**
  35158. * 图边
  35159. * @alias module:echarts/data/Graph.Edge
  35160. * @param {module:echarts/data/Graph.Node} n1
  35161. * @param {module:echarts/data/Graph.Node} n2
  35162. * @param {number} [dataIndex=-1]
  35163. */
  35164. function Edge(n1, n2, dataIndex) {
  35165. /**
  35166. * 节点1,如果是有向图则为源节点
  35167. * @type {module:echarts/data/Graph.Node}
  35168. */
  35169. this.node1 = n1;
  35170. /**
  35171. * 节点2,如果是有向图则为目标节点
  35172. * @type {module:echarts/data/Graph.Node}
  35173. */
  35174. this.node2 = n2;
  35175. this.dataIndex = dataIndex == null ? -1 : dataIndex;
  35176. }
  35177. /**
  35178. * @param {string} [path]
  35179. * @return {module:echarts/model/Model}
  35180. */
  35181. Edge.prototype.getModel = function (path) {
  35182. if (this.dataIndex < 0) {
  35183. return;
  35184. }
  35185. var graph = this.hostGraph;
  35186. var itemModel = graph.edgeData.getItemModel(this.dataIndex);
  35187. return itemModel.getModel(path);
  35188. };
  35189. var createGraphDataProxyMixin = function (hostName, dataName) {
  35190. return {
  35191. /**
  35192. * @param {string=} [dimension='value'] Default 'value'. can be 'a', 'b', 'c', 'd', 'e'.
  35193. * @return {number}
  35194. */
  35195. getValue: function (dimension) {
  35196. var data = this[hostName][dataName];
  35197. return data.get(data.getDimension(dimension || 'value'), this.dataIndex);
  35198. },
  35199. /**
  35200. * @param {Object|string} key
  35201. * @param {*} [value]
  35202. */
  35203. setVisual: function (key, value) {
  35204. this.dataIndex >= 0
  35205. && this[hostName][dataName].setItemVisual(this.dataIndex, key, value);
  35206. },
  35207. /**
  35208. * @param {string} key
  35209. * @return {boolean}
  35210. */
  35211. getVisual: function (key, ignoreParent) {
  35212. return this[hostName][dataName].getItemVisual(this.dataIndex, key, ignoreParent);
  35213. },
  35214. /**
  35215. * @param {Object} layout
  35216. * @return {boolean} [merge=false]
  35217. */
  35218. setLayout: function (layout, merge) {
  35219. this.dataIndex >= 0
  35220. && this[hostName][dataName].setItemLayout(this.dataIndex, layout, merge);
  35221. },
  35222. /**
  35223. * @return {Object}
  35224. */
  35225. getLayout: function () {
  35226. return this[hostName][dataName].getItemLayout(this.dataIndex);
  35227. },
  35228. /**
  35229. * @return {module:zrender/Element}
  35230. */
  35231. getGraphicEl: function () {
  35232. return this[hostName][dataName].getItemGraphicEl(this.dataIndex);
  35233. },
  35234. /**
  35235. * @return {number}
  35236. */
  35237. getRawIndex: function () {
  35238. return this[hostName][dataName].getRawIndex(this.dataIndex);
  35239. }
  35240. };
  35241. };
  35242. zrUtil.mixin(Node, createGraphDataProxyMixin('hostGraph', 'data'));
  35243. zrUtil.mixin(Edge, createGraphDataProxyMixin('hostGraph', 'edgeData'));
  35244. Graph.Node = Node;
  35245. Graph.Edge = Edge;
  35246. module.exports = Graph;
  35247. /***/ },
  35248. /* 208 */
  35249. /***/ function(module, exports, __webpack_require__) {
  35250. var SymbolDraw = __webpack_require__(116);
  35251. var LineDraw = __webpack_require__(209);
  35252. var RoamController = __webpack_require__(182);
  35253. var roamHelper = __webpack_require__(184);
  35254. var cursorHelper = __webpack_require__(185);
  35255. var graphic = __webpack_require__(18);
  35256. var adjustEdge = __webpack_require__(212);
  35257. var zrUtil = __webpack_require__(4);
  35258. var nodeOpacityPath = ['itemStyle', 'normal', 'opacity'];
  35259. var lineOpacityPath = ['lineStyle', 'normal', 'opacity'];
  35260. function getItemOpacity(item, opacityPath) {
  35261. return item.getVisual('opacity') || item.getModel().get(opacityPath);
  35262. }
  35263. __webpack_require__(1).extendChartView({
  35264. type: 'graph',
  35265. init: function (ecModel, api) {
  35266. var symbolDraw = new SymbolDraw();
  35267. var lineDraw = new LineDraw();
  35268. var group = this.group;
  35269. this._controller = new RoamController(api.getZr());
  35270. this._controllerHost = {target: group};
  35271. group.add(symbolDraw.group);
  35272. group.add(lineDraw.group);
  35273. this._symbolDraw = symbolDraw;
  35274. this._lineDraw = lineDraw;
  35275. this._firstRender = true;
  35276. },
  35277. render: function (seriesModel, ecModel, api) {
  35278. var coordSys = seriesModel.coordinateSystem;
  35279. this._model = seriesModel;
  35280. this._nodeScaleRatio = seriesModel.get('nodeScaleRatio');
  35281. var symbolDraw = this._symbolDraw;
  35282. var lineDraw = this._lineDraw;
  35283. var group = this.group;
  35284. if (coordSys.type === 'view') {
  35285. var groupNewProp = {
  35286. position: coordSys.position,
  35287. scale: coordSys.scale
  35288. };
  35289. if (this._firstRender) {
  35290. group.attr(groupNewProp);
  35291. }
  35292. else {
  35293. graphic.updateProps(group, groupNewProp, seriesModel);
  35294. }
  35295. }
  35296. // Fix edge contact point with node
  35297. adjustEdge(seriesModel.getGraph(), this._getNodeGlobalScale(seriesModel));
  35298. var data = seriesModel.getData();
  35299. symbolDraw.updateData(data);
  35300. var edgeData = seriesModel.getEdgeData();
  35301. lineDraw.updateData(edgeData);
  35302. this._updateNodeAndLinkScale();
  35303. this._updateController(seriesModel, ecModel, api);
  35304. clearTimeout(this._layoutTimeout);
  35305. var forceLayout = seriesModel.forceLayout;
  35306. var layoutAnimation = seriesModel.get('force.layoutAnimation');
  35307. if (forceLayout) {
  35308. this._startForceLayoutIteration(forceLayout, layoutAnimation);
  35309. }
  35310. data.eachItemGraphicEl(function (el, idx) {
  35311. var itemModel = data.getItemModel(idx);
  35312. // Update draggable
  35313. el.off('drag').off('dragend');
  35314. var draggable = data.getItemModel(idx).get('draggable');
  35315. if (draggable) {
  35316. el.on('drag', function () {
  35317. if (forceLayout) {
  35318. forceLayout.warmUp();
  35319. !this._layouting
  35320. && this._startForceLayoutIteration(forceLayout, layoutAnimation);
  35321. forceLayout.setFixed(idx);
  35322. // Write position back to layout
  35323. data.setItemLayout(idx, el.position);
  35324. }
  35325. }, this).on('dragend', function () {
  35326. if (forceLayout) {
  35327. forceLayout.setUnfixed(idx);
  35328. }
  35329. }, this);
  35330. }
  35331. el.setDraggable(draggable && forceLayout);
  35332. el.off('mouseover', el.__focusNodeAdjacency);
  35333. el.off('mouseout', el.__unfocusNodeAdjacency);
  35334. if (itemModel.get('focusNodeAdjacency')) {
  35335. el.on('mouseover', el.__focusNodeAdjacency = function () {
  35336. api.dispatchAction({
  35337. type: 'focusNodeAdjacency',
  35338. seriesId: seriesModel.id,
  35339. dataIndex: el.dataIndex
  35340. });
  35341. });
  35342. el.on('mouseout', el.__unfocusNodeAdjacency = function () {
  35343. api.dispatchAction({
  35344. type: 'unfocusNodeAdjacency',
  35345. seriesId: seriesModel.id
  35346. });
  35347. });
  35348. }
  35349. }, this);
  35350. var circularRotateLabel = seriesModel.get('layout') === 'circular' && seriesModel.get('circular.rotateLabel');
  35351. var cx = data.getLayout('cx');
  35352. var cy = data.getLayout('cy');
  35353. data.eachItemGraphicEl(function (el, idx) {
  35354. var symbolPath = el.getSymbolPath();
  35355. if (circularRotateLabel) {
  35356. var pos = data.getItemLayout(idx);
  35357. var rad = Math.atan2(pos[1] - cy, pos[0] - cx);
  35358. if (rad < 0) {
  35359. rad = Math.PI * 2 + rad;
  35360. }
  35361. var isLeft = pos[0] < cx;
  35362. if (isLeft) {
  35363. rad = rad - Math.PI;
  35364. }
  35365. var textPosition = isLeft ? 'left' : 'right';
  35366. symbolPath.setStyle({
  35367. textRotation: rad,
  35368. textPosition: textPosition
  35369. });
  35370. symbolPath.hoverStyle && (symbolPath.hoverStyle.textPosition = textPosition);
  35371. }
  35372. else {
  35373. symbolPath.setStyle({
  35374. textRotation: 0
  35375. });
  35376. }
  35377. });
  35378. this._firstRender = false;
  35379. },
  35380. dispose: function () {
  35381. this._controller && this._controller.dispose();
  35382. this._controllerHost = {};
  35383. },
  35384. focusNodeAdjacency: function (seriesModel, ecModel, api, payload) {
  35385. var data = this._model.getData();
  35386. var dataIndex = payload.dataIndex;
  35387. var el = data.getItemGraphicEl(dataIndex);
  35388. if (!el) {
  35389. return;
  35390. }
  35391. var graph = data.graph;
  35392. var dataType = el.dataType;
  35393. function fadeOutItem(item, opacityPath) {
  35394. var opacity = getItemOpacity(item, opacityPath);
  35395. var el = item.getGraphicEl();
  35396. if (opacity == null) {
  35397. opacity = 1;
  35398. }
  35399. el.traverse(function (child) {
  35400. child.trigger('normal');
  35401. if (child.type !== 'group') {
  35402. child.setStyle('opacity', opacity * 0.1);
  35403. }
  35404. });
  35405. }
  35406. function fadeInItem(item, opacityPath) {
  35407. var opacity = getItemOpacity(item, opacityPath);
  35408. var el = item.getGraphicEl();
  35409. el.traverse(function (child) {
  35410. child.trigger('emphasis');
  35411. if (child.type !== 'group') {
  35412. child.setStyle('opacity', opacity);
  35413. }
  35414. });
  35415. }
  35416. if (dataIndex !== null && dataType !== 'edge') {
  35417. graph.eachNode(function (node) {
  35418. fadeOutItem(node, nodeOpacityPath);
  35419. });
  35420. graph.eachEdge(function (edge) {
  35421. fadeOutItem(edge, lineOpacityPath);
  35422. });
  35423. var node = graph.getNodeByIndex(dataIndex);
  35424. fadeInItem(node, nodeOpacityPath);
  35425. zrUtil.each(node.edges, function (edge) {
  35426. if (edge.dataIndex < 0) {
  35427. return;
  35428. }
  35429. fadeInItem(edge, lineOpacityPath);
  35430. fadeInItem(edge.node1, nodeOpacityPath);
  35431. fadeInItem(edge.node2, nodeOpacityPath);
  35432. });
  35433. }
  35434. },
  35435. unfocusNodeAdjacency: function (seriesModel, ecModel, api, payload) {
  35436. var graph = this._model.getData().graph;
  35437. graph.eachNode(function (node) {
  35438. var opacity = getItemOpacity(node, nodeOpacityPath);
  35439. node.getGraphicEl().traverse(function (child) {
  35440. child.trigger('normal');
  35441. if (child.type !== 'group') {
  35442. child.setStyle('opacity', opacity);
  35443. }
  35444. });
  35445. });
  35446. graph.eachEdge(function (edge) {
  35447. var opacity = getItemOpacity(edge, lineOpacityPath);
  35448. edge.getGraphicEl().traverse(function (child) {
  35449. child.trigger('normal');
  35450. if (child.type !== 'group') {
  35451. child.setStyle('opacity', opacity);
  35452. }
  35453. });
  35454. });
  35455. },
  35456. _startForceLayoutIteration: function (forceLayout, layoutAnimation) {
  35457. var self = this;
  35458. (function step() {
  35459. forceLayout.step(function (stopped) {
  35460. self.updateLayout(self._model);
  35461. (self._layouting = !stopped) && (
  35462. layoutAnimation
  35463. ? (self._layoutTimeout = setTimeout(step, 16))
  35464. : step()
  35465. );
  35466. });
  35467. })();
  35468. },
  35469. _updateController: function (seriesModel, ecModel, api) {
  35470. var controller = this._controller;
  35471. var controllerHost = this._controllerHost;
  35472. var group = this.group;
  35473. controller.setPointerChecker(function (e, x, y) {
  35474. var rect = group.getBoundingRect();
  35475. rect.applyTransform(group.transform);
  35476. return rect.contain(x, y)
  35477. && !cursorHelper.onIrrelevantElement(e, api, seriesModel);
  35478. });
  35479. if (seriesModel.coordinateSystem.type !== 'view') {
  35480. controller.disable();
  35481. return;
  35482. }
  35483. controller.enable(seriesModel.get('roam'));
  35484. controllerHost.zoomLimit = seriesModel.get('scaleLimit');
  35485. controllerHost.zoom = seriesModel.coordinateSystem.getZoom();
  35486. controller
  35487. .off('pan')
  35488. .off('zoom')
  35489. .on('pan', function (dx, dy) {
  35490. roamHelper.updateViewOnPan(controllerHost, dx, dy);
  35491. api.dispatchAction({
  35492. seriesId: seriesModel.id,
  35493. type: 'graphRoam',
  35494. dx: dx,
  35495. dy: dy
  35496. });
  35497. })
  35498. .on('zoom', function (zoom, mouseX, mouseY) {
  35499. roamHelper.updateViewOnZoom(controllerHost, zoom, mouseX, mouseY);
  35500. api.dispatchAction({
  35501. seriesId: seriesModel.id,
  35502. type: 'graphRoam',
  35503. zoom: zoom,
  35504. originX: mouseX,
  35505. originY: mouseY
  35506. });
  35507. this._updateNodeAndLinkScale();
  35508. adjustEdge(seriesModel.getGraph(), this._getNodeGlobalScale(seriesModel));
  35509. this._lineDraw.updateLayout();
  35510. }, this);
  35511. },
  35512. _updateNodeAndLinkScale: function () {
  35513. var seriesModel = this._model;
  35514. var data = seriesModel.getData();
  35515. var nodeScale = this._getNodeGlobalScale(seriesModel);
  35516. var invScale = [nodeScale, nodeScale];
  35517. data.eachItemGraphicEl(function (el, idx) {
  35518. el.attr('scale', invScale);
  35519. });
  35520. },
  35521. _getNodeGlobalScale: function (seriesModel) {
  35522. var coordSys = seriesModel.coordinateSystem;
  35523. if (coordSys.type !== 'view') {
  35524. return 1;
  35525. }
  35526. var nodeScaleRatio = this._nodeScaleRatio;
  35527. var groupScale = coordSys.scale;
  35528. var groupZoom = (groupScale && groupScale[0]) || 1;
  35529. // Scale node when zoom changes
  35530. var roamZoom = coordSys.getZoom();
  35531. var nodeScale = (roamZoom - 1) * nodeScaleRatio + 1;
  35532. return nodeScale / groupZoom;
  35533. },
  35534. updateLayout: function (seriesModel) {
  35535. adjustEdge(seriesModel.getGraph(), this._getNodeGlobalScale(seriesModel));
  35536. this._symbolDraw.updateLayout();
  35537. this._lineDraw.updateLayout();
  35538. },
  35539. remove: function (ecModel, api) {
  35540. this._symbolDraw && this._symbolDraw.remove();
  35541. this._lineDraw && this._lineDraw.remove();
  35542. }
  35543. });
  35544. /***/ },
  35545. /* 209 */
  35546. /***/ function(module, exports, __webpack_require__) {
  35547. /**
  35548. * @module echarts/chart/helper/LineDraw
  35549. */
  35550. var graphic = __webpack_require__(18);
  35551. var LineGroup = __webpack_require__(210);
  35552. function isPointNaN(pt) {
  35553. return isNaN(pt[0]) || isNaN(pt[1]);
  35554. }
  35555. function lineNeedsDraw(pts) {
  35556. return !isPointNaN(pts[0]) && !isPointNaN(pts[1]);
  35557. }
  35558. /**
  35559. * @alias module:echarts/component/marker/LineDraw
  35560. * @constructor
  35561. */
  35562. function LineDraw(ctor) {
  35563. this._ctor = ctor || LineGroup;
  35564. this.group = new graphic.Group();
  35565. }
  35566. var lineDrawProto = LineDraw.prototype;
  35567. /**
  35568. * @param {module:echarts/data/List} lineData
  35569. */
  35570. lineDrawProto.updateData = function (lineData) {
  35571. var oldLineData = this._lineData;
  35572. var group = this.group;
  35573. var LineCtor = this._ctor;
  35574. var hostModel = lineData.hostModel;
  35575. var seriesScope = {
  35576. lineStyle: hostModel.getModel('lineStyle.normal').getLineStyle(),
  35577. hoverLineStyle: hostModel.getModel('lineStyle.emphasis').getLineStyle(),
  35578. labelModel: hostModel.getModel('label.normal'),
  35579. hoverLabelModel: hostModel.getModel('label.emphasis')
  35580. };
  35581. lineData.diff(oldLineData)
  35582. .add(function (idx) {
  35583. if (!lineNeedsDraw(lineData.getItemLayout(idx))) {
  35584. return;
  35585. }
  35586. var lineGroup = new LineCtor(lineData, idx, seriesScope);
  35587. lineData.setItemGraphicEl(idx, lineGroup);
  35588. group.add(lineGroup);
  35589. })
  35590. .update(function (newIdx, oldIdx) {
  35591. var lineGroup = oldLineData.getItemGraphicEl(oldIdx);
  35592. if (!lineNeedsDraw(lineData.getItemLayout(newIdx))) {
  35593. group.remove(lineGroup);
  35594. return;
  35595. }
  35596. if (!lineGroup) {
  35597. lineGroup = new LineCtor(lineData, newIdx, seriesScope);
  35598. }
  35599. else {
  35600. lineGroup.updateData(lineData, newIdx, seriesScope);
  35601. }
  35602. lineData.setItemGraphicEl(newIdx, lineGroup);
  35603. group.add(lineGroup);
  35604. })
  35605. .remove(function (idx) {
  35606. group.remove(oldLineData.getItemGraphicEl(idx));
  35607. })
  35608. .execute();
  35609. this._lineData = lineData;
  35610. };
  35611. lineDrawProto.updateLayout = function () {
  35612. var lineData = this._lineData;
  35613. lineData.eachItemGraphicEl(function (el, idx) {
  35614. el.updateLayout(lineData, idx);
  35615. }, this);
  35616. };
  35617. lineDrawProto.remove = function () {
  35618. this.group.removeAll();
  35619. };
  35620. module.exports = LineDraw;
  35621. /***/ },
  35622. /* 210 */
  35623. /***/ function(module, exports, __webpack_require__) {
  35624. /**
  35625. * @module echarts/chart/helper/Line
  35626. */
  35627. var symbolUtil = __webpack_require__(111);
  35628. var vector = __webpack_require__(10);
  35629. // var matrix = require('zrender/lib/core/matrix');
  35630. var LinePath = __webpack_require__(211);
  35631. var graphic = __webpack_require__(18);
  35632. var zrUtil = __webpack_require__(4);
  35633. var numberUtil = __webpack_require__(7);
  35634. var SYMBOL_CATEGORIES = ['fromSymbol', 'toSymbol'];
  35635. function makeSymbolTypeKey(symbolCategory) {
  35636. return '_' + symbolCategory + 'Type';
  35637. }
  35638. /**
  35639. * @inner
  35640. */
  35641. function createSymbol(name, lineData, idx) {
  35642. var color = lineData.getItemVisual(idx, 'color');
  35643. var symbolType = lineData.getItemVisual(idx, name);
  35644. var symbolSize = lineData.getItemVisual(idx, name + 'Size');
  35645. if (!symbolType || symbolType === 'none') {
  35646. return;
  35647. }
  35648. if (!zrUtil.isArray(symbolSize)) {
  35649. symbolSize = [symbolSize, symbolSize];
  35650. }
  35651. var symbolPath = symbolUtil.createSymbol(
  35652. symbolType, -symbolSize[0] / 2, -symbolSize[1] / 2,
  35653. symbolSize[0], symbolSize[1], color
  35654. );
  35655. symbolPath.name = name;
  35656. return symbolPath;
  35657. }
  35658. function createLine(points) {
  35659. var line = new LinePath({
  35660. name: 'line'
  35661. });
  35662. setLinePoints(line.shape, points);
  35663. return line;
  35664. }
  35665. function setLinePoints(targetShape, points) {
  35666. var p1 = points[0];
  35667. var p2 = points[1];
  35668. var cp1 = points[2];
  35669. targetShape.x1 = p1[0];
  35670. targetShape.y1 = p1[1];
  35671. targetShape.x2 = p2[0];
  35672. targetShape.y2 = p2[1];
  35673. targetShape.percent = 1;
  35674. if (cp1) {
  35675. targetShape.cpx1 = cp1[0];
  35676. targetShape.cpy1 = cp1[1];
  35677. }
  35678. else {
  35679. targetShape.cpx1 = NaN;
  35680. targetShape.cpy1 = NaN;
  35681. }
  35682. }
  35683. function updateSymbolAndLabelBeforeLineUpdate () {
  35684. var lineGroup = this;
  35685. var symbolFrom = lineGroup.childOfName('fromSymbol');
  35686. var symbolTo = lineGroup.childOfName('toSymbol');
  35687. var label = lineGroup.childOfName('label');
  35688. // Quick reject
  35689. if (!symbolFrom && !symbolTo && label.ignore) {
  35690. return;
  35691. }
  35692. var invScale = 1;
  35693. var parentNode = this.parent;
  35694. while (parentNode) {
  35695. if (parentNode.scale) {
  35696. invScale /= parentNode.scale[0];
  35697. }
  35698. parentNode = parentNode.parent;
  35699. }
  35700. var line = lineGroup.childOfName('line');
  35701. // If line not changed
  35702. // FIXME Parent scale changed
  35703. if (!this.__dirty && !line.__dirty) {
  35704. return;
  35705. }
  35706. var percent = line.shape.percent;
  35707. var fromPos = line.pointAt(0);
  35708. var toPos = line.pointAt(percent);
  35709. var d = vector.sub([], toPos, fromPos);
  35710. vector.normalize(d, d);
  35711. if (symbolFrom) {
  35712. symbolFrom.attr('position', fromPos);
  35713. var tangent = line.tangentAt(0);
  35714. symbolFrom.attr('rotation', Math.PI / 2 - Math.atan2(
  35715. tangent[1], tangent[0]
  35716. ));
  35717. symbolFrom.attr('scale', [invScale * percent, invScale * percent]);
  35718. }
  35719. if (symbolTo) {
  35720. symbolTo.attr('position', toPos);
  35721. var tangent = line.tangentAt(1);
  35722. symbolTo.attr('rotation', -Math.PI / 2 - Math.atan2(
  35723. tangent[1], tangent[0]
  35724. ));
  35725. symbolTo.attr('scale', [invScale * percent, invScale * percent]);
  35726. }
  35727. if (!label.ignore) {
  35728. label.attr('position', toPos);
  35729. var textPosition;
  35730. var textAlign;
  35731. var textVerticalAlign;
  35732. var distance = 5 * invScale;
  35733. // End
  35734. if (label.__position === 'end') {
  35735. textPosition = [d[0] * distance + toPos[0], d[1] * distance + toPos[1]];
  35736. textAlign = d[0] > 0.8 ? 'left' : (d[0] < -0.8 ? 'right' : 'center');
  35737. textVerticalAlign = d[1] > 0.8 ? 'top' : (d[1] < -0.8 ? 'bottom' : 'middle');
  35738. }
  35739. // Middle
  35740. else if (label.__position === 'middle') {
  35741. var halfPercent = percent / 2;
  35742. var tangent = line.tangentAt(halfPercent);
  35743. var n = [tangent[1], -tangent[0]];
  35744. var cp = line.pointAt(halfPercent);
  35745. if (n[1] > 0) {
  35746. n[0] = -n[0];
  35747. n[1] = -n[1];
  35748. }
  35749. textPosition = [cp[0] + n[0] * distance, cp[1] + n[1] * distance];
  35750. textAlign = 'center';
  35751. textVerticalAlign = 'bottom';
  35752. var rotation = -Math.atan2(tangent[1], tangent[0]);
  35753. if (toPos[0] < fromPos[0]) {
  35754. rotation = Math.PI + rotation;
  35755. }
  35756. label.attr('rotation', rotation);
  35757. }
  35758. // Start
  35759. else {
  35760. textPosition = [-d[0] * distance + fromPos[0], -d[1] * distance + fromPos[1]];
  35761. textAlign = d[0] > 0.8 ? 'right' : (d[0] < -0.8 ? 'left' : 'center');
  35762. textVerticalAlign = d[1] > 0.8 ? 'bottom' : (d[1] < -0.8 ? 'top' : 'middle');
  35763. }
  35764. label.attr({
  35765. style: {
  35766. // Use the user specified text align and baseline first
  35767. textVerticalAlign: label.__verticalAlign || textVerticalAlign,
  35768. textAlign: label.__textAlign || textAlign
  35769. },
  35770. position: textPosition,
  35771. scale: [invScale, invScale]
  35772. });
  35773. }
  35774. }
  35775. /**
  35776. * @constructor
  35777. * @extends {module:zrender/graphic/Group}
  35778. * @alias {module:echarts/chart/helper/Line}
  35779. */
  35780. function Line(lineData, idx, seriesScope) {
  35781. graphic.Group.call(this);
  35782. this._createLine(lineData, idx, seriesScope);
  35783. }
  35784. var lineProto = Line.prototype;
  35785. // Update symbol position and rotation
  35786. lineProto.beforeUpdate = updateSymbolAndLabelBeforeLineUpdate;
  35787. lineProto._createLine = function (lineData, idx, seriesScope) {
  35788. var seriesModel = lineData.hostModel;
  35789. var linePoints = lineData.getItemLayout(idx);
  35790. var line = createLine(linePoints);
  35791. line.shape.percent = 0;
  35792. graphic.initProps(line, {
  35793. shape: {
  35794. percent: 1
  35795. }
  35796. }, seriesModel, idx);
  35797. this.add(line);
  35798. var label = new graphic.Text({
  35799. name: 'label'
  35800. });
  35801. this.add(label);
  35802. zrUtil.each(SYMBOL_CATEGORIES, function (symbolCategory) {
  35803. var symbol = createSymbol(symbolCategory, lineData, idx);
  35804. // symbols must added after line to make sure
  35805. // it will be updated after line#update.
  35806. // Or symbol position and rotation update in line#beforeUpdate will be one frame slow
  35807. this.add(symbol);
  35808. this[makeSymbolTypeKey(symbolCategory)] = lineData.getItemVisual(idx, symbolCategory);
  35809. }, this);
  35810. this._updateCommonStl(lineData, idx, seriesScope);
  35811. };
  35812. lineProto.updateData = function (lineData, idx, seriesScope) {
  35813. var seriesModel = lineData.hostModel;
  35814. var line = this.childOfName('line');
  35815. var linePoints = lineData.getItemLayout(idx);
  35816. var target = {
  35817. shape: {}
  35818. };
  35819. setLinePoints(target.shape, linePoints);
  35820. graphic.updateProps(line, target, seriesModel, idx);
  35821. zrUtil.each(SYMBOL_CATEGORIES, function (symbolCategory) {
  35822. var symbolType = lineData.getItemVisual(idx, symbolCategory);
  35823. var key = makeSymbolTypeKey(symbolCategory);
  35824. // Symbol changed
  35825. if (this[key] !== symbolType) {
  35826. this.remove(this.childOfName(symbolCategory));
  35827. var symbol = createSymbol(symbolCategory, lineData, idx);
  35828. this.add(symbol);
  35829. }
  35830. this[key] = symbolType;
  35831. }, this);
  35832. this._updateCommonStl(lineData, idx, seriesScope);
  35833. };
  35834. lineProto._updateCommonStl = function (lineData, idx, seriesScope) {
  35835. var seriesModel = lineData.hostModel;
  35836. var line = this.childOfName('line');
  35837. var lineStyle = seriesScope && seriesScope.lineStyle;
  35838. var hoverLineStyle = seriesScope && seriesScope.hoverLineStyle;
  35839. var labelModel = seriesScope && seriesScope.labelModel;
  35840. var hoverLabelModel = seriesScope && seriesScope.hoverLabelModel;
  35841. // Optimization for large dataset
  35842. if (!seriesScope || lineData.hasItemOption) {
  35843. var itemModel = lineData.getItemModel(idx);
  35844. lineStyle = itemModel.getModel('lineStyle.normal').getLineStyle();
  35845. hoverLineStyle = itemModel.getModel('lineStyle.emphasis').getLineStyle();
  35846. labelModel = itemModel.getModel('label.normal');
  35847. hoverLabelModel = itemModel.getModel('label.emphasis');
  35848. }
  35849. var visualColor = lineData.getItemVisual(idx, 'color');
  35850. var visualOpacity = zrUtil.retrieve(
  35851. lineData.getItemVisual(idx, 'opacity'),
  35852. lineStyle.opacity,
  35853. 1
  35854. );
  35855. line.useStyle(zrUtil.defaults(
  35856. {
  35857. strokeNoScale: true,
  35858. fill: 'none',
  35859. stroke: visualColor,
  35860. opacity: visualOpacity
  35861. },
  35862. lineStyle
  35863. ));
  35864. line.hoverStyle = hoverLineStyle;
  35865. // Update symbol
  35866. zrUtil.each(SYMBOL_CATEGORIES, function (symbolCategory) {
  35867. var symbol = this.childOfName(symbolCategory);
  35868. if (symbol) {
  35869. symbol.setColor(visualColor);
  35870. symbol.setStyle({
  35871. opacity: visualOpacity
  35872. });
  35873. }
  35874. }, this);
  35875. var showLabel = labelModel.getShallow('show');
  35876. var hoverShowLabel = hoverLabelModel.getShallow('show');
  35877. var label = this.childOfName('label');
  35878. var defaultLabelColor;
  35879. var defaultText;
  35880. if (showLabel || hoverShowLabel) {
  35881. var rawVal = seriesModel.getRawValue(idx);
  35882. defaultText = rawVal == null
  35883. ? defaultText = lineData.getName(idx)
  35884. : isFinite(rawVal)
  35885. ? numberUtil.round(rawVal)
  35886. : rawVal;
  35887. defaultLabelColor = visualColor || '#000';
  35888. }
  35889. // label.afterUpdate = lineAfterUpdate;
  35890. if (showLabel) {
  35891. var textStyleModel = labelModel.getModel('textStyle');
  35892. label.setStyle({
  35893. text: zrUtil.retrieve(
  35894. seriesModel.getFormattedLabel(idx, 'normal', lineData.dataType),
  35895. defaultText
  35896. ),
  35897. textFont: textStyleModel.getFont(),
  35898. fill: textStyleModel.getTextColor() || defaultLabelColor
  35899. });
  35900. label.__textAlign = textStyleModel.get('align');
  35901. label.__verticalAlign = textStyleModel.get('baseline');
  35902. label.__position = labelModel.get('position');
  35903. }
  35904. else {
  35905. label.setStyle('text', '');
  35906. }
  35907. if (hoverShowLabel) {
  35908. var textStyleHoverModel = hoverLabelModel.getModel('textStyle');
  35909. label.hoverStyle = {
  35910. text: zrUtil.retrieve(
  35911. seriesModel.getFormattedLabel(idx, 'emphasis', lineData.dataType),
  35912. defaultText
  35913. ),
  35914. textFont: textStyleHoverModel.getFont(),
  35915. fill: textStyleHoverModel.getTextColor() || defaultLabelColor
  35916. };
  35917. }
  35918. else {
  35919. label.hoverStyle = {
  35920. text: ''
  35921. };
  35922. }
  35923. label.ignore = !showLabel && !hoverShowLabel;
  35924. graphic.setHoverStyle(this);
  35925. };
  35926. lineProto.updateLayout = function (lineData, idx) {
  35927. this.setLinePoints(lineData.getItemLayout(idx));
  35928. };
  35929. lineProto.setLinePoints = function (points) {
  35930. var linePath = this.childOfName('line');
  35931. setLinePoints(linePath.shape, points);
  35932. linePath.dirty();
  35933. };
  35934. zrUtil.inherits(Line, graphic.Group);
  35935. module.exports = Line;
  35936. /***/ },
  35937. /* 211 */
  35938. /***/ function(module, exports, __webpack_require__) {
  35939. /**
  35940. * Line path for bezier and straight line draw
  35941. */
  35942. var graphic = __webpack_require__(18);
  35943. var vec2 = __webpack_require__(10);
  35944. var straightLineProto = graphic.Line.prototype;
  35945. var bezierCurveProto = graphic.BezierCurve.prototype;
  35946. function isLine(shape) {
  35947. return isNaN(+shape.cpx1) || isNaN(+shape.cpy1);
  35948. }
  35949. module.exports = graphic.extendShape({
  35950. type: 'ec-line',
  35951. style: {
  35952. stroke: '#000',
  35953. fill: null
  35954. },
  35955. shape: {
  35956. x1: 0,
  35957. y1: 0,
  35958. x2: 0,
  35959. y2: 0,
  35960. percent: 1,
  35961. cpx1: null,
  35962. cpy1: null
  35963. },
  35964. buildPath: function (ctx, shape) {
  35965. (isLine(shape) ? straightLineProto : bezierCurveProto).buildPath(ctx, shape);
  35966. },
  35967. pointAt: function (t) {
  35968. return isLine(this.shape)
  35969. ? straightLineProto.pointAt.call(this, t)
  35970. : bezierCurveProto.pointAt.call(this, t);
  35971. },
  35972. tangentAt: function (t) {
  35973. var shape = this.shape;
  35974. var p = isLine(shape)
  35975. ? [shape.x2 - shape.x1, shape.y2 - shape.y1]
  35976. : bezierCurveProto.tangentAt.call(this, t);
  35977. return vec2.normalize(p, p);
  35978. }
  35979. });
  35980. /***/ },
  35981. /* 212 */
  35982. /***/ function(module, exports, __webpack_require__) {
  35983. var curveTool = __webpack_require__(37);
  35984. var vec2 = __webpack_require__(10);
  35985. var v1 = [];
  35986. var v2 = [];
  35987. var v3 = [];
  35988. var quadraticAt = curveTool.quadraticAt;
  35989. var v2DistSquare = vec2.distSquare;
  35990. var mathAbs = Math.abs;
  35991. function intersectCurveCircle(curvePoints, center, radius) {
  35992. var p0 = curvePoints[0];
  35993. var p1 = curvePoints[1];
  35994. var p2 = curvePoints[2];
  35995. var d = Infinity;
  35996. var t;
  35997. var radiusSquare = radius * radius;
  35998. var interval = 0.1;
  35999. for (var _t = 0.1; _t <= 0.9; _t += 0.1) {
  36000. v1[0] = quadraticAt(p0[0], p1[0], p2[0], _t);
  36001. v1[1] = quadraticAt(p0[1], p1[1], p2[1], _t);
  36002. var diff = mathAbs(v2DistSquare(v1, center) - radiusSquare);
  36003. if (diff < d) {
  36004. d = diff;
  36005. t = _t;
  36006. }
  36007. }
  36008. // Assume the segment is monotone,Find root through Bisection method
  36009. // At most 32 iteration
  36010. for (var i = 0; i < 32; i++) {
  36011. // var prev = t - interval;
  36012. var next = t + interval;
  36013. // v1[0] = quadraticAt(p0[0], p1[0], p2[0], prev);
  36014. // v1[1] = quadraticAt(p0[1], p1[1], p2[1], prev);
  36015. v2[0] = quadraticAt(p0[0], p1[0], p2[0], t);
  36016. v2[1] = quadraticAt(p0[1], p1[1], p2[1], t);
  36017. v3[0] = quadraticAt(p0[0], p1[0], p2[0], next);
  36018. v3[1] = quadraticAt(p0[1], p1[1], p2[1], next);
  36019. var diff = v2DistSquare(v2, center) - radiusSquare;
  36020. if (mathAbs(diff) < 1e-2) {
  36021. break;
  36022. }
  36023. // var prevDiff = v2DistSquare(v1, center) - radiusSquare;
  36024. var nextDiff = v2DistSquare(v3, center) - radiusSquare;
  36025. interval /= 2;
  36026. if (diff < 0) {
  36027. if (nextDiff >= 0) {
  36028. t = t + interval;
  36029. }
  36030. else {
  36031. t = t - interval;
  36032. }
  36033. }
  36034. else {
  36035. if (nextDiff >= 0) {
  36036. t = t - interval;
  36037. }
  36038. else {
  36039. t = t + interval;
  36040. }
  36041. }
  36042. }
  36043. return t;
  36044. }
  36045. // Adjust edge to avoid
  36046. module.exports = function (graph, scale) {
  36047. var tmp0 = [];
  36048. var quadraticSubdivide = curveTool.quadraticSubdivide;
  36049. var pts = [[], [], []];
  36050. var pts2 = [[], []];
  36051. var v = [];
  36052. scale /= 2;
  36053. function getSymbolSize(node) {
  36054. var symbolSize = node.getVisual('symbolSize');
  36055. if (symbolSize instanceof Array) {
  36056. symbolSize = (symbolSize[0] + symbolSize[1]) / 2;
  36057. }
  36058. return symbolSize;
  36059. }
  36060. graph.eachEdge(function (edge, idx) {
  36061. var linePoints = edge.getLayout();
  36062. var fromSymbol = edge.getVisual('fromSymbol');
  36063. var toSymbol = edge.getVisual('toSymbol');
  36064. if (!linePoints.__original) {
  36065. linePoints.__original = [
  36066. vec2.clone(linePoints[0]),
  36067. vec2.clone(linePoints[1])
  36068. ];
  36069. if (linePoints[2]) {
  36070. linePoints.__original.push(vec2.clone(linePoints[2]));
  36071. }
  36072. }
  36073. var originalPoints = linePoints.__original;
  36074. // Quadratic curve
  36075. if (linePoints[2] != null) {
  36076. vec2.copy(pts[0], originalPoints[0]);
  36077. vec2.copy(pts[1], originalPoints[2]);
  36078. vec2.copy(pts[2], originalPoints[1]);
  36079. if (fromSymbol && fromSymbol != 'none') {
  36080. var symbolSize = getSymbolSize(edge.node1);
  36081. var t = intersectCurveCircle(pts, originalPoints[0], symbolSize * scale);
  36082. // Subdivide and get the second
  36083. quadraticSubdivide(pts[0][0], pts[1][0], pts[2][0], t, tmp0);
  36084. pts[0][0] = tmp0[3];
  36085. pts[1][0] = tmp0[4];
  36086. quadraticSubdivide(pts[0][1], pts[1][1], pts[2][1], t, tmp0);
  36087. pts[0][1] = tmp0[3];
  36088. pts[1][1] = tmp0[4];
  36089. }
  36090. if (toSymbol && toSymbol != 'none') {
  36091. var symbolSize = getSymbolSize(edge.node2);
  36092. var t = intersectCurveCircle(pts, originalPoints[1], symbolSize * scale);
  36093. // Subdivide and get the first
  36094. quadraticSubdivide(pts[0][0], pts[1][0], pts[2][0], t, tmp0);
  36095. pts[1][0] = tmp0[1];
  36096. pts[2][0] = tmp0[2];
  36097. quadraticSubdivide(pts[0][1], pts[1][1], pts[2][1], t, tmp0);
  36098. pts[1][1] = tmp0[1];
  36099. pts[2][1] = tmp0[2];
  36100. }
  36101. // Copy back to layout
  36102. vec2.copy(linePoints[0], pts[0]);
  36103. vec2.copy(linePoints[1], pts[2]);
  36104. vec2.copy(linePoints[2], pts[1]);
  36105. }
  36106. // Line
  36107. else {
  36108. vec2.copy(pts2[0], originalPoints[0]);
  36109. vec2.copy(pts2[1], originalPoints[1]);
  36110. vec2.sub(v, pts2[1], pts2[0]);
  36111. vec2.normalize(v, v);
  36112. if (fromSymbol && fromSymbol != 'none') {
  36113. var symbolSize = getSymbolSize(edge.node1);
  36114. vec2.scaleAndAdd(pts2[0], pts2[0], v, symbolSize * scale);
  36115. }
  36116. if (toSymbol && toSymbol != 'none') {
  36117. var symbolSize = getSymbolSize(edge.node2);
  36118. vec2.scaleAndAdd(pts2[1], pts2[1], v, -symbolSize * scale);
  36119. }
  36120. vec2.copy(linePoints[0], pts2[0]);
  36121. vec2.copy(linePoints[1], pts2[1]);
  36122. }
  36123. });
  36124. };
  36125. /***/ },
  36126. /* 213 */
  36127. /***/ function(module, exports, __webpack_require__) {
  36128. var echarts = __webpack_require__(1);
  36129. var roamHelper = __webpack_require__(187);
  36130. var actionInfo = {
  36131. type: 'graphRoam',
  36132. event: 'graphRoam',
  36133. update: 'none'
  36134. };
  36135. /**
  36136. * @payload
  36137. * @property {string} name Series name
  36138. * @property {number} [dx]
  36139. * @property {number} [dy]
  36140. * @property {number} [zoom]
  36141. * @property {number} [originX]
  36142. * @property {number} [originY]
  36143. */
  36144. echarts.registerAction(actionInfo, function (payload, ecModel) {
  36145. ecModel.eachComponent({mainType: 'series', query: payload}, function (seriesModel) {
  36146. var coordSys = seriesModel.coordinateSystem;
  36147. var res = roamHelper.updateCenterAndZoom(coordSys, payload);
  36148. seriesModel.setCenter
  36149. && seriesModel.setCenter(res.center);
  36150. seriesModel.setZoom
  36151. && seriesModel.setZoom(res.zoom);
  36152. });
  36153. });
  36154. /**
  36155. * @payload
  36156. * @property {number} [seriesIndex]
  36157. * @property {string} [seriesId]
  36158. * @property {string} [seriesName]
  36159. * @property {number} [dataIndex]
  36160. */
  36161. echarts.registerAction({
  36162. type: 'focusNodeAdjacency',
  36163. event: 'focusNodeAdjacency',
  36164. update: 'series.graph:focusNodeAdjacency'
  36165. }, function () {});
  36166. /**
  36167. * @payload
  36168. * @property {number} [seriesIndex]
  36169. * @property {string} [seriesId]
  36170. * @property {string} [seriesName]
  36171. */
  36172. echarts.registerAction({
  36173. type: 'unfocusNodeAdjacency',
  36174. event: 'unfocusNodeAdjacency',
  36175. update: 'series.graph:unfocusNodeAdjacency'
  36176. }, function () {});
  36177. /***/ },
  36178. /* 214 */
  36179. /***/ function(module, exports) {
  36180. module.exports = function (ecModel) {
  36181. var legendModels = ecModel.findComponents({
  36182. mainType: 'legend'
  36183. });
  36184. if (!legendModels || !legendModels.length) {
  36185. return;
  36186. }
  36187. ecModel.eachSeriesByType('graph', function (graphSeries) {
  36188. var categoriesData = graphSeries.getCategoriesData();
  36189. var graph = graphSeries.getGraph();
  36190. var data = graph.data;
  36191. var categoryNames = categoriesData.mapArray(categoriesData.getName);
  36192. data.filterSelf(function (idx) {
  36193. var model = data.getItemModel(idx);
  36194. var category = model.getShallow('category');
  36195. if (category != null) {
  36196. if (typeof category === 'number') {
  36197. category = categoryNames[category];
  36198. }
  36199. // If in any legend component the status is not selected.
  36200. for (var i = 0; i < legendModels.length; i++) {
  36201. if (!legendModels[i].isSelected(category)) {
  36202. return false;
  36203. }
  36204. }
  36205. }
  36206. return true;
  36207. });
  36208. }, this);
  36209. };
  36210. /***/ },
  36211. /* 215 */
  36212. /***/ function(module, exports) {
  36213. module.exports = function (ecModel) {
  36214. var paletteScope = {};
  36215. ecModel.eachSeriesByType('graph', function (seriesModel) {
  36216. var categoriesData = seriesModel.getCategoriesData();
  36217. var data = seriesModel.getData();
  36218. var categoryNameIdxMap = {};
  36219. categoriesData.each(function (idx) {
  36220. var name = categoriesData.getName(idx);
  36221. // Add prefix to avoid conflict with Object.prototype.
  36222. categoryNameIdxMap['ec-' + name] = idx;
  36223. var itemModel = categoriesData.getItemModel(idx);
  36224. var color = itemModel.get('itemStyle.normal.color')
  36225. || seriesModel.getColorFromPalette(name, paletteScope);
  36226. categoriesData.setItemVisual(idx, 'color', color);
  36227. });
  36228. // Assign category color to visual
  36229. if (categoriesData.count()) {
  36230. data.each(function (idx) {
  36231. var model = data.getItemModel(idx);
  36232. var category = model.getShallow('category');
  36233. if (category != null) {
  36234. if (typeof category === 'string') {
  36235. category = categoryNameIdxMap['ec-' + category];
  36236. }
  36237. if (!data.getItemVisual(idx, 'color', true)) {
  36238. data.setItemVisual(
  36239. idx, 'color',
  36240. categoriesData.getItemVisual(category, 'color')
  36241. );
  36242. }
  36243. }
  36244. });
  36245. }
  36246. });
  36247. };
  36248. /***/ },
  36249. /* 216 */
  36250. /***/ function(module, exports) {
  36251. function normalize(a) {
  36252. if (!(a instanceof Array)) {
  36253. a = [a, a];
  36254. }
  36255. return a;
  36256. }
  36257. module.exports = function (ecModel) {
  36258. ecModel.eachSeriesByType('graph', function (seriesModel) {
  36259. var graph = seriesModel.getGraph();
  36260. var edgeData = seriesModel.getEdgeData();
  36261. var symbolType = normalize(seriesModel.get('edgeSymbol'));
  36262. var symbolSize = normalize(seriesModel.get('edgeSymbolSize'));
  36263. var colorQuery = 'lineStyle.normal.color'.split('.');
  36264. var opacityQuery = 'lineStyle.normal.opacity'.split('.');
  36265. edgeData.setVisual('fromSymbol', symbolType && symbolType[0]);
  36266. edgeData.setVisual('toSymbol', symbolType && symbolType[1]);
  36267. edgeData.setVisual('fromSymbolSize', symbolSize && symbolSize[0]);
  36268. edgeData.setVisual('toSymbolSize', symbolSize && symbolSize[1]);
  36269. edgeData.setVisual('color', seriesModel.get(colorQuery));
  36270. edgeData.setVisual('opacity', seriesModel.get(opacityQuery));
  36271. edgeData.each(function (idx) {
  36272. var itemModel = edgeData.getItemModel(idx);
  36273. var edge = graph.getEdgeByIndex(idx);
  36274. var symbolType = normalize(itemModel.getShallow('symbol', true));
  36275. var symbolSize = normalize(itemModel.getShallow('symbolSize', true));
  36276. // Edge visual must after node visual
  36277. var color = itemModel.get(colorQuery);
  36278. var opacity = itemModel.get(opacityQuery);
  36279. switch (color) {
  36280. case 'source':
  36281. color = edge.node1.getVisual('color');
  36282. break;
  36283. case 'target':
  36284. color = edge.node2.getVisual('color');
  36285. break;
  36286. }
  36287. symbolType[0] && edge.setVisual('fromSymbol', symbolType[0]);
  36288. symbolType[1] && edge.setVisual('toSymbol', symbolType[1]);
  36289. symbolSize[0] && edge.setVisual('fromSymbolSize', symbolSize[0]);
  36290. symbolSize[1] && edge.setVisual('toSymbolSize', symbolSize[1]);
  36291. edge.setVisual('color', color);
  36292. edge.setVisual('opacity', opacity);
  36293. });
  36294. });
  36295. };
  36296. /***/ },
  36297. /* 217 */
  36298. /***/ function(module, exports, __webpack_require__) {
  36299. var simpleLayoutHelper = __webpack_require__(218);
  36300. var simpleLayoutEdge = __webpack_require__(219);
  36301. module.exports = function (ecModel, api) {
  36302. ecModel.eachSeriesByType('graph', function (seriesModel) {
  36303. var layout = seriesModel.get('layout');
  36304. var coordSys = seriesModel.coordinateSystem;
  36305. if (coordSys && coordSys.type !== 'view') {
  36306. var data = seriesModel.getData();
  36307. var dimensions = coordSys.dimensions;
  36308. data.each(dimensions, function () {
  36309. var hasValue;
  36310. var args = arguments;
  36311. var value = [];
  36312. for (var i = 0; i < dimensions.length; i++) {
  36313. if (!isNaN(args[i])) {
  36314. hasValue = true;
  36315. }
  36316. value.push(args[i]);
  36317. }
  36318. var idx = args[args.length - 1];
  36319. if (hasValue) {
  36320. data.setItemLayout(idx, coordSys.dataToPoint(value));
  36321. }
  36322. else {
  36323. // Also {Array.<number>}, not undefined to avoid if...else... statement
  36324. data.setItemLayout(idx, [NaN, NaN]);
  36325. }
  36326. });
  36327. simpleLayoutEdge(data.graph);
  36328. }
  36329. else if (!layout || layout === 'none') {
  36330. simpleLayoutHelper(seriesModel);
  36331. }
  36332. });
  36333. };
  36334. /***/ },
  36335. /* 218 */
  36336. /***/ function(module, exports, __webpack_require__) {
  36337. var simpleLayoutEdge = __webpack_require__(219);
  36338. module.exports = function (seriesModel) {
  36339. var coordSys = seriesModel.coordinateSystem;
  36340. if (coordSys && coordSys.type !== 'view') {
  36341. return;
  36342. }
  36343. var graph = seriesModel.getGraph();
  36344. graph.eachNode(function (node) {
  36345. var model = node.getModel();
  36346. node.setLayout([+model.get('x'), +model.get('y')]);
  36347. });
  36348. simpleLayoutEdge(graph);
  36349. };
  36350. /***/ },
  36351. /* 219 */
  36352. /***/ function(module, exports, __webpack_require__) {
  36353. var vec2 = __webpack_require__(10);
  36354. module.exports = function (graph) {
  36355. graph.eachEdge(function (edge) {
  36356. var curveness = edge.getModel().get('lineStyle.normal.curveness') || 0;
  36357. var p1 = vec2.clone(edge.node1.getLayout());
  36358. var p2 = vec2.clone(edge.node2.getLayout());
  36359. var points = [p1, p2];
  36360. if (+curveness) {
  36361. points.push([
  36362. (p1[0] + p2[0]) / 2 - (p1[1] - p2[1]) * curveness,
  36363. (p1[1] + p2[1]) / 2 - (p2[0] - p1[0]) * curveness
  36364. ]);
  36365. }
  36366. edge.setLayout(points);
  36367. });
  36368. };
  36369. /***/ },
  36370. /* 220 */
  36371. /***/ function(module, exports, __webpack_require__) {
  36372. var circularLayoutHelper = __webpack_require__(221);
  36373. module.exports = function (ecModel) {
  36374. ecModel.eachSeriesByType('graph', function (seriesModel) {
  36375. if (seriesModel.get('layout') === 'circular') {
  36376. circularLayoutHelper(seriesModel);
  36377. }
  36378. });
  36379. };
  36380. /***/ },
  36381. /* 221 */
  36382. /***/ function(module, exports, __webpack_require__) {
  36383. var vec2 = __webpack_require__(10);
  36384. module.exports = function (seriesModel) {
  36385. var coordSys = seriesModel.coordinateSystem;
  36386. if (coordSys && coordSys.type !== 'view') {
  36387. return;
  36388. }
  36389. var rect = coordSys.getBoundingRect();
  36390. var nodeData = seriesModel.getData();
  36391. var graph = nodeData.graph;
  36392. var angle = 0;
  36393. var sum = nodeData.getSum('value');
  36394. var unitAngle = Math.PI * 2 / (sum || nodeData.count());
  36395. var cx = rect.width / 2 + rect.x;
  36396. var cy = rect.height / 2 + rect.y;
  36397. var r = Math.min(rect.width, rect.height) / 2;
  36398. graph.eachNode(function (node) {
  36399. var value = node.getValue('value');
  36400. angle += unitAngle * (sum ? value : 1) / 2;
  36401. node.setLayout([
  36402. r * Math.cos(angle) + cx,
  36403. r * Math.sin(angle) + cy
  36404. ]);
  36405. angle += unitAngle * (sum ? value : 1) / 2;
  36406. });
  36407. nodeData.setLayout({
  36408. cx: cx,
  36409. cy: cy
  36410. });
  36411. graph.eachEdge(function (edge) {
  36412. var curveness = edge.getModel().get('lineStyle.normal.curveness') || 0;
  36413. var p1 = vec2.clone(edge.node1.getLayout());
  36414. var p2 = vec2.clone(edge.node2.getLayout());
  36415. var cp1;
  36416. var x12 = (p1[0] + p2[0]) / 2;
  36417. var y12 = (p1[1] + p2[1]) / 2;
  36418. if (+curveness) {
  36419. curveness *= 3;
  36420. cp1 = [
  36421. cx * curveness + x12 * (1 - curveness),
  36422. cy * curveness + y12 * (1 - curveness)
  36423. ];
  36424. }
  36425. edge.setLayout([p1, p2, cp1]);
  36426. });
  36427. };
  36428. /***/ },
  36429. /* 222 */
  36430. /***/ function(module, exports, __webpack_require__) {
  36431. var forceHelper = __webpack_require__(223);
  36432. var numberUtil = __webpack_require__(7);
  36433. var simpleLayoutHelper = __webpack_require__(218);
  36434. var circularLayoutHelper = __webpack_require__(221);
  36435. var vec2 = __webpack_require__(10);
  36436. var zrUtil = __webpack_require__(4);
  36437. module.exports = function (ecModel) {
  36438. ecModel.eachSeriesByType('graph', function (graphSeries) {
  36439. var coordSys = graphSeries.coordinateSystem;
  36440. if (coordSys && coordSys.type !== 'view') {
  36441. return;
  36442. }
  36443. if (graphSeries.get('layout') === 'force') {
  36444. var preservedPoints = graphSeries.preservedPoints || {};
  36445. var graph = graphSeries.getGraph();
  36446. var nodeData = graph.data;
  36447. var edgeData = graph.edgeData;
  36448. var forceModel = graphSeries.getModel('force');
  36449. var initLayout = forceModel.get('initLayout');
  36450. if (graphSeries.preservedPoints) {
  36451. nodeData.each(function (idx) {
  36452. var id = nodeData.getId(idx);
  36453. nodeData.setItemLayout(idx, preservedPoints[id] || [NaN, NaN]);
  36454. });
  36455. }
  36456. else if (!initLayout || initLayout === 'none') {
  36457. simpleLayoutHelper(graphSeries);
  36458. }
  36459. else if (initLayout === 'circular') {
  36460. circularLayoutHelper(graphSeries);
  36461. }
  36462. var nodeDataExtent = nodeData.getDataExtent('value');
  36463. var edgeDataExtent = edgeData.getDataExtent('value');
  36464. // var edgeDataExtent = edgeData.getDataExtent('value');
  36465. var repulsion = forceModel.get('repulsion');
  36466. var edgeLength = forceModel.get('edgeLength');
  36467. if (!zrUtil.isArray(repulsion)) {
  36468. repulsion = [repulsion, repulsion];
  36469. }
  36470. if (!zrUtil.isArray(edgeLength)) {
  36471. edgeLength = [edgeLength, edgeLength];
  36472. }
  36473. // Larger value has smaller length
  36474. edgeLength = [edgeLength[1], edgeLength[0]];
  36475. var nodes = nodeData.mapArray('value', function (value, idx) {
  36476. var point = nodeData.getItemLayout(idx);
  36477. // var w = numberUtil.linearMap(value, nodeDataExtent, [0, 50]);
  36478. var rep = numberUtil.linearMap(value, nodeDataExtent, repulsion);
  36479. if (isNaN(rep)) {
  36480. rep = (repulsion[0] + repulsion[1]) / 2;
  36481. }
  36482. return {
  36483. w: rep,
  36484. rep: rep,
  36485. p: (!point || isNaN(point[0]) || isNaN(point[1])) ? null : point
  36486. };
  36487. });
  36488. var edges = edgeData.mapArray('value', function (value, idx) {
  36489. var edge = graph.getEdgeByIndex(idx);
  36490. var d = numberUtil.linearMap(value, edgeDataExtent, edgeLength);
  36491. if (isNaN(d)) {
  36492. d = (edgeLength[0] + edgeLength[1]) / 2;
  36493. }
  36494. return {
  36495. n1: nodes[edge.node1.dataIndex],
  36496. n2: nodes[edge.node2.dataIndex],
  36497. d: d,
  36498. curveness: edge.getModel().get('lineStyle.normal.curveness') || 0
  36499. };
  36500. });
  36501. var coordSys = graphSeries.coordinateSystem;
  36502. var rect = coordSys.getBoundingRect();
  36503. var forceInstance = forceHelper(nodes, edges, {
  36504. rect: rect,
  36505. gravity: forceModel.get('gravity')
  36506. });
  36507. var oldStep = forceInstance.step;
  36508. forceInstance.step = function (cb) {
  36509. for (var i = 0, l = nodes.length; i < l; i++) {
  36510. if (nodes[i].fixed) {
  36511. // Write back to layout instance
  36512. vec2.copy(nodes[i].p, graph.getNodeByIndex(i).getLayout());
  36513. }
  36514. }
  36515. oldStep(function (nodes, edges, stopped) {
  36516. for (var i = 0, l = nodes.length; i < l; i++) {
  36517. if (!nodes[i].fixed) {
  36518. graph.getNodeByIndex(i).setLayout(nodes[i].p);
  36519. }
  36520. preservedPoints[nodeData.getId(i)] = nodes[i].p;
  36521. }
  36522. for (var i = 0, l = edges.length; i < l; i++) {
  36523. var e = edges[i];
  36524. var edge = graph.getEdgeByIndex(i);
  36525. var p1 = e.n1.p;
  36526. var p2 = e.n2.p;
  36527. var points = edge.getLayout();
  36528. points = points ? points.slice() : [];
  36529. points[0] = points[0] || [];
  36530. points[1] = points[1] || [];
  36531. vec2.copy(points[0], p1);
  36532. vec2.copy(points[1], p2);
  36533. if (+e.curveness) {
  36534. points[2] = [
  36535. (p1[0] + p2[0]) / 2 - (p1[1] - p2[1]) * e.curveness,
  36536. (p1[1] + p2[1]) / 2 - (p2[0] - p1[0]) * e.curveness
  36537. ];
  36538. }
  36539. edge.setLayout(points);
  36540. }
  36541. // Update layout
  36542. cb && cb(stopped);
  36543. });
  36544. };
  36545. graphSeries.forceLayout = forceInstance;
  36546. graphSeries.preservedPoints = preservedPoints;
  36547. // Step to get the layout
  36548. forceInstance.step();
  36549. }
  36550. else {
  36551. // Remove prev injected forceLayout instance
  36552. graphSeries.forceLayout = null;
  36553. }
  36554. });
  36555. };
  36556. /***/ },
  36557. /* 223 */
  36558. /***/ function(module, exports, __webpack_require__) {
  36559. var vec2 = __webpack_require__(10);
  36560. var scaleAndAdd = vec2.scaleAndAdd;
  36561. // function adjacentNode(n, e) {
  36562. // return e.n1 === n ? e.n2 : e.n1;
  36563. // }
  36564. module.exports = function (nodes, edges, opts) {
  36565. var rect = opts.rect;
  36566. var width = rect.width;
  36567. var height = rect.height;
  36568. var center = [rect.x + width / 2, rect.y + height / 2];
  36569. // var scale = opts.scale || 1;
  36570. var gravity = opts.gravity == null ? 0.1 : opts.gravity;
  36571. // for (var i = 0; i < edges.length; i++) {
  36572. // var e = edges[i];
  36573. // var n1 = e.n1;
  36574. // var n2 = e.n2;
  36575. // n1.edges = n1.edges || [];
  36576. // n2.edges = n2.edges || [];
  36577. // n1.edges.push(e);
  36578. // n2.edges.push(e);
  36579. // }
  36580. // Init position
  36581. for (var i = 0; i < nodes.length; i++) {
  36582. var n = nodes[i];
  36583. if (!n.p) {
  36584. // Use the position from first adjecent node with defined position
  36585. // Or use a random position
  36586. // From d3
  36587. // if (n.edges) {
  36588. // var j = -1;
  36589. // while (++j < n.edges.length) {
  36590. // var e = n.edges[j];
  36591. // var other = adjacentNode(n, e);
  36592. // if (other.p) {
  36593. // n.p = vec2.clone(other.p);
  36594. // break;
  36595. // }
  36596. // }
  36597. // }
  36598. // if (!n.p) {
  36599. n.p = vec2.create(
  36600. width * (Math.random() - 0.5) + center[0],
  36601. height * (Math.random() - 0.5) + center[1]
  36602. );
  36603. // }
  36604. }
  36605. n.pp = vec2.clone(n.p);
  36606. n.edges = null;
  36607. }
  36608. // Formula in 'Graph Drawing by Force-directed Placement'
  36609. // var k = scale * Math.sqrt(width * height / nodes.length);
  36610. // var k2 = k * k;
  36611. var friction = 0.6;
  36612. return {
  36613. warmUp: function () {
  36614. friction = 0.5;
  36615. },
  36616. setFixed: function (idx) {
  36617. nodes[idx].fixed = true;
  36618. },
  36619. setUnfixed: function (idx) {
  36620. nodes[idx].fixed = false;
  36621. },
  36622. step: function (cb) {
  36623. var v12 = [];
  36624. var nLen = nodes.length;
  36625. for (var i = 0; i < edges.length; i++) {
  36626. var e = edges[i];
  36627. var n1 = e.n1;
  36628. var n2 = e.n2;
  36629. vec2.sub(v12, n2.p, n1.p);
  36630. var d = vec2.len(v12) - e.d;
  36631. var w = n2.w / (n1.w + n2.w);
  36632. vec2.normalize(v12, v12);
  36633. !n1.fixed && scaleAndAdd(n1.p, n1.p, v12, w * d * friction);
  36634. !n2.fixed && scaleAndAdd(n2.p, n2.p, v12, -(1 - w) * d * friction);
  36635. }
  36636. // Gravity
  36637. for (var i = 0; i < nLen; i++) {
  36638. var n = nodes[i];
  36639. if (!n.fixed) {
  36640. vec2.sub(v12, center, n.p);
  36641. // var d = vec2.len(v12);
  36642. // vec2.scale(v12, v12, 1 / d);
  36643. // var gravityFactor = gravity;
  36644. vec2.scaleAndAdd(n.p, n.p, v12, gravity * friction);
  36645. }
  36646. }
  36647. // Repulsive
  36648. // PENDING
  36649. for (var i = 0; i < nLen; i++) {
  36650. var n1 = nodes[i];
  36651. for (var j = i + 1; j < nLen; j++) {
  36652. var n2 = nodes[j];
  36653. vec2.sub(v12, n2.p, n1.p);
  36654. var d = vec2.len(v12);
  36655. if (d === 0) {
  36656. // Random repulse
  36657. vec2.set(v12, Math.random() - 0.5, Math.random() - 0.5);
  36658. d = 1;
  36659. }
  36660. var repFact = (n1.rep + n2.rep) / d / d;
  36661. !n1.fixed && scaleAndAdd(n1.pp, n1.pp, v12, repFact);
  36662. !n2.fixed && scaleAndAdd(n2.pp, n2.pp, v12, -repFact);
  36663. }
  36664. }
  36665. var v = [];
  36666. for (var i = 0; i < nLen; i++) {
  36667. var n = nodes[i];
  36668. if (!n.fixed) {
  36669. vec2.sub(v, n.p, n.pp);
  36670. vec2.scaleAndAdd(n.p, n.p, v, friction);
  36671. vec2.copy(n.pp, n.p);
  36672. }
  36673. }
  36674. friction = friction * 0.992;
  36675. cb && cb(nodes, edges, friction < 0.01);
  36676. }
  36677. };
  36678. };
  36679. /***/ },
  36680. /* 224 */
  36681. /***/ function(module, exports, __webpack_require__) {
  36682. // FIXME Where to create the simple view coordinate system
  36683. var View = __webpack_require__(176);
  36684. var layout = __webpack_require__(71);
  36685. var bbox = __webpack_require__(38);
  36686. function getViewRect(seriesModel, api, aspect) {
  36687. var option = seriesModel.getBoxLayoutParams();
  36688. option.aspect = aspect;
  36689. return layout.getLayoutRect(option, {
  36690. width: api.getWidth(),
  36691. height: api.getHeight()
  36692. });
  36693. }
  36694. module.exports = function (ecModel, api) {
  36695. var viewList = [];
  36696. ecModel.eachSeriesByType('graph', function (seriesModel) {
  36697. var coordSysType = seriesModel.get('coordinateSystem');
  36698. if (!coordSysType || coordSysType === 'view') {
  36699. var data = seriesModel.getData();
  36700. var positions = data.mapArray(function (idx) {
  36701. var itemModel = data.getItemModel(idx);
  36702. return [+itemModel.get('x'), +itemModel.get('y')];
  36703. });
  36704. var min = [];
  36705. var max = [];
  36706. bbox.fromPoints(positions, min, max);
  36707. // If width or height is 0
  36708. if (max[0] - min[0] === 0) {
  36709. max[0] += 1;
  36710. min[0] -= 1;
  36711. }
  36712. if (max[1] - min[1] === 0) {
  36713. max[1] += 1;
  36714. min[1] -= 1;
  36715. }
  36716. var aspect = (max[0] - min[0]) / (max[1] - min[1]);
  36717. // FIXME If get view rect after data processed?
  36718. var viewRect = getViewRect(seriesModel, api, aspect);
  36719. // Position may be NaN, use view rect instead
  36720. if (isNaN(aspect)) {
  36721. min = [viewRect.x, viewRect.y];
  36722. max = [viewRect.x + viewRect.width, viewRect.y + viewRect.height];
  36723. }
  36724. var bbWidth = max[0] - min[0];
  36725. var bbHeight = max[1] - min[1];
  36726. var viewWidth = viewRect.width;
  36727. var viewHeight = viewRect.height;
  36728. var viewCoordSys = seriesModel.coordinateSystem = new View();
  36729. viewCoordSys.zoomLimit = seriesModel.get('scaleLimit');
  36730. viewCoordSys.setBoundingRect(
  36731. min[0], min[1], bbWidth, bbHeight
  36732. );
  36733. viewCoordSys.setViewRect(
  36734. viewRect.x, viewRect.y, viewWidth, viewHeight
  36735. );
  36736. // Update roam info
  36737. viewCoordSys.setCenter(seriesModel.get('center'));
  36738. viewCoordSys.setZoom(seriesModel.get('zoom'));
  36739. viewList.push(viewCoordSys);
  36740. }
  36741. });
  36742. return viewList;
  36743. };
  36744. /***/ },
  36745. /* 225 */
  36746. /***/ function(module, exports, __webpack_require__) {
  36747. __webpack_require__(226);
  36748. __webpack_require__(227);
  36749. /***/ },
  36750. /* 226 */
  36751. /***/ function(module, exports, __webpack_require__) {
  36752. var List = __webpack_require__(98);
  36753. var SeriesModel = __webpack_require__(78);
  36754. var zrUtil = __webpack_require__(4);
  36755. var GaugeSeries = SeriesModel.extend({
  36756. type: 'series.gauge',
  36757. getInitialData: function (option, ecModel) {
  36758. var list = new List(['value'], this);
  36759. var dataOpt = option.data || [];
  36760. if (!zrUtil.isArray(dataOpt)) {
  36761. dataOpt = [dataOpt];
  36762. }
  36763. // Only use the first data item
  36764. list.initData(dataOpt);
  36765. return list;
  36766. },
  36767. defaultOption: {
  36768. zlevel: 0,
  36769. z: 2,
  36770. // 默认全局居中
  36771. center: ['50%', '50%'],
  36772. legendHoverLink: true,
  36773. radius: '75%',
  36774. startAngle: 225,
  36775. endAngle: -45,
  36776. clockwise: true,
  36777. // 最小值
  36778. min: 0,
  36779. // 最大值
  36780. max: 100,
  36781. // 分割段数,默认为10
  36782. splitNumber: 10,
  36783. // 坐标轴线
  36784. axisLine: {
  36785. // 默认显示,属性show控制显示与否
  36786. show: true,
  36787. lineStyle: { // 属性lineStyle控制线条样式
  36788. color: [[0.2, '#91c7ae'], [0.8, '#63869e'], [1, '#c23531']],
  36789. width: 30
  36790. }
  36791. },
  36792. // 分隔线
  36793. splitLine: {
  36794. // 默认显示,属性show控制显示与否
  36795. show: true,
  36796. // 属性length控制线长
  36797. length: 30,
  36798. // 属性lineStyle(详见lineStyle)控制线条样式
  36799. lineStyle: {
  36800. color: '#eee',
  36801. width: 2,
  36802. type: 'solid'
  36803. }
  36804. },
  36805. // 坐标轴小标记
  36806. axisTick: {
  36807. // 属性show控制显示与否,默认不显示
  36808. show: true,
  36809. // 每份split细分多少段
  36810. splitNumber: 5,
  36811. // 属性length控制线长
  36812. length: 8,
  36813. // 属性lineStyle控制线条样式
  36814. lineStyle: {
  36815. color: '#eee',
  36816. width: 1,
  36817. type: 'solid'
  36818. }
  36819. },
  36820. axisLabel: {
  36821. show: true,
  36822. distance: 5,
  36823. // formatter: null,
  36824. textStyle: { // 其余属性默认使用全局文本样式,详见TEXTSTYLE
  36825. color: 'auto'
  36826. }
  36827. },
  36828. pointer: {
  36829. show: true,
  36830. length: '80%',
  36831. width: 8
  36832. },
  36833. itemStyle: {
  36834. normal: {
  36835. color: 'auto'
  36836. }
  36837. },
  36838. title: {
  36839. show: true,
  36840. // x, y,单位px
  36841. offsetCenter: [0, '-40%'],
  36842. // 其余属性默认使用全局文本样式,详见TEXTSTYLE
  36843. textStyle: {
  36844. color: '#333',
  36845. fontSize: 15
  36846. }
  36847. },
  36848. detail: {
  36849. show: true,
  36850. backgroundColor: 'rgba(0,0,0,0)',
  36851. borderWidth: 0,
  36852. borderColor: '#ccc',
  36853. width: 100,
  36854. height: 40,
  36855. // x, y,单位px
  36856. offsetCenter: [0, '40%'],
  36857. // formatter: null,
  36858. // 其余属性默认使用全局文本样式,详见TEXTSTYLE
  36859. textStyle: {
  36860. color: 'auto',
  36861. fontSize: 30
  36862. }
  36863. }
  36864. }
  36865. });
  36866. module.exports = GaugeSeries;
  36867. /***/ },
  36868. /* 227 */
  36869. /***/ function(module, exports, __webpack_require__) {
  36870. var PointerPath = __webpack_require__(228);
  36871. var graphic = __webpack_require__(18);
  36872. var numberUtil = __webpack_require__(7);
  36873. var parsePercent = numberUtil.parsePercent;
  36874. function parsePosition(seriesModel, api) {
  36875. var center = seriesModel.get('center');
  36876. var width = api.getWidth();
  36877. var height = api.getHeight();
  36878. var size = Math.min(width, height);
  36879. var cx = parsePercent(center[0], api.getWidth());
  36880. var cy = parsePercent(center[1], api.getHeight());
  36881. var r = parsePercent(seriesModel.get('radius'), size / 2);
  36882. return {
  36883. cx: cx,
  36884. cy: cy,
  36885. r: r
  36886. };
  36887. }
  36888. function formatLabel(label, labelFormatter) {
  36889. if (labelFormatter) {
  36890. if (typeof labelFormatter === 'string') {
  36891. label = labelFormatter.replace('{value}', label != null ? label : '');
  36892. }
  36893. else if (typeof labelFormatter === 'function') {
  36894. label = labelFormatter(label);
  36895. }
  36896. }
  36897. return label;
  36898. }
  36899. var PI2 = Math.PI * 2;
  36900. var GaugeView = __webpack_require__(80).extend({
  36901. type: 'gauge',
  36902. render: function (seriesModel, ecModel, api) {
  36903. this.group.removeAll();
  36904. var colorList = seriesModel.get('axisLine.lineStyle.color');
  36905. var posInfo = parsePosition(seriesModel, api);
  36906. this._renderMain(
  36907. seriesModel, ecModel, api, colorList, posInfo
  36908. );
  36909. },
  36910. dispose: function () {},
  36911. _renderMain: function (seriesModel, ecModel, api, colorList, posInfo) {
  36912. var group = this.group;
  36913. var axisLineModel = seriesModel.getModel('axisLine');
  36914. var lineStyleModel = axisLineModel.getModel('lineStyle');
  36915. var clockwise = seriesModel.get('clockwise');
  36916. var startAngle = -seriesModel.get('startAngle') / 180 * Math.PI;
  36917. var endAngle = -seriesModel.get('endAngle') / 180 * Math.PI;
  36918. var angleRangeSpan = (endAngle - startAngle) % PI2;
  36919. var prevEndAngle = startAngle;
  36920. var axisLineWidth = lineStyleModel.get('width');
  36921. for (var i = 0; i < colorList.length; i++) {
  36922. // Clamp
  36923. var percent = Math.min(Math.max(colorList[i][0], 0), 1);
  36924. var endAngle = startAngle + angleRangeSpan * percent;
  36925. var sector = new graphic.Sector({
  36926. shape: {
  36927. startAngle: prevEndAngle,
  36928. endAngle: endAngle,
  36929. cx: posInfo.cx,
  36930. cy: posInfo.cy,
  36931. clockwise: clockwise,
  36932. r0: posInfo.r - axisLineWidth,
  36933. r: posInfo.r
  36934. },
  36935. silent: true
  36936. });
  36937. sector.setStyle({
  36938. fill: colorList[i][1]
  36939. });
  36940. sector.setStyle(lineStyleModel.getLineStyle(
  36941. // Because we use sector to simulate arc
  36942. // so the properties for stroking are useless
  36943. ['color', 'borderWidth', 'borderColor']
  36944. ));
  36945. group.add(sector);
  36946. prevEndAngle = endAngle;
  36947. }
  36948. var getColor = function (percent) {
  36949. // Less than 0
  36950. if (percent <= 0) {
  36951. return colorList[0][1];
  36952. }
  36953. for (var i = 0; i < colorList.length; i++) {
  36954. if (colorList[i][0] >= percent
  36955. && (i === 0 ? 0 : colorList[i - 1][0]) < percent
  36956. ) {
  36957. return colorList[i][1];
  36958. }
  36959. }
  36960. // More than 1
  36961. return colorList[i - 1][1];
  36962. };
  36963. if (!clockwise) {
  36964. var tmp = startAngle;
  36965. startAngle = endAngle;
  36966. endAngle = tmp;
  36967. }
  36968. this._renderTicks(
  36969. seriesModel, ecModel, api, getColor, posInfo,
  36970. startAngle, endAngle, clockwise
  36971. );
  36972. this._renderPointer(
  36973. seriesModel, ecModel, api, getColor, posInfo,
  36974. startAngle, endAngle, clockwise
  36975. );
  36976. this._renderTitle(
  36977. seriesModel, ecModel, api, getColor, posInfo
  36978. );
  36979. this._renderDetail(
  36980. seriesModel, ecModel, api, getColor, posInfo
  36981. );
  36982. },
  36983. _renderTicks: function (
  36984. seriesModel, ecModel, api, getColor, posInfo,
  36985. startAngle, endAngle, clockwise
  36986. ) {
  36987. var group = this.group;
  36988. var cx = posInfo.cx;
  36989. var cy = posInfo.cy;
  36990. var r = posInfo.r;
  36991. var minVal = +seriesModel.get('min');
  36992. var maxVal = +seriesModel.get('max');
  36993. var splitLineModel = seriesModel.getModel('splitLine');
  36994. var tickModel = seriesModel.getModel('axisTick');
  36995. var labelModel = seriesModel.getModel('axisLabel');
  36996. var splitNumber = seriesModel.get('splitNumber');
  36997. var subSplitNumber = tickModel.get('splitNumber');
  36998. var splitLineLen = parsePercent(
  36999. splitLineModel.get('length'), r
  37000. );
  37001. var tickLen = parsePercent(
  37002. tickModel.get('length'), r
  37003. );
  37004. var angle = startAngle;
  37005. var step = (endAngle - startAngle) / splitNumber;
  37006. var subStep = step / subSplitNumber;
  37007. var splitLineStyle = splitLineModel.getModel('lineStyle').getLineStyle();
  37008. var tickLineStyle = tickModel.getModel('lineStyle').getLineStyle();
  37009. var textStyleModel = labelModel.getModel('textStyle');
  37010. for (var i = 0; i <= splitNumber; i++) {
  37011. var unitX = Math.cos(angle);
  37012. var unitY = Math.sin(angle);
  37013. // Split line
  37014. if (splitLineModel.get('show')) {
  37015. var splitLine = new graphic.Line({
  37016. shape: {
  37017. x1: unitX * r + cx,
  37018. y1: unitY * r + cy,
  37019. x2: unitX * (r - splitLineLen) + cx,
  37020. y2: unitY * (r - splitLineLen) + cy
  37021. },
  37022. style: splitLineStyle,
  37023. silent: true
  37024. });
  37025. if (splitLineStyle.stroke === 'auto') {
  37026. splitLine.setStyle({
  37027. stroke: getColor(i / splitNumber)
  37028. });
  37029. }
  37030. group.add(splitLine);
  37031. }
  37032. // Label
  37033. if (labelModel.get('show')) {
  37034. var label = formatLabel(
  37035. numberUtil.round(i / splitNumber * (maxVal - minVal) + minVal),
  37036. labelModel.get('formatter')
  37037. );
  37038. var distance = labelModel.get('distance');
  37039. var text = new graphic.Text({
  37040. style: {
  37041. text: label,
  37042. x: unitX * (r - splitLineLen - distance) + cx,
  37043. y: unitY * (r - splitLineLen - distance) + cy,
  37044. fill: textStyleModel.getTextColor(),
  37045. textFont: textStyleModel.getFont(),
  37046. textVerticalAlign: unitY < -0.4 ? 'top' : (unitY > 0.4 ? 'bottom' : 'middle'),
  37047. textAlign: unitX < -0.4 ? 'left' : (unitX > 0.4 ? 'right' : 'center')
  37048. },
  37049. silent: true
  37050. });
  37051. if (text.style.fill === 'auto') {
  37052. text.setStyle({
  37053. fill: getColor(i / splitNumber)
  37054. });
  37055. }
  37056. group.add(text);
  37057. }
  37058. // Axis tick
  37059. if (tickModel.get('show') && i !== splitNumber) {
  37060. for (var j = 0; j <= subSplitNumber; j++) {
  37061. var unitX = Math.cos(angle);
  37062. var unitY = Math.sin(angle);
  37063. var tickLine = new graphic.Line({
  37064. shape: {
  37065. x1: unitX * r + cx,
  37066. y1: unitY * r + cy,
  37067. x2: unitX * (r - tickLen) + cx,
  37068. y2: unitY * (r - tickLen) + cy
  37069. },
  37070. silent: true,
  37071. style: tickLineStyle
  37072. });
  37073. if (tickLineStyle.stroke === 'auto') {
  37074. tickLine.setStyle({
  37075. stroke: getColor((i + j / subSplitNumber) / splitNumber)
  37076. });
  37077. }
  37078. group.add(tickLine);
  37079. angle += subStep;
  37080. }
  37081. angle -= subStep;
  37082. }
  37083. else {
  37084. angle += step;
  37085. }
  37086. }
  37087. },
  37088. _renderPointer: function (
  37089. seriesModel, ecModel, api, getColor, posInfo,
  37090. startAngle, endAngle, clockwise
  37091. ) {
  37092. var group = this.group;
  37093. var oldData = this._data;
  37094. if (!seriesModel.get('pointer.show')) {
  37095. // Remove old element
  37096. oldData && oldData.eachItemGraphicEl(function (el) {
  37097. group.remove(el);
  37098. });
  37099. return;
  37100. }
  37101. var valueExtent = [+seriesModel.get('min'), +seriesModel.get('max')];
  37102. var angleExtent = [startAngle, endAngle];
  37103. var data = seriesModel.getData();
  37104. data.diff(oldData)
  37105. .add(function (idx) {
  37106. var pointer = new PointerPath({
  37107. shape: {
  37108. angle: startAngle
  37109. }
  37110. });
  37111. graphic.initProps(pointer, {
  37112. shape: {
  37113. angle: numberUtil.linearMap(data.get('value', idx), valueExtent, angleExtent, true)
  37114. }
  37115. }, seriesModel);
  37116. group.add(pointer);
  37117. data.setItemGraphicEl(idx, pointer);
  37118. })
  37119. .update(function (newIdx, oldIdx) {
  37120. var pointer = oldData.getItemGraphicEl(oldIdx);
  37121. graphic.updateProps(pointer, {
  37122. shape: {
  37123. angle: numberUtil.linearMap(data.get('value', newIdx), valueExtent, angleExtent, true)
  37124. }
  37125. }, seriesModel);
  37126. group.add(pointer);
  37127. data.setItemGraphicEl(newIdx, pointer);
  37128. })
  37129. .remove(function (idx) {
  37130. var pointer = oldData.getItemGraphicEl(idx);
  37131. group.remove(pointer);
  37132. })
  37133. .execute();
  37134. data.eachItemGraphicEl(function (pointer, idx) {
  37135. var itemModel = data.getItemModel(idx);
  37136. var pointerModel = itemModel.getModel('pointer');
  37137. pointer.setShape({
  37138. x: posInfo.cx,
  37139. y: posInfo.cy,
  37140. width: parsePercent(
  37141. pointerModel.get('width'), posInfo.r
  37142. ),
  37143. r: parsePercent(pointerModel.get('length'), posInfo.r)
  37144. });
  37145. pointer.useStyle(itemModel.getModel('itemStyle.normal').getItemStyle());
  37146. if (pointer.style.fill === 'auto') {
  37147. pointer.setStyle('fill', getColor(
  37148. numberUtil.linearMap(data.get('value', idx), valueExtent, [0, 1], true)
  37149. ));
  37150. }
  37151. graphic.setHoverStyle(
  37152. pointer, itemModel.getModel('itemStyle.emphasis').getItemStyle()
  37153. );
  37154. });
  37155. this._data = data;
  37156. },
  37157. _renderTitle: function (
  37158. seriesModel, ecModel, api, getColor, posInfo
  37159. ) {
  37160. var titleModel = seriesModel.getModel('title');
  37161. if (titleModel.get('show')) {
  37162. var textStyleModel = titleModel.getModel('textStyle');
  37163. var offsetCenter = titleModel.get('offsetCenter');
  37164. var x = posInfo.cx + parsePercent(offsetCenter[0], posInfo.r);
  37165. var y = posInfo.cy + parsePercent(offsetCenter[1], posInfo.r);
  37166. var text = new graphic.Text({
  37167. style: {
  37168. x: x,
  37169. y: y,
  37170. // FIXME First data name ?
  37171. text: seriesModel.getData().getName(0),
  37172. fill: textStyleModel.getTextColor(),
  37173. textFont: textStyleModel.getFont(),
  37174. textAlign: 'center',
  37175. textVerticalAlign: 'middle'
  37176. }
  37177. });
  37178. if (text.style.fill === 'auto') {
  37179. var minVal = +seriesModel.get('min');
  37180. var maxVal = +seriesModel.get('max');
  37181. var value = seriesModel.getData().get('value', 0);
  37182. text.setStyle('fill', getColor(
  37183. numberUtil.linearMap(value, [minVal, maxVal], [0, 1], true)
  37184. ));
  37185. }
  37186. this.group.add(text);
  37187. }
  37188. },
  37189. _renderDetail: function (
  37190. seriesModel, ecModel, api, getColor, posInfo
  37191. ) {
  37192. var detailModel = seriesModel.getModel('detail');
  37193. var minVal = +seriesModel.get('min');
  37194. var maxVal = +seriesModel.get('max');
  37195. if (detailModel.get('show')) {
  37196. var textStyleModel = detailModel.getModel('textStyle');
  37197. var offsetCenter = detailModel.get('offsetCenter');
  37198. var x = posInfo.cx + parsePercent(offsetCenter[0], posInfo.r);
  37199. var y = posInfo.cy + parsePercent(offsetCenter[1], posInfo.r);
  37200. var width = parsePercent(detailModel.get('width'), posInfo.r);
  37201. var height = parsePercent(detailModel.get('height'), posInfo.r);
  37202. var value = seriesModel.getData().get('value', 0);
  37203. var rect = new graphic.Rect({
  37204. shape: {
  37205. x: x - width / 2,
  37206. y: y - height / 2,
  37207. width: width,
  37208. height: height
  37209. },
  37210. style: {
  37211. text: formatLabel(
  37212. // FIXME First data name ?
  37213. value, detailModel.get('formatter')
  37214. ),
  37215. fill: detailModel.get('backgroundColor'),
  37216. textFill: textStyleModel.getTextColor(),
  37217. textFont: textStyleModel.getFont()
  37218. }
  37219. });
  37220. if (rect.style.textFill === 'auto') {
  37221. rect.setStyle('textFill', getColor(
  37222. numberUtil.linearMap(value, [minVal, maxVal], [0, 1], true)
  37223. ));
  37224. }
  37225. rect.setStyle(detailModel.getItemStyle(['color']));
  37226. this.group.add(rect);
  37227. }
  37228. }
  37229. });
  37230. module.exports = GaugeView;
  37231. /***/ },
  37232. /* 228 */
  37233. /***/ function(module, exports, __webpack_require__) {
  37234. module.exports = __webpack_require__(20).extend({
  37235. type: 'echartsGaugePointer',
  37236. shape: {
  37237. angle: 0,
  37238. width: 10,
  37239. r: 10,
  37240. x: 0,
  37241. y: 0
  37242. },
  37243. buildPath: function (ctx, shape) {
  37244. var mathCos = Math.cos;
  37245. var mathSin = Math.sin;
  37246. var r = shape.r;
  37247. var width = shape.width;
  37248. var angle = shape.angle;
  37249. var x = shape.x - mathCos(angle) * width * (width >= r / 3 ? 1 : 2);
  37250. var y = shape.y - mathSin(angle) * width * (width >= r / 3 ? 1 : 2);
  37251. angle = shape.angle - Math.PI / 2;
  37252. ctx.moveTo(x, y);
  37253. ctx.lineTo(
  37254. shape.x + mathCos(angle) * width,
  37255. shape.y + mathSin(angle) * width
  37256. );
  37257. ctx.lineTo(
  37258. shape.x + mathCos(shape.angle) * r,
  37259. shape.y + mathSin(shape.angle) * r
  37260. );
  37261. ctx.lineTo(
  37262. shape.x - mathCos(angle) * width,
  37263. shape.y - mathSin(angle) * width
  37264. );
  37265. ctx.lineTo(x, y);
  37266. return;
  37267. }
  37268. });
  37269. /***/ },
  37270. /* 229 */
  37271. /***/ function(module, exports, __webpack_require__) {
  37272. var zrUtil = __webpack_require__(4);
  37273. var echarts = __webpack_require__(1);
  37274. __webpack_require__(230);
  37275. __webpack_require__(231);
  37276. echarts.registerVisual(zrUtil.curry(__webpack_require__(151), 'funnel'));
  37277. echarts.registerLayout(__webpack_require__(232));
  37278. echarts.registerProcessor(zrUtil.curry(__webpack_require__(154), 'funnel'));
  37279. /***/ },
  37280. /* 230 */
  37281. /***/ function(module, exports, __webpack_require__) {
  37282. 'use strict';
  37283. var List = __webpack_require__(98);
  37284. var modelUtil = __webpack_require__(5);
  37285. var completeDimensions = __webpack_require__(110);
  37286. var FunnelSeries = __webpack_require__(1).extendSeriesModel({
  37287. type: 'series.funnel',
  37288. init: function (option) {
  37289. FunnelSeries.superApply(this, 'init', arguments);
  37290. // Enable legend selection for each data item
  37291. // Use a function instead of direct access because data reference may changed
  37292. this.legendDataProvider = function () {
  37293. return this.getRawData();
  37294. };
  37295. // Extend labelLine emphasis
  37296. this._defaultLabelLine(option);
  37297. },
  37298. getInitialData: function (option, ecModel) {
  37299. var dimensions = completeDimensions(['value'], option.data);
  37300. var list = new List(dimensions, this);
  37301. list.initData(option.data);
  37302. return list;
  37303. },
  37304. _defaultLabelLine: function (option) {
  37305. // Extend labelLine emphasis
  37306. modelUtil.defaultEmphasis(option.labelLine, ['show']);
  37307. var labelLineNormalOpt = option.labelLine.normal;
  37308. var labelLineEmphasisOpt = option.labelLine.emphasis;
  37309. // Not show label line if `label.normal.show = false`
  37310. labelLineNormalOpt.show = labelLineNormalOpt.show
  37311. && option.label.normal.show;
  37312. labelLineEmphasisOpt.show = labelLineEmphasisOpt.show
  37313. && option.label.emphasis.show;
  37314. },
  37315. // Overwrite
  37316. getDataParams: function (dataIndex) {
  37317. var data = this.getData();
  37318. var params = FunnelSeries.superCall(this, 'getDataParams', dataIndex);
  37319. var sum = data.getSum('value');
  37320. // Percent is 0 if sum is 0
  37321. params.percent = !sum ? 0 : +(data.get('value', dataIndex) / sum * 100).toFixed(2);
  37322. params.$vars.push('percent');
  37323. return params;
  37324. },
  37325. defaultOption: {
  37326. zlevel: 0, // 一级层叠
  37327. z: 2, // 二级层叠
  37328. legendHoverLink: true,
  37329. left: 80,
  37330. top: 60,
  37331. right: 80,
  37332. bottom: 60,
  37333. // width: {totalWidth} - left - right,
  37334. // height: {totalHeight} - top - bottom,
  37335. // 默认取数据最小最大值
  37336. // min: 0,
  37337. // max: 100,
  37338. minSize: '0%',
  37339. maxSize: '100%',
  37340. sort: 'descending', // 'ascending', 'descending'
  37341. gap: 0,
  37342. funnelAlign: 'center',
  37343. label: {
  37344. normal: {
  37345. show: true,
  37346. position: 'outer'
  37347. // formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调
  37348. // textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
  37349. },
  37350. emphasis: {
  37351. show: true
  37352. }
  37353. },
  37354. labelLine: {
  37355. normal: {
  37356. show: true,
  37357. length: 20,
  37358. lineStyle: {
  37359. // color: 各异,
  37360. width: 1,
  37361. type: 'solid'
  37362. }
  37363. },
  37364. emphasis: {}
  37365. },
  37366. itemStyle: {
  37367. normal: {
  37368. // color: 各异,
  37369. borderColor: '#fff',
  37370. borderWidth: 1
  37371. },
  37372. emphasis: {
  37373. // color: 各异,
  37374. }
  37375. }
  37376. }
  37377. });
  37378. module.exports = FunnelSeries;
  37379. /***/ },
  37380. /* 231 */
  37381. /***/ function(module, exports, __webpack_require__) {
  37382. var graphic = __webpack_require__(18);
  37383. var zrUtil = __webpack_require__(4);
  37384. /**
  37385. * Piece of pie including Sector, Label, LabelLine
  37386. * @constructor
  37387. * @extends {module:zrender/graphic/Group}
  37388. */
  37389. function FunnelPiece(data, idx) {
  37390. graphic.Group.call(this);
  37391. var polygon = new graphic.Polygon();
  37392. var labelLine = new graphic.Polyline();
  37393. var text = new graphic.Text();
  37394. this.add(polygon);
  37395. this.add(labelLine);
  37396. this.add(text);
  37397. this.updateData(data, idx, true);
  37398. // Hover to change label and labelLine
  37399. function onEmphasis() {
  37400. labelLine.ignore = labelLine.hoverIgnore;
  37401. text.ignore = text.hoverIgnore;
  37402. }
  37403. function onNormal() {
  37404. labelLine.ignore = labelLine.normalIgnore;
  37405. text.ignore = text.normalIgnore;
  37406. }
  37407. this.on('emphasis', onEmphasis)
  37408. .on('normal', onNormal)
  37409. .on('mouseover', onEmphasis)
  37410. .on('mouseout', onNormal);
  37411. }
  37412. var funnelPieceProto = FunnelPiece.prototype;
  37413. function getLabelStyle(data, idx, state, labelModel) {
  37414. var textStyleModel = labelModel.getModel('textStyle');
  37415. var position = labelModel.get('position');
  37416. var isLabelInside = position === 'inside' || position === 'inner' || position === 'center';
  37417. return {
  37418. fill: textStyleModel.getTextColor()
  37419. || (isLabelInside ? '#fff' : data.getItemVisual(idx, 'color')),
  37420. textFont: textStyleModel.getFont(),
  37421. text: zrUtil.retrieve(
  37422. data.hostModel.getFormattedLabel(idx, state),
  37423. data.getName(idx)
  37424. )
  37425. };
  37426. }
  37427. var opacityAccessPath = ['itemStyle', 'normal', 'opacity'];
  37428. funnelPieceProto.updateData = function (data, idx, firstCreate) {
  37429. var polygon = this.childAt(0);
  37430. var seriesModel = data.hostModel;
  37431. var itemModel = data.getItemModel(idx);
  37432. var layout = data.getItemLayout(idx);
  37433. var opacity = data.getItemModel(idx).get(opacityAccessPath);
  37434. opacity = opacity == null ? 1 : opacity;
  37435. // Reset style
  37436. polygon.useStyle({});
  37437. if (firstCreate) {
  37438. polygon.setShape({
  37439. points: layout.points
  37440. });
  37441. polygon.setStyle({ opacity : 0 });
  37442. graphic.initProps(polygon, {
  37443. style: {
  37444. opacity: opacity
  37445. }
  37446. }, seriesModel, idx);
  37447. }
  37448. else {
  37449. graphic.updateProps(polygon, {
  37450. style: {
  37451. opacity: opacity
  37452. },
  37453. shape: {
  37454. points: layout.points
  37455. }
  37456. }, seriesModel, idx);
  37457. }
  37458. // Update common style
  37459. var itemStyleModel = itemModel.getModel('itemStyle');
  37460. var visualColor = data.getItemVisual(idx, 'color');
  37461. polygon.setStyle(
  37462. zrUtil.defaults(
  37463. {
  37464. lineJoin: 'round',
  37465. fill: visualColor
  37466. },
  37467. itemStyleModel.getModel('normal').getItemStyle(['opacity'])
  37468. )
  37469. );
  37470. polygon.hoverStyle = itemStyleModel.getModel('emphasis').getItemStyle();
  37471. this._updateLabel(data, idx);
  37472. graphic.setHoverStyle(this);
  37473. };
  37474. funnelPieceProto._updateLabel = function (data, idx) {
  37475. var labelLine = this.childAt(1);
  37476. var labelText = this.childAt(2);
  37477. var seriesModel = data.hostModel;
  37478. var itemModel = data.getItemModel(idx);
  37479. var layout = data.getItemLayout(idx);
  37480. var labelLayout = layout.label;
  37481. var visualColor = data.getItemVisual(idx, 'color');
  37482. graphic.updateProps(labelLine, {
  37483. shape: {
  37484. points: labelLayout.linePoints || labelLayout.linePoints
  37485. }
  37486. }, seriesModel, idx);
  37487. graphic.updateProps(labelText, {
  37488. style: {
  37489. x: labelLayout.x,
  37490. y: labelLayout.y
  37491. }
  37492. }, seriesModel, idx);
  37493. labelText.attr({
  37494. style: {
  37495. textAlign: labelLayout.textAlign,
  37496. textVerticalAlign: labelLayout.verticalAlign,
  37497. textFont: labelLayout.font
  37498. },
  37499. rotation: labelLayout.rotation,
  37500. origin: [labelLayout.x, labelLayout.y],
  37501. z2: 10
  37502. });
  37503. var labelModel = itemModel.getModel('label.normal');
  37504. var labelHoverModel = itemModel.getModel('label.emphasis');
  37505. var labelLineModel = itemModel.getModel('labelLine.normal');
  37506. var labelLineHoverModel = itemModel.getModel('labelLine.emphasis');
  37507. labelText.setStyle(getLabelStyle(data, idx, 'normal', labelModel));
  37508. labelText.ignore = labelText.normalIgnore = !labelModel.get('show');
  37509. labelText.hoverIgnore = !labelHoverModel.get('show');
  37510. labelLine.ignore = labelLine.normalIgnore = !labelLineModel.get('show');
  37511. labelLine.hoverIgnore = !labelLineHoverModel.get('show');
  37512. // Default use item visual color
  37513. labelLine.setStyle({
  37514. stroke: visualColor
  37515. });
  37516. labelLine.setStyle(labelLineModel.getModel('lineStyle').getLineStyle());
  37517. labelText.hoverStyle = getLabelStyle(data, idx, 'emphasis', labelHoverModel);
  37518. labelLine.hoverStyle = labelLineHoverModel.getModel('lineStyle').getLineStyle();
  37519. };
  37520. zrUtil.inherits(FunnelPiece, graphic.Group);
  37521. var Funnel = __webpack_require__(80).extend({
  37522. type: 'funnel',
  37523. render: function (seriesModel, ecModel, api) {
  37524. var data = seriesModel.getData();
  37525. var oldData = this._data;
  37526. var group = this.group;
  37527. data.diff(oldData)
  37528. .add(function (idx) {
  37529. var funnelPiece = new FunnelPiece(data, idx);
  37530. data.setItemGraphicEl(idx, funnelPiece);
  37531. group.add(funnelPiece);
  37532. })
  37533. .update(function (newIdx, oldIdx) {
  37534. var piePiece = oldData.getItemGraphicEl(oldIdx);
  37535. piePiece.updateData(data, newIdx);
  37536. group.add(piePiece);
  37537. data.setItemGraphicEl(newIdx, piePiece);
  37538. })
  37539. .remove(function (idx) {
  37540. var piePiece = oldData.getItemGraphicEl(idx);
  37541. group.remove(piePiece);
  37542. })
  37543. .execute();
  37544. this._data = data;
  37545. },
  37546. remove: function () {
  37547. this.group.removeAll();
  37548. this._data = null;
  37549. },
  37550. dispose: function () {}
  37551. });
  37552. module.exports = Funnel;
  37553. /***/ },
  37554. /* 232 */
  37555. /***/ function(module, exports, __webpack_require__) {
  37556. var layout = __webpack_require__(71);
  37557. var number = __webpack_require__(7);
  37558. var parsePercent = number.parsePercent;
  37559. function getViewRect(seriesModel, api) {
  37560. return layout.getLayoutRect(
  37561. seriesModel.getBoxLayoutParams(), {
  37562. width: api.getWidth(),
  37563. height: api.getHeight()
  37564. }
  37565. );
  37566. }
  37567. function getSortedIndices(data, sort) {
  37568. var valueArr = data.mapArray('value', function (val) {
  37569. return val;
  37570. });
  37571. var indices = [];
  37572. var isAscending = sort === 'ascending';
  37573. for (var i = 0, len = data.count(); i < len; i++) {
  37574. indices[i] = i;
  37575. }
  37576. // Add custom sortable function & none sortable opetion by "options.sort"
  37577. if (typeof sort === 'function') {
  37578. indices.sort(sort);
  37579. } else if (sort !== 'none') {
  37580. indices.sort(function (a, b) {
  37581. return isAscending ? valueArr[a] - valueArr[b] : valueArr[b] - valueArr[a];
  37582. });
  37583. }
  37584. return indices;
  37585. }
  37586. function labelLayout (data) {
  37587. data.each(function (idx) {
  37588. var itemModel = data.getItemModel(idx);
  37589. var labelModel = itemModel.getModel('label.normal');
  37590. var labelPosition = labelModel.get('position');
  37591. var labelLineModel = itemModel.getModel('labelLine.normal');
  37592. var layout = data.getItemLayout(idx);
  37593. var points = layout.points;
  37594. var isLabelInside = labelPosition === 'inner'
  37595. || labelPosition === 'inside' || labelPosition === 'center';
  37596. var textAlign;
  37597. var textX;
  37598. var textY;
  37599. var linePoints;
  37600. if (isLabelInside) {
  37601. textX = (points[0][0] + points[1][0] + points[2][0] + points[3][0]) / 4;
  37602. textY = (points[0][1] + points[1][1] + points[2][1] + points[3][1]) / 4;
  37603. textAlign = 'center';
  37604. linePoints = [
  37605. [textX, textY], [textX, textY]
  37606. ];
  37607. }
  37608. else {
  37609. var x1;
  37610. var y1;
  37611. var x2;
  37612. var labelLineLen = labelLineModel.get('length');
  37613. if (labelPosition === 'left') {
  37614. // Left side
  37615. x1 = (points[3][0] + points[0][0]) / 2;
  37616. y1 = (points[3][1] + points[0][1]) / 2;
  37617. x2 = x1 - labelLineLen;
  37618. textX = x2 - 5;
  37619. textAlign = 'right';
  37620. }
  37621. else {
  37622. // Right side
  37623. x1 = (points[1][0] + points[2][0]) / 2;
  37624. y1 = (points[1][1] + points[2][1]) / 2;
  37625. x2 = x1 + labelLineLen;
  37626. textX = x2 + 5;
  37627. textAlign = 'left';
  37628. }
  37629. var y2 = y1;
  37630. linePoints = [[x1, y1], [x2, y2]];
  37631. textY = y2;
  37632. }
  37633. layout.label = {
  37634. linePoints: linePoints,
  37635. x: textX,
  37636. y: textY,
  37637. verticalAlign: 'middle',
  37638. textAlign: textAlign,
  37639. inside: isLabelInside
  37640. };
  37641. });
  37642. }
  37643. module.exports = function (ecModel, api, payload) {
  37644. ecModel.eachSeriesByType('funnel', function (seriesModel) {
  37645. var data = seriesModel.getData();
  37646. var sort = seriesModel.get('sort');
  37647. var viewRect = getViewRect(seriesModel, api);
  37648. var indices = getSortedIndices(data, sort);
  37649. var sizeExtent = [
  37650. parsePercent(seriesModel.get('minSize'), viewRect.width),
  37651. parsePercent(seriesModel.get('maxSize'), viewRect.width)
  37652. ];
  37653. var dataExtent = data.getDataExtent('value');
  37654. var min = seriesModel.get('min');
  37655. var max = seriesModel.get('max');
  37656. if (min == null) {
  37657. min = Math.min(dataExtent[0], 0);
  37658. }
  37659. if (max == null) {
  37660. max = dataExtent[1];
  37661. }
  37662. var funnelAlign = seriesModel.get('funnelAlign');
  37663. var gap = seriesModel.get('gap');
  37664. var itemHeight = (viewRect.height - gap * (data.count() - 1)) / data.count();
  37665. var y = viewRect.y;
  37666. var getLinePoints = function (idx, offY) {
  37667. // End point index is data.count() and we assign it 0
  37668. var val = data.get('value', idx) || 0;
  37669. var itemWidth = number.linearMap(val, [min, max], sizeExtent, true);
  37670. var x0;
  37671. switch (funnelAlign) {
  37672. case 'left':
  37673. x0 = viewRect.x;
  37674. break;
  37675. case 'center':
  37676. x0 = viewRect.x + (viewRect.width - itemWidth) / 2;
  37677. break;
  37678. case 'right':
  37679. x0 = viewRect.x + viewRect.width - itemWidth;
  37680. break;
  37681. }
  37682. return [
  37683. [x0, offY],
  37684. [x0 + itemWidth, offY]
  37685. ];
  37686. };
  37687. if (sort === 'ascending') {
  37688. // From bottom to top
  37689. itemHeight = -itemHeight;
  37690. gap = -gap;
  37691. y += viewRect.height;
  37692. indices = indices.reverse();
  37693. }
  37694. for (var i = 0; i < indices.length; i++) {
  37695. var idx = indices[i];
  37696. var nextIdx = indices[i + 1];
  37697. var start = getLinePoints(idx, y);
  37698. var end = getLinePoints(nextIdx, y + itemHeight);
  37699. y += itemHeight + gap;
  37700. data.setItemLayout(idx, {
  37701. points: start.concat(end.slice().reverse())
  37702. });
  37703. }
  37704. labelLayout(data);
  37705. });
  37706. };
  37707. /***/ },
  37708. /* 233 */
  37709. /***/ function(module, exports, __webpack_require__) {
  37710. var echarts = __webpack_require__(1);
  37711. __webpack_require__(234);
  37712. __webpack_require__(247);
  37713. __webpack_require__(248);
  37714. echarts.registerVisual(__webpack_require__(249));
  37715. /***/ },
  37716. /* 234 */
  37717. /***/ function(module, exports, __webpack_require__) {
  37718. __webpack_require__(235);
  37719. __webpack_require__(239);
  37720. __webpack_require__(241);
  37721. var echarts = __webpack_require__(1);
  37722. var zrUtil = __webpack_require__(4);
  37723. var throttle = __webpack_require__(81);
  37724. var CLICK_THRESHOLD = 5; // > 4
  37725. // Parallel view
  37726. echarts.extendComponentView({
  37727. type: 'parallel',
  37728. render: function (parallelModel, ecModel, api) {
  37729. this._model = parallelModel;
  37730. this._api = api;
  37731. if (!this._handlers) {
  37732. this._handlers = {};
  37733. zrUtil.each(handlers, function (handler, eventName) {
  37734. api.getZr().on(eventName, this._handlers[eventName] = zrUtil.bind(handler, this));
  37735. }, this);
  37736. }
  37737. throttle.createOrUpdate(
  37738. this,
  37739. '_throttledDispatchExpand',
  37740. parallelModel.get('axisExpandRate'),
  37741. 'fixRate'
  37742. );
  37743. },
  37744. dispose: function (ecModel, api) {
  37745. zrUtil.each(this._handlers, function (handler, eventName) {
  37746. api.getZr().off(eventName, handler);
  37747. });
  37748. this._handlers = null;
  37749. },
  37750. /**
  37751. * @param {Object} [opt] If null, cancle the last action triggering for debounce.
  37752. */
  37753. _throttledDispatchExpand: function (opt) {
  37754. this._dispatchExpand(opt);
  37755. },
  37756. _dispatchExpand: function (opt) {
  37757. opt && this._api.dispatchAction(
  37758. zrUtil.extend({type: 'parallelAxisExpand'}, opt)
  37759. );
  37760. }
  37761. });
  37762. var handlers = {
  37763. mousedown: function (e) {
  37764. if (checkTrigger(this, 'click')) {
  37765. this._mouseDownPoint = [e.offsetX, e.offsetY];
  37766. }
  37767. },
  37768. mouseup: function (e) {
  37769. var mouseDownPoint = this._mouseDownPoint;
  37770. if (checkTrigger(this, 'click') && mouseDownPoint) {
  37771. var point = [e.offsetX, e.offsetY];
  37772. var dist = Math.pow(mouseDownPoint[0] - point[0], 2)
  37773. + Math.pow(mouseDownPoint[1] - point[1], 2);
  37774. if (dist > CLICK_THRESHOLD) {
  37775. return;
  37776. }
  37777. var result = this._model.coordinateSystem.getSlidedAxisExpandWindow(
  37778. [e.offsetX, e.offsetY]
  37779. );
  37780. result.behavior !== 'none' && this._dispatchExpand({
  37781. axisExpandWindow: result.axisExpandWindow
  37782. });
  37783. }
  37784. this._mouseDownPoint = null;
  37785. },
  37786. mousemove: function (e) {
  37787. // Should do nothing when brushing.
  37788. if (this._mouseDownPoint || !checkTrigger(this, 'mousemove')) {
  37789. return;
  37790. }
  37791. var model = this._model;
  37792. var result = model.coordinateSystem.getSlidedAxisExpandWindow(
  37793. [e.offsetX, e.offsetY]
  37794. );
  37795. var behavior = result.behavior;
  37796. behavior === 'jump' && this._throttledDispatchExpand.debounceNextCall(model.get('axisExpandDebounce'));
  37797. this._throttledDispatchExpand(
  37798. behavior === 'none'
  37799. ? null // Cancle the last trigger, in case that mouse slide out of the area quickly.
  37800. : {
  37801. axisExpandWindow: result.axisExpandWindow,
  37802. // Jumping uses animation, and sliding suppresses animation.
  37803. animation: behavior === 'jump' ? null : false
  37804. }
  37805. );
  37806. }
  37807. };
  37808. function checkTrigger(view, triggerOn) {
  37809. var model = view._model;
  37810. return model.get('axisExpandable') && model.get('axisExpandTriggerOn') === triggerOn;
  37811. }
  37812. echarts.registerPreprocessor(
  37813. __webpack_require__(246)
  37814. );
  37815. /***/ },
  37816. /* 235 */
  37817. /***/ function(module, exports, __webpack_require__) {
  37818. /**
  37819. * Parallel coordinate system creater.
  37820. */
  37821. var Parallel = __webpack_require__(236);
  37822. function create(ecModel, api) {
  37823. var coordSysList = [];
  37824. ecModel.eachComponent('parallel', function (parallelModel, idx) {
  37825. var coordSys = new Parallel(parallelModel, ecModel, api);
  37826. coordSys.name = 'parallel_' + idx;
  37827. coordSys.resize(parallelModel, api);
  37828. parallelModel.coordinateSystem = coordSys;
  37829. coordSys.model = parallelModel;
  37830. coordSysList.push(coordSys);
  37831. });
  37832. // Inject the coordinateSystems into seriesModel
  37833. ecModel.eachSeries(function (seriesModel) {
  37834. if (seriesModel.get('coordinateSystem') === 'parallel') {
  37835. var parallelModel = ecModel.queryComponents({
  37836. mainType: 'parallel',
  37837. index: seriesModel.get('parallelIndex'),
  37838. id: seriesModel.get('parallelId')
  37839. })[0];
  37840. seriesModel.coordinateSystem = parallelModel.coordinateSystem;
  37841. }
  37842. });
  37843. return coordSysList;
  37844. }
  37845. __webpack_require__(76).register('parallel', {create: create});
  37846. /***/ },
  37847. /* 236 */
  37848. /***/ function(module, exports, __webpack_require__) {
  37849. /**
  37850. * Parallel Coordinates
  37851. * <https://en.wikipedia.org/wiki/Parallel_coordinates>
  37852. */
  37853. var layoutUtil = __webpack_require__(71);
  37854. var axisHelper = __webpack_require__(101);
  37855. var zrUtil = __webpack_require__(4);
  37856. var ParallelAxis = __webpack_require__(237);
  37857. var graphic = __webpack_require__(18);
  37858. var matrix = __webpack_require__(11);
  37859. var numberUtil = __webpack_require__(7);
  37860. var sliderMove = __webpack_require__(238);
  37861. var each = zrUtil.each;
  37862. var mathMin = Math.min;
  37863. var mathMax = Math.max;
  37864. var mathFloor = Math.floor;
  37865. var mathCeil = Math.ceil;
  37866. var round = numberUtil.round;
  37867. var PI = Math.PI;
  37868. function Parallel(parallelModel, ecModel, api) {
  37869. /**
  37870. * key: dimension
  37871. * @type {Object.<string, module:echarts/coord/parallel/Axis>}
  37872. * @private
  37873. */
  37874. this._axesMap = zrUtil.createHashMap();
  37875. /**
  37876. * key: dimension
  37877. * value: {position: [], rotation, }
  37878. * @type {Object.<string, Object>}
  37879. * @private
  37880. */
  37881. this._axesLayout = {};
  37882. /**
  37883. * Always follow axis order.
  37884. * @type {Array.<string>}
  37885. * @readOnly
  37886. */
  37887. this.dimensions = parallelModel.dimensions;
  37888. /**
  37889. * @type {module:zrender/core/BoundingRect}
  37890. */
  37891. this._rect;
  37892. /**
  37893. * @type {module:echarts/coord/parallel/ParallelModel}
  37894. */
  37895. this._model = parallelModel;
  37896. this._init(parallelModel, ecModel, api);
  37897. }
  37898. Parallel.prototype = {
  37899. type: 'parallel',
  37900. constructor: Parallel,
  37901. /**
  37902. * Initialize cartesian coordinate systems
  37903. * @private
  37904. */
  37905. _init: function (parallelModel, ecModel, api) {
  37906. var dimensions = parallelModel.dimensions;
  37907. var parallelAxisIndex = parallelModel.parallelAxisIndex;
  37908. each(dimensions, function (dim, idx) {
  37909. var axisIndex = parallelAxisIndex[idx];
  37910. var axisModel = ecModel.getComponent('parallelAxis', axisIndex);
  37911. var axis = this._axesMap.set(dim, new ParallelAxis(
  37912. dim,
  37913. axisHelper.createScaleByModel(axisModel),
  37914. [0, 0],
  37915. axisModel.get('type'),
  37916. axisIndex
  37917. ));
  37918. var isCategory = axis.type === 'category';
  37919. axis.onBand = isCategory && axisModel.get('boundaryGap');
  37920. axis.inverse = axisModel.get('inverse');
  37921. // Injection
  37922. axisModel.axis = axis;
  37923. axis.model = axisModel;
  37924. axis.coordinateSystem = axisModel.coordinateSystem = this;
  37925. }, this);
  37926. },
  37927. /**
  37928. * Update axis scale after data processed
  37929. * @param {module:echarts/model/Global} ecModel
  37930. * @param {module:echarts/ExtensionAPI} api
  37931. */
  37932. update: function (ecModel, api) {
  37933. this._updateAxesFromSeries(this._model, ecModel);
  37934. },
  37935. /**
  37936. * @override
  37937. */
  37938. containPoint: function (point) {
  37939. var layoutInfo = this._makeLayoutInfo();
  37940. var axisBase = layoutInfo.axisBase;
  37941. var layoutBase = layoutInfo.layoutBase;
  37942. var pixelDimIndex = layoutInfo.pixelDimIndex;
  37943. var pAxis = point[1 - pixelDimIndex];
  37944. var pLayout = point[pixelDimIndex];
  37945. return pAxis >= axisBase
  37946. && pAxis <= axisBase + layoutInfo.axisLength
  37947. && pLayout >= layoutBase
  37948. && pLayout <= layoutBase + layoutInfo.layoutLength;
  37949. },
  37950. /**
  37951. * Update properties from series
  37952. * @private
  37953. */
  37954. _updateAxesFromSeries: function (parallelModel, ecModel) {
  37955. ecModel.eachSeries(function (seriesModel) {
  37956. if (!parallelModel.contains(seriesModel, ecModel)) {
  37957. return;
  37958. }
  37959. var data = seriesModel.getData();
  37960. each(this.dimensions, function (dim) {
  37961. var axis = this._axesMap.get(dim);
  37962. axis.scale.unionExtentFromData(data, dim);
  37963. axisHelper.niceScaleExtent(axis.scale, axis.model);
  37964. }, this);
  37965. }, this);
  37966. },
  37967. /**
  37968. * Resize the parallel coordinate system.
  37969. * @param {module:echarts/coord/parallel/ParallelModel} parallelModel
  37970. * @param {module:echarts/ExtensionAPI} api
  37971. */
  37972. resize: function (parallelModel, api) {
  37973. this._rect = layoutUtil.getLayoutRect(
  37974. parallelModel.getBoxLayoutParams(),
  37975. {
  37976. width: api.getWidth(),
  37977. height: api.getHeight()
  37978. }
  37979. );
  37980. this._layoutAxes();
  37981. },
  37982. /**
  37983. * @return {module:zrender/core/BoundingRect}
  37984. */
  37985. getRect: function () {
  37986. return this._rect;
  37987. },
  37988. /**
  37989. * @private
  37990. */
  37991. _makeLayoutInfo: function () {
  37992. var parallelModel = this._model;
  37993. var rect = this._rect;
  37994. var xy = ['x', 'y'];
  37995. var wh = ['width', 'height'];
  37996. var layout = parallelModel.get('layout');
  37997. var pixelDimIndex = layout === 'horizontal' ? 0 : 1;
  37998. var layoutLength = rect[wh[pixelDimIndex]];
  37999. var layoutExtent = [0, layoutLength];
  38000. var axisCount = this.dimensions.length;
  38001. var axisExpandWidth = restrict(parallelModel.get('axisExpandWidth'), layoutExtent);
  38002. var axisExpandCount = restrict(parallelModel.get('axisExpandCount') || 0, [0, axisCount]);
  38003. var axisExpandable = parallelModel.get('axisExpandable')
  38004. && axisCount > 3
  38005. && axisCount > axisExpandCount
  38006. && axisExpandCount > 1
  38007. && axisExpandWidth > 0
  38008. && layoutLength > 0;
  38009. // `axisExpandWindow` is According to the coordinates of [0, axisExpandLength],
  38010. // for sake of consider the case that axisCollapseWidth is 0 (when screen is narrow),
  38011. // where collapsed axes should be overlapped.
  38012. var axisExpandWindow = parallelModel.get('axisExpandWindow');
  38013. var winSize;
  38014. if (!axisExpandWindow) {
  38015. winSize = restrict(axisExpandWidth * (axisExpandCount - 1), layoutExtent);
  38016. var axisExpandCenter = parallelModel.get('axisExpandCenter') || mathFloor(axisCount / 2);
  38017. axisExpandWindow = [axisExpandWidth * axisExpandCenter - winSize / 2];
  38018. axisExpandWindow[1] = axisExpandWindow[0] + winSize;
  38019. }
  38020. else {
  38021. winSize = restrict(axisExpandWindow[1] - axisExpandWindow[0], layoutExtent);
  38022. axisExpandWindow[1] = axisExpandWindow[0] + winSize;
  38023. }
  38024. var axisCollapseWidth = (layoutLength - winSize) / (axisCount - axisExpandCount);
  38025. // Avoid axisCollapseWidth is too small.
  38026. axisCollapseWidth < 3 && (axisCollapseWidth = 0);
  38027. // Find the first and last indices > ewin[0] and < ewin[1].
  38028. var winInnerIndices = [
  38029. mathFloor(round(axisExpandWindow[0] / axisExpandWidth, 1)) + 1,
  38030. mathCeil(round(axisExpandWindow[1] / axisExpandWidth, 1)) - 1
  38031. ];
  38032. // Pos in ec coordinates.
  38033. var axisExpandWindow0Pos = axisCollapseWidth / axisExpandWidth * axisExpandWindow[0];
  38034. return {
  38035. layout: layout,
  38036. pixelDimIndex: pixelDimIndex,
  38037. layoutBase: rect[xy[pixelDimIndex]],
  38038. layoutLength: layoutLength,
  38039. axisBase: rect[xy[1 - pixelDimIndex]],
  38040. axisLength: rect[wh[1 - pixelDimIndex]],
  38041. axisExpandable: axisExpandable,
  38042. axisExpandWidth: axisExpandWidth,
  38043. axisCollapseWidth: axisCollapseWidth,
  38044. axisExpandWindow: axisExpandWindow,
  38045. axisCount: axisCount,
  38046. winInnerIndices: winInnerIndices,
  38047. axisExpandWindow0Pos: axisExpandWindow0Pos
  38048. };
  38049. },
  38050. /**
  38051. * @private
  38052. */
  38053. _layoutAxes: function () {
  38054. var rect = this._rect;
  38055. var axes = this._axesMap;
  38056. var dimensions = this.dimensions;
  38057. var layoutInfo = this._makeLayoutInfo();
  38058. var layout = layoutInfo.layout;
  38059. axes.each(function (axis) {
  38060. var axisExtent = [0, layoutInfo.axisLength];
  38061. var idx = axis.inverse ? 1 : 0;
  38062. axis.setExtent(axisExtent[idx], axisExtent[1 - idx]);
  38063. });
  38064. each(dimensions, function (dim, idx) {
  38065. var posInfo = (layoutInfo.axisExpandable
  38066. ? layoutAxisWithExpand : layoutAxisWithoutExpand
  38067. )(idx, layoutInfo);
  38068. var positionTable = {
  38069. horizontal: {
  38070. x: posInfo.position,
  38071. y: layoutInfo.axisLength
  38072. },
  38073. vertical: {
  38074. x: 0,
  38075. y: posInfo.position
  38076. }
  38077. };
  38078. var rotationTable = {
  38079. horizontal: PI / 2,
  38080. vertical: 0
  38081. };
  38082. var position = [
  38083. positionTable[layout].x + rect.x,
  38084. positionTable[layout].y + rect.y
  38085. ];
  38086. var rotation = rotationTable[layout];
  38087. var transform = matrix.create();
  38088. matrix.rotate(transform, transform, rotation);
  38089. matrix.translate(transform, transform, position);
  38090. // TODO
  38091. // tick等排布信息。
  38092. // TODO
  38093. // 根据axis order 更新 dimensions顺序。
  38094. this._axesLayout[dim] = {
  38095. position: position,
  38096. rotation: rotation,
  38097. transform: transform,
  38098. axisNameAvailableWidth: posInfo.axisNameAvailableWidth,
  38099. axisLabelShow: posInfo.axisLabelShow,
  38100. nameTruncateMaxWidth: posInfo.nameTruncateMaxWidth,
  38101. tickDirection: 1,
  38102. labelDirection: 1,
  38103. labelInterval: axes.get(dim).getLabelInterval()
  38104. };
  38105. }, this);
  38106. },
  38107. /**
  38108. * Get axis by dim.
  38109. * @param {string} dim
  38110. * @return {module:echarts/coord/parallel/ParallelAxis} [description]
  38111. */
  38112. getAxis: function (dim) {
  38113. return this._axesMap.get(dim);
  38114. },
  38115. /**
  38116. * Convert a dim value of a single item of series data to Point.
  38117. * @param {*} value
  38118. * @param {string} dim
  38119. * @return {Array}
  38120. */
  38121. dataToPoint: function (value, dim) {
  38122. return this.axisCoordToPoint(
  38123. this._axesMap.get(dim).dataToCoord(value),
  38124. dim
  38125. );
  38126. },
  38127. /**
  38128. * Travel data for one time, get activeState of each data item.
  38129. * @param {module:echarts/data/List} data
  38130. * @param {Functio} cb param: {string} activeState 'active' or 'inactive' or 'normal'
  38131. * {number} dataIndex
  38132. * @param {Object} context
  38133. */
  38134. eachActiveState: function (data, callback, context) {
  38135. var dimensions = this.dimensions;
  38136. var axesMap = this._axesMap;
  38137. var hasActiveSet = this.hasAxisBrushed();
  38138. for (var i = 0, len = data.count(); i < len; i++) {
  38139. var values = data.getValues(dimensions, i);
  38140. var activeState;
  38141. if (!hasActiveSet) {
  38142. activeState = 'normal';
  38143. }
  38144. else {
  38145. activeState = 'active';
  38146. for (var j = 0, lenj = dimensions.length; j < lenj; j++) {
  38147. var dimName = dimensions[j];
  38148. var state = axesMap.get(dimName).model.getActiveState(values[j], j);
  38149. if (state === 'inactive') {
  38150. activeState = 'inactive';
  38151. break;
  38152. }
  38153. }
  38154. }
  38155. callback.call(context, activeState, i);
  38156. }
  38157. },
  38158. /**
  38159. * Whether has any activeSet.
  38160. * @return {boolean}
  38161. */
  38162. hasAxisBrushed: function () {
  38163. var dimensions = this.dimensions;
  38164. var axesMap = this._axesMap;
  38165. var hasActiveSet = false;
  38166. for (var j = 0, lenj = dimensions.length; j < lenj; j++) {
  38167. if (axesMap.get(dimensions[j]).model.getActiveState() !== 'normal') {
  38168. hasActiveSet = true;
  38169. }
  38170. }
  38171. return hasActiveSet;
  38172. },
  38173. /**
  38174. * Convert coords of each axis to Point.
  38175. * Return point. For example: [10, 20]
  38176. * @param {Array.<number>} coords
  38177. * @param {string} dim
  38178. * @return {Array.<number>}
  38179. */
  38180. axisCoordToPoint: function (coord, dim) {
  38181. var axisLayout = this._axesLayout[dim];
  38182. return graphic.applyTransform([coord, 0], axisLayout.transform);
  38183. },
  38184. /**
  38185. * Get axis layout.
  38186. */
  38187. getAxisLayout: function (dim) {
  38188. return zrUtil.clone(this._axesLayout[dim]);
  38189. },
  38190. /**
  38191. * @param {Array.<number>} point
  38192. * @return {Object} {axisExpandWindow, delta, behavior: 'jump' | 'slide' | 'none'}.
  38193. */
  38194. getSlidedAxisExpandWindow: function (point) {
  38195. var layoutInfo = this._makeLayoutInfo();
  38196. var pixelDimIndex = layoutInfo.pixelDimIndex;
  38197. var axisExpandWindow = layoutInfo.axisExpandWindow.slice();
  38198. var winSize = axisExpandWindow[1] - axisExpandWindow[0];
  38199. var extent = [0, layoutInfo.axisExpandWidth * (layoutInfo.axisCount - 1)];
  38200. // Out of the area of coordinate system.
  38201. if (!this.containPoint(point)) {
  38202. return {behavior: 'none', axisExpandWindow: axisExpandWindow};
  38203. }
  38204. // Conver the point from global to expand coordinates.
  38205. var pointCoord = point[pixelDimIndex] - layoutInfo.layoutBase - layoutInfo.axisExpandWindow0Pos;
  38206. // For dragging operation convenience, the window should not be
  38207. // slided when mouse is the center area of the window.
  38208. var delta;
  38209. var behavior = 'slide';
  38210. var axisCollapseWidth = layoutInfo.axisCollapseWidth;
  38211. var triggerArea = this._model.get('axisExpandSlideTriggerArea');
  38212. // But consider touch device, jump is necessary.
  38213. var useJump = triggerArea[0] != null;
  38214. if (axisCollapseWidth) {
  38215. if (useJump && axisCollapseWidth && pointCoord < winSize * triggerArea[0]) {
  38216. behavior = 'jump';
  38217. delta = pointCoord - winSize * triggerArea[2];
  38218. }
  38219. else if (useJump && axisCollapseWidth && pointCoord > winSize * (1 - triggerArea[0])) {
  38220. behavior = 'jump';
  38221. delta = pointCoord - winSize * (1 - triggerArea[2]);
  38222. }
  38223. else {
  38224. (delta = pointCoord - winSize * triggerArea[1]) >= 0
  38225. && (delta = pointCoord - winSize * (1 - triggerArea[1])) <= 0
  38226. && (delta = 0);
  38227. }
  38228. delta *= layoutInfo.axisExpandWidth / axisCollapseWidth;
  38229. delta
  38230. ? sliderMove(delta, axisExpandWindow, extent, 'all')
  38231. // Avoid nonsense triger on mousemove.
  38232. : (behavior = 'none');
  38233. }
  38234. // When screen is too narrow, make it visible and slidable, although it is hard to interact.
  38235. else {
  38236. var winSize = axisExpandWindow[1] - axisExpandWindow[0];
  38237. var pos = extent[1] * pointCoord / winSize;
  38238. axisExpandWindow = [mathMax(0, pos - winSize / 2)];
  38239. axisExpandWindow[1] = mathMin(extent[1], axisExpandWindow[0] + winSize);
  38240. axisExpandWindow[0] = axisExpandWindow[1] - winSize;
  38241. }
  38242. return {
  38243. axisExpandWindow: axisExpandWindow,
  38244. behavior: behavior
  38245. };
  38246. }
  38247. };
  38248. function restrict(len, extent) {
  38249. return mathMin(mathMax(len, extent[0]), extent[1]);
  38250. }
  38251. function layoutAxisWithoutExpand(axisIndex, layoutInfo) {
  38252. var step = layoutInfo.layoutLength / (layoutInfo.axisCount - 1);
  38253. return {
  38254. position: step * axisIndex,
  38255. axisNameAvailableWidth: step,
  38256. axisLabelShow: true
  38257. };
  38258. }
  38259. function layoutAxisWithExpand(axisIndex, layoutInfo) {
  38260. var layoutLength = layoutInfo.layoutLength;
  38261. var axisExpandWidth = layoutInfo.axisExpandWidth;
  38262. var axisCount = layoutInfo.axisCount;
  38263. var axisCollapseWidth = layoutInfo.axisCollapseWidth;
  38264. var winInnerIndices = layoutInfo.winInnerIndices;
  38265. var position;
  38266. var axisNameAvailableWidth = axisCollapseWidth;
  38267. var axisLabelShow = false;
  38268. var nameTruncateMaxWidth;
  38269. if (axisIndex < winInnerIndices[0]) {
  38270. position = axisIndex * axisCollapseWidth;
  38271. nameTruncateMaxWidth = axisCollapseWidth;
  38272. }
  38273. else if (axisIndex <= winInnerIndices[1]) {
  38274. position = layoutInfo.axisExpandWindow0Pos
  38275. + axisIndex * axisExpandWidth - layoutInfo.axisExpandWindow[0];
  38276. axisNameAvailableWidth = axisExpandWidth;
  38277. axisLabelShow = true;
  38278. }
  38279. else {
  38280. position = layoutLength - (axisCount - 1 - axisIndex) * axisCollapseWidth;
  38281. nameTruncateMaxWidth = axisCollapseWidth;
  38282. }
  38283. return {
  38284. position: position,
  38285. axisNameAvailableWidth: axisNameAvailableWidth,
  38286. axisLabelShow: axisLabelShow,
  38287. nameTruncateMaxWidth: nameTruncateMaxWidth
  38288. };
  38289. }
  38290. module.exports = Parallel;
  38291. /***/ },
  38292. /* 237 */
  38293. /***/ function(module, exports, __webpack_require__) {
  38294. var zrUtil = __webpack_require__(4);
  38295. var Axis = __webpack_require__(100);
  38296. /**
  38297. * @constructor module:echarts/coord/parallel/ParallelAxis
  38298. * @extends {module:echarts/coord/Axis}
  38299. * @param {string} dim
  38300. * @param {*} scale
  38301. * @param {Array.<number>} coordExtent
  38302. * @param {string} axisType
  38303. */
  38304. var ParallelAxis = function (dim, scale, coordExtent, axisType, axisIndex) {
  38305. Axis.call(this, dim, scale, coordExtent);
  38306. /**
  38307. * Axis type
  38308. * - 'category'
  38309. * - 'value'
  38310. * - 'time'
  38311. * - 'log'
  38312. * @type {string}
  38313. */
  38314. this.type = axisType || 'value';
  38315. /**
  38316. * @type {number}
  38317. * @readOnly
  38318. */
  38319. this.axisIndex = axisIndex;
  38320. };
  38321. ParallelAxis.prototype = {
  38322. constructor: ParallelAxis,
  38323. /**
  38324. * Axis model
  38325. * @param {module:echarts/coord/parallel/AxisModel}
  38326. */
  38327. model: null
  38328. };
  38329. zrUtil.inherits(ParallelAxis, Axis);
  38330. module.exports = ParallelAxis;
  38331. /***/ },
  38332. /* 238 */
  38333. /***/ function(module, exports) {
  38334. /**
  38335. * Calculate slider move result.
  38336. * Usage:
  38337. * (1) If both handle0 and handle1 are needed to be moved, set minSpan the same as
  38338. * maxSpan and the same as `Math.abs(handleEnd[1] - handleEnds[0])`.
  38339. * (2) If handle0 is forbidden to cross handle1, set minSpan as `0`.
  38340. *
  38341. * @param {number} delta Move length.
  38342. * @param {Array.<number>} handleEnds handleEnds[0] can be bigger then handleEnds[1].
  38343. * handleEnds will be modified in this method.
  38344. * @param {Array.<number>} extent handleEnds is restricted by extent.
  38345. * extent[0] should less or equals than extent[1].
  38346. * @param {number|string} handleIndex Can be 'all', means that both move the two handleEnds,
  38347. * where the input minSpan and maxSpan will not work.
  38348. * @param {number} [minSpan] The range of dataZoom can not be smaller than that.
  38349. * If not set, handle0 and cross handle1. If set as a non-negative
  38350. * number (including `0`), handles will push each other when reaching
  38351. * the minSpan.
  38352. * @param {number} [maxSpan] The range of dataZoom can not be larger than that.
  38353. * @return {Array.<number>} The input handleEnds.
  38354. */
  38355. module.exports = function (delta, handleEnds, extent, handleIndex, minSpan, maxSpan) {
  38356. // Normalize firstly.
  38357. handleEnds[0] = restrict(handleEnds[0], extent);
  38358. handleEnds[1] = restrict(handleEnds[1], extent);
  38359. delta = delta || 0;
  38360. var extentSpan = extent[1] - extent[0];
  38361. // Notice maxSpan and minSpan can be null/undefined.
  38362. if (minSpan != null) {
  38363. minSpan = restrict(minSpan, [0, extentSpan]);
  38364. }
  38365. if (maxSpan != null) {
  38366. maxSpan = Math.max(maxSpan, minSpan != null ? minSpan : 0);
  38367. }
  38368. if (handleIndex === 'all') {
  38369. minSpan = maxSpan = Math.abs(handleEnds[1] - handleEnds[0]);
  38370. handleIndex = 0;
  38371. }
  38372. var originalDistSign = getSpanSign(handleEnds, handleIndex);
  38373. handleEnds[handleIndex] += delta;
  38374. // Restrict in extent.
  38375. var extentMinSpan = minSpan || 0;
  38376. var realExtent = extent.slice();
  38377. originalDistSign.sign < 0 ? (realExtent[0] += extentMinSpan) : (realExtent[1] -= extentMinSpan);
  38378. handleEnds[handleIndex] = restrict(handleEnds[handleIndex], realExtent);
  38379. // Expand span.
  38380. var currDistSign = getSpanSign(handleEnds, handleIndex);
  38381. if (minSpan != null && (
  38382. currDistSign.sign !== originalDistSign.sign || currDistSign.span < minSpan
  38383. )) {
  38384. // If minSpan exists, 'cross' is forbinden.
  38385. handleEnds[1 - handleIndex] = handleEnds[handleIndex] + originalDistSign.sign * minSpan;
  38386. }
  38387. // Shrink span.
  38388. var currDistSign = getSpanSign(handleEnds, handleIndex);
  38389. if (maxSpan != null && currDistSign.span > maxSpan) {
  38390. handleEnds[1 - handleIndex] = handleEnds[handleIndex] + currDistSign.sign * maxSpan;
  38391. }
  38392. return handleEnds;
  38393. };
  38394. function getSpanSign(handleEnds, handleIndex) {
  38395. var dist = handleEnds[handleIndex] - handleEnds[1 - handleIndex];
  38396. // If `handleEnds[0] === handleEnds[1]`, always believe that handleEnd[0]
  38397. // is at left of handleEnds[1] for non-cross case.
  38398. return {span: Math.abs(dist), sign: dist > 0 ? -1 : dist < 0 ? 1 : handleIndex ? -1 : 1};
  38399. }
  38400. function restrict(value, extend) {
  38401. return Math.min(extend[1], Math.max(extend[0], value));
  38402. }
  38403. /***/ },
  38404. /* 239 */
  38405. /***/ function(module, exports, __webpack_require__) {
  38406. var zrUtil = __webpack_require__(4);
  38407. var Component = __webpack_require__(69);
  38408. __webpack_require__(240);
  38409. Component.extend({
  38410. type: 'parallel',
  38411. dependencies: ['parallelAxis'],
  38412. /**
  38413. * @type {module:echarts/coord/parallel/Parallel}
  38414. */
  38415. coordinateSystem: null,
  38416. /**
  38417. * Each item like: 'dim0', 'dim1', 'dim2', ...
  38418. * @type {Array.<string>}
  38419. * @readOnly
  38420. */
  38421. dimensions: null,
  38422. /**
  38423. * Coresponding to dimensions.
  38424. * @type {Array.<number>}
  38425. * @readOnly
  38426. */
  38427. parallelAxisIndex: null,
  38428. layoutMode: 'box',
  38429. defaultOption: {
  38430. zlevel: 0,
  38431. z: 0,
  38432. left: 80,
  38433. top: 60,
  38434. right: 80,
  38435. bottom: 60,
  38436. // width: {totalWidth} - left - right,
  38437. // height: {totalHeight} - top - bottom,
  38438. layout: 'horizontal', // 'horizontal' or 'vertical'
  38439. // FIXME
  38440. // naming?
  38441. axisExpandable: false,
  38442. axisExpandCenter: null,
  38443. axisExpandCount: 0,
  38444. axisExpandWidth: 50, // FIXME '10%' ?
  38445. axisExpandRate: 17,
  38446. axisExpandDebounce: 50,
  38447. // [out, in, jumpTarget]. In percentage. If use [null, 0.05], null means full.
  38448. // Do not doc to user until necessary.
  38449. axisExpandSlideTriggerArea: [-0.15, 0.05, 0.4],
  38450. axisExpandTriggerOn: 'click', // 'mousemove' or 'click'
  38451. parallelAxisDefault: null
  38452. },
  38453. /**
  38454. * @override
  38455. */
  38456. init: function () {
  38457. Component.prototype.init.apply(this, arguments);
  38458. this.mergeOption({});
  38459. },
  38460. /**
  38461. * @override
  38462. */
  38463. mergeOption: function (newOption) {
  38464. var thisOption = this.option;
  38465. newOption && zrUtil.merge(thisOption, newOption, true);
  38466. this._initDimensions();
  38467. },
  38468. /**
  38469. * Whether series or axis is in this coordinate system.
  38470. * @param {module:echarts/model/Series|module:echarts/coord/parallel/AxisModel} model
  38471. * @param {module:echarts/model/Global} ecModel
  38472. */
  38473. contains: function (model, ecModel) {
  38474. var parallelIndex = model.get('parallelIndex');
  38475. return parallelIndex != null
  38476. && ecModel.getComponent('parallel', parallelIndex) === this;
  38477. },
  38478. setAxisExpand: function (opt) {
  38479. zrUtil.each(
  38480. ['axisExpandable', 'axisExpandCenter', 'axisExpandCount', 'axisExpandWidth', 'axisExpandWindow'],
  38481. function (name) {
  38482. if (opt.hasOwnProperty(name)) {
  38483. this.option[name] = opt[name];
  38484. }
  38485. },
  38486. this
  38487. );
  38488. },
  38489. /**
  38490. * @private
  38491. */
  38492. _initDimensions: function () {
  38493. var dimensions = this.dimensions = [];
  38494. var parallelAxisIndex = this.parallelAxisIndex = [];
  38495. var axisModels = zrUtil.filter(this.dependentModels.parallelAxis, function (axisModel) {
  38496. // Can not use this.contains here, because
  38497. // initialization has not been completed yet.
  38498. return axisModel.get('parallelIndex') === this.componentIndex;
  38499. });
  38500. zrUtil.each(axisModels, function (axisModel) {
  38501. dimensions.push('dim' + axisModel.get('dim'));
  38502. parallelAxisIndex.push(axisModel.componentIndex);
  38503. });
  38504. }
  38505. });
  38506. /***/ },
  38507. /* 240 */
  38508. /***/ function(module, exports, __webpack_require__) {
  38509. var ComponentModel = __webpack_require__(69);
  38510. var zrUtil = __webpack_require__(4);
  38511. var makeStyleMapper = __webpack_require__(15);
  38512. var axisModelCreator = __webpack_require__(131);
  38513. var numberUtil = __webpack_require__(7);
  38514. var AxisModel = ComponentModel.extend({
  38515. type: 'baseParallelAxis',
  38516. /**
  38517. * @type {module:echarts/coord/parallel/Axis}
  38518. */
  38519. axis: null,
  38520. /**
  38521. * @type {Array.<Array.<number>}
  38522. * @readOnly
  38523. */
  38524. activeIntervals: [],
  38525. /**
  38526. * @return {Object}
  38527. */
  38528. getAreaSelectStyle: function () {
  38529. return makeStyleMapper(
  38530. [
  38531. ['fill', 'color'],
  38532. ['lineWidth', 'borderWidth'],
  38533. ['stroke', 'borderColor'],
  38534. ['width', 'width'],
  38535. ['opacity', 'opacity']
  38536. ]
  38537. ).call(this.getModel('areaSelectStyle'));
  38538. },
  38539. /**
  38540. * The code of this feature is put on AxisModel but not ParallelAxis,
  38541. * because axisModel can be alive after echarts updating but instance of
  38542. * ParallelAxis having been disposed. this._activeInterval should be kept
  38543. * when action dispatched (i.e. legend click).
  38544. *
  38545. * @param {Array.<Array<number>>} intervals interval.length === 0
  38546. * means set all active.
  38547. * @public
  38548. */
  38549. setActiveIntervals: function (intervals) {
  38550. var activeIntervals = this.activeIntervals = zrUtil.clone(intervals);
  38551. // Normalize
  38552. if (activeIntervals) {
  38553. for (var i = activeIntervals.length - 1; i >= 0; i--) {
  38554. numberUtil.asc(activeIntervals[i]);
  38555. }
  38556. }
  38557. },
  38558. /**
  38559. * @param {number|string} [value] When attempting to detect 'no activeIntervals set',
  38560. * value can not be input.
  38561. * @return {string} 'normal': no activeIntervals set,
  38562. * 'active',
  38563. * 'inactive'.
  38564. * @public
  38565. */
  38566. getActiveState: function (value) {
  38567. var activeIntervals = this.activeIntervals;
  38568. if (!activeIntervals.length) {
  38569. return 'normal';
  38570. }
  38571. if (value == null) {
  38572. return 'inactive';
  38573. }
  38574. for (var i = 0, len = activeIntervals.length; i < len; i++) {
  38575. if (activeIntervals[i][0] <= value && value <= activeIntervals[i][1]) {
  38576. return 'active';
  38577. }
  38578. }
  38579. return 'inactive';
  38580. }
  38581. });
  38582. var defaultOption = {
  38583. type: 'value',
  38584. /**
  38585. * @type {Array.<number>}
  38586. */
  38587. dim: null, // 0, 1, 2, ...
  38588. // parallelIndex: null,
  38589. areaSelectStyle: {
  38590. width: 20,
  38591. borderWidth: 1,
  38592. borderColor: 'rgba(160,197,232)',
  38593. color: 'rgba(160,197,232)',
  38594. opacity: 0.3
  38595. },
  38596. realtime: true, // Whether realtime update view when select.
  38597. z: 10
  38598. };
  38599. zrUtil.merge(AxisModel.prototype, __webpack_require__(112));
  38600. function getAxisType(axisName, option) {
  38601. return option.type || (option.data ? 'category' : 'value');
  38602. }
  38603. axisModelCreator('parallel', AxisModel, getAxisType, defaultOption);
  38604. module.exports = AxisModel;
  38605. /***/ },
  38606. /* 241 */
  38607. /***/ function(module, exports, __webpack_require__) {
  38608. __webpack_require__(235);
  38609. __webpack_require__(242);
  38610. __webpack_require__(243);
  38611. /***/ },
  38612. /* 242 */
  38613. /***/ function(module, exports, __webpack_require__) {
  38614. var echarts = __webpack_require__(1);
  38615. /**
  38616. * @payload
  38617. * @property {string} parallelAxisId
  38618. * @property {Array.<Array.<number>>} intervals
  38619. */
  38620. var actionInfo = {
  38621. type: 'axisAreaSelect',
  38622. event: 'axisAreaSelected',
  38623. update: 'updateVisual'
  38624. };
  38625. echarts.registerAction(actionInfo, function (payload, ecModel) {
  38626. ecModel.eachComponent(
  38627. {mainType: 'parallelAxis', query: payload},
  38628. function (parallelAxisModel) {
  38629. parallelAxisModel.axis.model.setActiveIntervals(payload.intervals);
  38630. }
  38631. );
  38632. });
  38633. /**
  38634. * @payload
  38635. */
  38636. echarts.registerAction('parallelAxisExpand', function (payload, ecModel) {
  38637. ecModel.eachComponent(
  38638. {mainType: 'parallel', query: payload},
  38639. function (parallelModel) {
  38640. parallelModel.setAxisExpand(payload);
  38641. }
  38642. );
  38643. });
  38644. /***/ },
  38645. /* 243 */
  38646. /***/ function(module, exports, __webpack_require__) {
  38647. var zrUtil = __webpack_require__(4);
  38648. var AxisBuilder = __webpack_require__(135);
  38649. var BrushController = __webpack_require__(244);
  38650. var brushHelper = __webpack_require__(245);
  38651. var graphic = __webpack_require__(18);
  38652. var elementList = ['axisLine', 'axisLabel', 'axisTick', 'axisName'];
  38653. var AxisView = __webpack_require__(1).extendComponentView({
  38654. type: 'parallelAxis',
  38655. /**
  38656. * @override
  38657. */
  38658. init: function (ecModel, api) {
  38659. AxisView.superApply(this, 'init', arguments);
  38660. /**
  38661. * @type {module:echarts/component/helper/BrushController}
  38662. */
  38663. (this._brushController = new BrushController(api.getZr()))
  38664. .on('brush', zrUtil.bind(this._onBrush, this));
  38665. },
  38666. /**
  38667. * @override
  38668. */
  38669. render: function (axisModel, ecModel, api, payload) {
  38670. if (fromAxisAreaSelect(axisModel, ecModel, payload)) {
  38671. return;
  38672. }
  38673. this.axisModel = axisModel;
  38674. this.api = api;
  38675. this.group.removeAll();
  38676. var oldAxisGroup = this._axisGroup;
  38677. this._axisGroup = new graphic.Group();
  38678. this.group.add(this._axisGroup);
  38679. if (!axisModel.get('show')) {
  38680. return;
  38681. }
  38682. var coordSysModel = getCoordSysModel(axisModel, ecModel);
  38683. var coordSys = coordSysModel.coordinateSystem;
  38684. var areaSelectStyle = axisModel.getAreaSelectStyle();
  38685. var areaWidth = areaSelectStyle.width;
  38686. var dim = axisModel.axis.dim;
  38687. var axisLayout = coordSys.getAxisLayout(dim);
  38688. var builderOpt = zrUtil.extend(
  38689. {strokeContainThreshold: areaWidth},
  38690. axisLayout
  38691. );
  38692. var axisBuilder = new AxisBuilder(axisModel, builderOpt);
  38693. zrUtil.each(elementList, axisBuilder.add, axisBuilder);
  38694. this._axisGroup.add(axisBuilder.getGroup());
  38695. this._refreshBrushController(
  38696. builderOpt, areaSelectStyle, axisModel, coordSysModel, areaWidth, api
  38697. );
  38698. var animationModel = (payload && payload.animation === false) ? null : axisModel;
  38699. graphic.groupTransition(oldAxisGroup, this._axisGroup, animationModel);
  38700. },
  38701. /**
  38702. * @override
  38703. */
  38704. updateVisual: function (axisModel, ecModel, api, payload) {
  38705. this._brushController && this._brushController
  38706. .updateCovers(getCoverInfoList(axisModel));
  38707. },
  38708. _refreshBrushController: function (
  38709. builderOpt, areaSelectStyle, axisModel, coordSysModel, areaWidth, api
  38710. ) {
  38711. // After filtering, axis may change, select area needs to be update.
  38712. var extent = axisModel.axis.getExtent();
  38713. var extentLen = extent[1] - extent[0];
  38714. var extra = Math.min(30, Math.abs(extentLen) * 0.1); // Arbitrary value.
  38715. // width/height might be negative, which will be
  38716. // normalized in BoundingRect.
  38717. var rect = graphic.BoundingRect.create({
  38718. x: extent[0],
  38719. y: -areaWidth / 2,
  38720. width: extentLen,
  38721. height: areaWidth
  38722. });
  38723. rect.x -= extra;
  38724. rect.width += 2 * extra;
  38725. this._brushController
  38726. .mount({
  38727. enableGlobalPan: true,
  38728. rotation: builderOpt.rotation,
  38729. position: builderOpt.position
  38730. })
  38731. .setPanels([{
  38732. panelId: 'pl',
  38733. clipPath: brushHelper.makeRectPanelClipPath(rect),
  38734. isTargetByCursor: brushHelper.makeRectIsTargetByCursor(rect, api, coordSysModel),
  38735. getLinearBrushOtherExtent: brushHelper.makeLinearBrushOtherExtent(rect, 0)
  38736. }])
  38737. .enableBrush({
  38738. brushType: 'lineX',
  38739. brushStyle: areaSelectStyle,
  38740. removeOnClick: true
  38741. })
  38742. .updateCovers(getCoverInfoList(axisModel));
  38743. },
  38744. _onBrush: function (coverInfoList, opt) {
  38745. // Do not cache these object, because the mey be changed.
  38746. var axisModel = this.axisModel;
  38747. var axis = axisModel.axis;
  38748. var intervals = zrUtil.map(coverInfoList, function (coverInfo) {
  38749. return [
  38750. axis.coordToData(coverInfo.range[0], true),
  38751. axis.coordToData(coverInfo.range[1], true)
  38752. ];
  38753. });
  38754. // If realtime is true, action is not dispatched on drag end, because
  38755. // the drag end emits the same params with the last drag move event,
  38756. // and may have some delay when using touch pad.
  38757. if (!axisModel.option.realtime === opt.isEnd || opt.removeOnClick) { // jshint ignore:line
  38758. this.api.dispatchAction({
  38759. type: 'axisAreaSelect',
  38760. parallelAxisId: axisModel.id,
  38761. intervals: intervals
  38762. });
  38763. }
  38764. },
  38765. /**
  38766. * @override
  38767. */
  38768. dispose: function () {
  38769. this._brushController.dispose();
  38770. }
  38771. });
  38772. function fromAxisAreaSelect(axisModel, ecModel, payload) {
  38773. return payload
  38774. && payload.type === 'axisAreaSelect'
  38775. && ecModel.findComponents(
  38776. {mainType: 'parallelAxis', query: payload}
  38777. )[0] === axisModel;
  38778. }
  38779. function getCoverInfoList(axisModel) {
  38780. var axis = axisModel.axis;
  38781. return zrUtil.map(axisModel.activeIntervals, function (interval) {
  38782. return {
  38783. brushType: 'lineX',
  38784. panelId: 'pl',
  38785. range: [
  38786. axis.dataToCoord(interval[0], true),
  38787. axis.dataToCoord(interval[1], true)
  38788. ]
  38789. };
  38790. });
  38791. }
  38792. function getCoordSysModel(axisModel, ecModel) {
  38793. return ecModel.getComponent(
  38794. 'parallel', axisModel.get('parallelIndex')
  38795. );
  38796. }
  38797. module.exports = AxisView;
  38798. /***/ },
  38799. /* 244 */
  38800. /***/ function(module, exports, __webpack_require__) {
  38801. /**
  38802. * Box selection tool.
  38803. *
  38804. * @module echarts/component/helper/BrushController
  38805. */
  38806. var Eventful = __webpack_require__(25);
  38807. var zrUtil = __webpack_require__(4);
  38808. var graphic = __webpack_require__(18);
  38809. var interactionMutex = __webpack_require__(183);
  38810. var DataDiffer = __webpack_require__(99);
  38811. var curry = zrUtil.curry;
  38812. var each = zrUtil.each;
  38813. var map = zrUtil.map;
  38814. var mathMin = Math.min;
  38815. var mathMax = Math.max;
  38816. var mathPow = Math.pow;
  38817. var COVER_Z = 10000;
  38818. var UNSELECT_THRESHOLD = 6;
  38819. var MIN_RESIZE_LINE_WIDTH = 6;
  38820. var MUTEX_RESOURCE_KEY = 'globalPan';
  38821. var DIRECTION_MAP = {
  38822. w: [0, 0],
  38823. e: [0, 1],
  38824. n: [1, 0],
  38825. s: [1, 1]
  38826. };
  38827. var CURSOR_MAP = {
  38828. w: 'ew',
  38829. e: 'ew',
  38830. n: 'ns',
  38831. s: 'ns',
  38832. ne: 'nesw',
  38833. sw: 'nesw',
  38834. nw: 'nwse',
  38835. se: 'nwse'
  38836. };
  38837. var DEFAULT_BRUSH_OPT = {
  38838. brushStyle: {
  38839. lineWidth: 2,
  38840. stroke: 'rgba(0,0,0,0.3)',
  38841. fill: 'rgba(0,0,0,0.1)'
  38842. },
  38843. transformable: true,
  38844. brushMode: 'single',
  38845. removeOnClick: false
  38846. };
  38847. var baseUID = 0;
  38848. /**
  38849. * @alias module:echarts/component/helper/BrushController
  38850. * @constructor
  38851. * @mixin {module:zrender/mixin/Eventful}
  38852. * @event module:echarts/component/helper/BrushController#brush
  38853. * params:
  38854. * areas: Array.<Array>, coord relates to container group,
  38855. * If no container specified, to global.
  38856. * opt {
  38857. * isEnd: boolean,
  38858. * removeOnClick: boolean
  38859. * }
  38860. *
  38861. * @param {module:zrender/zrender~ZRender} zr
  38862. */
  38863. function BrushController(zr) {
  38864. if (true) {
  38865. zrUtil.assert(zr);
  38866. }
  38867. Eventful.call(this);
  38868. /**
  38869. * @type {module:zrender/zrender~ZRender}
  38870. * @private
  38871. */
  38872. this._zr = zr;
  38873. /**
  38874. * @type {module:zrender/container/Group}
  38875. * @readOnly
  38876. */
  38877. this.group = new graphic.Group();
  38878. /**
  38879. * Only for drawing (after enabledBrush).
  38880. * 'line', 'rect', 'polygon' or false
  38881. * If passing false/null/undefined, disable brush.
  38882. * If passing 'auto', determined by panel.defaultBrushType
  38883. * @private
  38884. * @type {string}
  38885. */
  38886. this._brushType;
  38887. /**
  38888. * Only for drawing (after enabledBrush).
  38889. *
  38890. * @private
  38891. * @type {Object}
  38892. */
  38893. this._brushOption;
  38894. /**
  38895. * @private
  38896. * @type {Object}
  38897. */
  38898. this._panels;
  38899. /**
  38900. * @private
  38901. * @type {Array.<nubmer>}
  38902. */
  38903. this._track = [];
  38904. /**
  38905. * @private
  38906. * @type {boolean}
  38907. */
  38908. this._dragging;
  38909. /**
  38910. * @private
  38911. * @type {Array}
  38912. */
  38913. this._covers = [];
  38914. /**
  38915. * @private
  38916. * @type {moudule:zrender/container/Group}
  38917. */
  38918. this._creatingCover;
  38919. /**
  38920. * `true` means global panel
  38921. * @private
  38922. * @type {module:zrender/container/Group|boolean}
  38923. */
  38924. this._creatingPanel;
  38925. /**
  38926. * @private
  38927. * @type {boolean}
  38928. */
  38929. this._enableGlobalPan;
  38930. /**
  38931. * @private
  38932. * @type {boolean}
  38933. */
  38934. if (true) {
  38935. this._mounted;
  38936. }
  38937. /**
  38938. * @private
  38939. * @type {string}
  38940. */
  38941. this._uid = 'brushController_' + baseUID++;
  38942. /**
  38943. * @private
  38944. * @type {Object}
  38945. */
  38946. this._handlers = {};
  38947. each(mouseHandlers, function (handler, eventName) {
  38948. this._handlers[eventName] = zrUtil.bind(handler, this);
  38949. }, this);
  38950. }
  38951. BrushController.prototype = {
  38952. constructor: BrushController,
  38953. /**
  38954. * If set to null/undefined/false, select disabled.
  38955. * @param {Object} brushOption
  38956. * @param {string|boolean} brushOption.brushType 'line', 'rect', 'polygon' or false
  38957. * If passing false/null/undefined, disable brush.
  38958. * If passing 'auto', determined by panel.defaultBrushType.
  38959. * ('auto' can not be used in global panel)
  38960. * @param {number} [brushOption.brushMode='single'] 'single' or 'multiple'
  38961. * @param {boolean} [brushOption.transformable=true]
  38962. * @param {boolean} [brushOption.removeOnClick=false]
  38963. * @param {Object} [brushOption.brushStyle]
  38964. * @param {number} [brushOption.brushStyle.width]
  38965. * @param {number} [brushOption.brushStyle.lineWidth]
  38966. * @param {string} [brushOption.brushStyle.stroke]
  38967. * @param {string} [brushOption.brushStyle.fill]
  38968. * @param {number} [brushOption.z]
  38969. */
  38970. enableBrush: function (brushOption) {
  38971. if (true) {
  38972. zrUtil.assert(this._mounted);
  38973. }
  38974. this._brushType && doDisableBrush(this);
  38975. brushOption.brushType && doEnableBrush(this, brushOption);
  38976. return this;
  38977. },
  38978. /**
  38979. * @param {Array.<Object>} panelOpts If not pass, it is global brush.
  38980. * Each items: {
  38981. * panelId, // mandatory.
  38982. * clipPath, // mandatory. function.
  38983. * isTargetByCursor, // mandatory. function.
  38984. * defaultBrushType, // optional, only used when brushType is 'auto'.
  38985. * getLinearBrushOtherExtent, // optional. function.
  38986. * }
  38987. */
  38988. setPanels: function (panelOpts) {
  38989. if (panelOpts && panelOpts.length) {
  38990. var panels = this._panels = {};
  38991. zrUtil.each(panelOpts, function (panelOpts) {
  38992. panels[panelOpts.panelId] = zrUtil.clone(panelOpts);
  38993. });
  38994. }
  38995. else {
  38996. this._panels = null;
  38997. }
  38998. return this;
  38999. },
  39000. /**
  39001. * @param {Object} [opt]
  39002. * @return {boolean} [opt.enableGlobalPan=false]
  39003. */
  39004. mount: function (opt) {
  39005. opt = opt || {};
  39006. if (true) {
  39007. this._mounted = true; // should be at first.
  39008. }
  39009. this._enableGlobalPan = opt.enableGlobalPan;
  39010. var thisGroup = this.group;
  39011. this._zr.add(thisGroup);
  39012. thisGroup.attr({
  39013. position: opt.position || [0, 0],
  39014. rotation: opt.rotation || 0,
  39015. scale: opt.scale || [1, 1]
  39016. });
  39017. this._transform = thisGroup.getLocalTransform();
  39018. return this;
  39019. },
  39020. eachCover: function (cb, context) {
  39021. each(this._covers, cb, context);
  39022. },
  39023. /**
  39024. * Update covers.
  39025. * @param {Array.<Object>} brushOptionList Like:
  39026. * [
  39027. * {id: 'xx', brushType: 'line', range: [23, 44], brushStyle, transformable},
  39028. * {id: 'yy', brushType: 'rect', range: [[23, 44], [23, 54]]},
  39029. * ...
  39030. * ]
  39031. * `brushType` is required in each cover info. (can not be 'auto')
  39032. * `id` is not mandatory.
  39033. * `brushStyle`, `transformable` is not mandatory, use DEFAULT_BRUSH_OPT by default.
  39034. * If brushOptionList is null/undefined, all covers removed.
  39035. */
  39036. updateCovers: function (brushOptionList) {
  39037. if (true) {
  39038. zrUtil.assert(this._mounted);
  39039. }
  39040. brushOptionList = zrUtil.map(brushOptionList, function (brushOption) {
  39041. return zrUtil.merge(zrUtil.clone(DEFAULT_BRUSH_OPT), brushOption, true);
  39042. });
  39043. var tmpIdPrefix = '\0-brush-index-';
  39044. var oldCovers = this._covers;
  39045. var newCovers = this._covers = [];
  39046. var controller = this;
  39047. var creatingCover = this._creatingCover;
  39048. (new DataDiffer(oldCovers, brushOptionList, oldGetKey, getKey))
  39049. .add(addOrUpdate)
  39050. .update(addOrUpdate)
  39051. .remove(remove)
  39052. .execute();
  39053. return this;
  39054. function getKey(brushOption, index) {
  39055. return (brushOption.id != null ? brushOption.id : tmpIdPrefix + index)
  39056. + '-' + brushOption.brushType;
  39057. }
  39058. function oldGetKey(cover, index) {
  39059. return getKey(cover.__brushOption, index);
  39060. }
  39061. function addOrUpdate(newIndex, oldIndex) {
  39062. var newBrushOption = brushOptionList[newIndex];
  39063. // Consider setOption in event listener of brushSelect,
  39064. // where updating cover when creating should be forbiden.
  39065. if (oldIndex != null && oldCovers[oldIndex] === creatingCover) {
  39066. newCovers[newIndex] = oldCovers[oldIndex];
  39067. }
  39068. else {
  39069. var cover = newCovers[newIndex] = oldIndex != null
  39070. ? (
  39071. oldCovers[oldIndex].__brushOption = newBrushOption,
  39072. oldCovers[oldIndex]
  39073. )
  39074. : endCreating(controller, createCover(controller, newBrushOption));
  39075. updateCoverAfterCreation(controller, cover);
  39076. }
  39077. }
  39078. function remove(oldIndex) {
  39079. if (oldCovers[oldIndex] !== creatingCover) {
  39080. controller.group.remove(oldCovers[oldIndex]);
  39081. }
  39082. }
  39083. },
  39084. unmount: function () {
  39085. if (true) {
  39086. if (!this._mounted) {
  39087. return;
  39088. }
  39089. }
  39090. this.enableBrush(false);
  39091. // container may 'removeAll' outside.
  39092. clearCovers(this);
  39093. this._zr.remove(this.group);
  39094. if (true) {
  39095. this._mounted = false; // should be at last.
  39096. }
  39097. return this;
  39098. },
  39099. dispose: function () {
  39100. this.unmount();
  39101. this.off();
  39102. }
  39103. };
  39104. zrUtil.mixin(BrushController, Eventful);
  39105. function doEnableBrush(controller, brushOption) {
  39106. var zr = controller._zr;
  39107. // Consider roam, which takes globalPan too.
  39108. if (!controller._enableGlobalPan) {
  39109. interactionMutex.take(zr, MUTEX_RESOURCE_KEY, controller._uid);
  39110. }
  39111. each(controller._handlers, function (handler, eventName) {
  39112. zr.on(eventName, handler);
  39113. });
  39114. controller._brushType = brushOption.brushType;
  39115. controller._brushOption = zrUtil.merge(zrUtil.clone(DEFAULT_BRUSH_OPT), brushOption, true);
  39116. }
  39117. function doDisableBrush(controller) {
  39118. var zr = controller._zr;
  39119. interactionMutex.release(zr, MUTEX_RESOURCE_KEY, controller._uid);
  39120. each(controller._handlers, function (handler, eventName) {
  39121. zr.off(eventName, handler);
  39122. });
  39123. controller._brushType = controller._brushOption = null;
  39124. }
  39125. function createCover(controller, brushOption) {
  39126. var cover = coverRenderers[brushOption.brushType].createCover(controller, brushOption);
  39127. cover.__brushOption = brushOption;
  39128. updateZ(cover, brushOption);
  39129. controller.group.add(cover);
  39130. return cover;
  39131. }
  39132. function endCreating(controller, creatingCover) {
  39133. var coverRenderer = getCoverRenderer(creatingCover);
  39134. if (coverRenderer.endCreating) {
  39135. coverRenderer.endCreating(controller, creatingCover);
  39136. updateZ(creatingCover, creatingCover.__brushOption);
  39137. }
  39138. return creatingCover;
  39139. }
  39140. function updateCoverShape(controller, cover) {
  39141. var brushOption = cover.__brushOption;
  39142. getCoverRenderer(cover).updateCoverShape(
  39143. controller, cover, brushOption.range, brushOption
  39144. );
  39145. }
  39146. function updateZ(cover, brushOption) {
  39147. var z = brushOption.z;
  39148. z == null && (z = COVER_Z);
  39149. cover.traverse(function (el) {
  39150. el.z = z;
  39151. el.z2 = z; // Consider in given container.
  39152. });
  39153. }
  39154. function updateCoverAfterCreation(controller, cover) {
  39155. getCoverRenderer(cover).updateCommon(controller, cover);
  39156. updateCoverShape(controller, cover);
  39157. }
  39158. function getCoverRenderer(cover) {
  39159. return coverRenderers[cover.__brushOption.brushType];
  39160. }
  39161. // return target panel or `true` (means global panel)
  39162. function getPanelByPoint(controller, e, localCursorPoint) {
  39163. var panels = controller._panels;
  39164. if (!panels) {
  39165. return true; // Global panel
  39166. }
  39167. var panel;
  39168. var transform = controller._transform;
  39169. each(panels, function (pn) {
  39170. pn.isTargetByCursor(e, localCursorPoint, transform) && (panel = pn);
  39171. });
  39172. return panel;
  39173. }
  39174. // Return a panel or true
  39175. function getPanelByCover(controller, cover) {
  39176. var panels = controller._panels;
  39177. if (!panels) {
  39178. return true; // Global panel
  39179. }
  39180. var panelId = cover.__brushOption.panelId;
  39181. // User may give cover without coord sys info,
  39182. // which is then treated as global panel.
  39183. return panelId != null ? panels[panelId] : true;
  39184. }
  39185. function clearCovers(controller) {
  39186. var covers = controller._covers;
  39187. var originalLength = covers.length;
  39188. each(covers, function (cover) {
  39189. controller.group.remove(cover);
  39190. }, controller);
  39191. covers.length = 0;
  39192. return !!originalLength;
  39193. }
  39194. function trigger(controller, opt) {
  39195. var areas = map(controller._covers, function (cover) {
  39196. var brushOption = cover.__brushOption;
  39197. var range = zrUtil.clone(brushOption.range);
  39198. return {
  39199. brushType: brushOption.brushType,
  39200. panelId: brushOption.panelId,
  39201. range: range
  39202. };
  39203. });
  39204. controller.trigger('brush', areas, {
  39205. isEnd: !!opt.isEnd,
  39206. removeOnClick: !!opt.removeOnClick
  39207. });
  39208. }
  39209. function shouldShowCover(controller) {
  39210. var track = controller._track;
  39211. if (!track.length) {
  39212. return false;
  39213. }
  39214. var p2 = track[track.length - 1];
  39215. var p1 = track[0];
  39216. var dx = p2[0] - p1[0];
  39217. var dy = p2[1] - p1[1];
  39218. var dist = mathPow(dx * dx + dy * dy, 0.5);
  39219. return dist > UNSELECT_THRESHOLD;
  39220. }
  39221. function getTrackEnds(track) {
  39222. var tail = track.length - 1;
  39223. tail < 0 && (tail = 0);
  39224. return [track[0], track[tail]];
  39225. }
  39226. function createBaseRectCover(doDrift, controller, brushOption, edgeNames) {
  39227. var cover = new graphic.Group();
  39228. cover.add(new graphic.Rect({
  39229. name: 'main',
  39230. style: makeStyle(brushOption),
  39231. silent: true,
  39232. draggable: true,
  39233. cursor: 'move',
  39234. drift: curry(doDrift, controller, cover, 'nswe'),
  39235. ondragend: curry(trigger, controller, {isEnd: true})
  39236. }));
  39237. each(
  39238. edgeNames,
  39239. function (name) {
  39240. cover.add(new graphic.Rect({
  39241. name: name,
  39242. style: {opacity: 0},
  39243. draggable: true,
  39244. silent: true,
  39245. invisible: true,
  39246. drift: curry(doDrift, controller, cover, name),
  39247. ondragend: curry(trigger, controller, {isEnd: true})
  39248. }));
  39249. }
  39250. );
  39251. return cover;
  39252. }
  39253. function updateBaseRect(controller, cover, localRange, brushOption) {
  39254. var lineWidth = brushOption.brushStyle.lineWidth || 0;
  39255. var handleSize = mathMax(lineWidth, MIN_RESIZE_LINE_WIDTH);
  39256. var x = localRange[0][0];
  39257. var y = localRange[1][0];
  39258. var xa = x - lineWidth / 2;
  39259. var ya = y - lineWidth / 2;
  39260. var x2 = localRange[0][1];
  39261. var y2 = localRange[1][1];
  39262. var x2a = x2 - handleSize + lineWidth / 2;
  39263. var y2a = y2 - handleSize + lineWidth / 2;
  39264. var width = x2 - x;
  39265. var height = y2 - y;
  39266. var widtha = width + lineWidth;
  39267. var heighta = height + lineWidth;
  39268. updateRectShape(controller, cover, 'main', x, y, width, height);
  39269. if (brushOption.transformable) {
  39270. updateRectShape(controller, cover, 'w', xa, ya, handleSize, heighta);
  39271. updateRectShape(controller, cover, 'e', x2a, ya, handleSize, heighta);
  39272. updateRectShape(controller, cover, 'n', xa, ya, widtha, handleSize);
  39273. updateRectShape(controller, cover, 's', xa, y2a, widtha, handleSize);
  39274. updateRectShape(controller, cover, 'nw', xa, ya, handleSize, handleSize);
  39275. updateRectShape(controller, cover, 'ne', x2a, ya, handleSize, handleSize);
  39276. updateRectShape(controller, cover, 'sw', xa, y2a, handleSize, handleSize);
  39277. updateRectShape(controller, cover, 'se', x2a, y2a, handleSize, handleSize);
  39278. }
  39279. }
  39280. function updateCommon(controller, cover) {
  39281. var brushOption = cover.__brushOption;
  39282. var transformable = brushOption.transformable;
  39283. var mainEl = cover.childAt(0);
  39284. mainEl.useStyle(makeStyle(brushOption));
  39285. mainEl.attr({
  39286. silent: !transformable,
  39287. cursor: transformable ? 'move' : 'default'
  39288. });
  39289. each(
  39290. ['w', 'e', 'n', 's', 'se', 'sw', 'ne', 'nw'],
  39291. function (name) {
  39292. var el = cover.childOfName(name);
  39293. var globalDir = getGlobalDirection(controller, name);
  39294. el && el.attr({
  39295. silent: !transformable,
  39296. invisible: !transformable,
  39297. cursor: transformable ? CURSOR_MAP[globalDir] + '-resize' : null
  39298. });
  39299. }
  39300. );
  39301. }
  39302. function updateRectShape(controller, cover, name, x, y, w, h) {
  39303. var el = cover.childOfName(name);
  39304. el && el.setShape(pointsToRect(
  39305. clipByPanel(controller, cover, [[x, y], [x + w, y + h]])
  39306. ));
  39307. }
  39308. function makeStyle(brushOption) {
  39309. return zrUtil.defaults({strokeNoScale: true}, brushOption.brushStyle);
  39310. }
  39311. function formatRectRange(x, y, x2, y2) {
  39312. var min = [mathMin(x, x2), mathMin(y, y2)];
  39313. var max = [mathMax(x, x2), mathMax(y, y2)];
  39314. return [
  39315. [min[0], max[0]], // x range
  39316. [min[1], max[1]] // y range
  39317. ];
  39318. }
  39319. function getTransform(controller) {
  39320. return graphic.getTransform(controller.group);
  39321. }
  39322. function getGlobalDirection(controller, localDirection) {
  39323. if (localDirection.length > 1) {
  39324. localDirection = localDirection.split('');
  39325. var globalDir = [
  39326. getGlobalDirection(controller, localDirection[0]),
  39327. getGlobalDirection(controller, localDirection[1])
  39328. ];
  39329. (globalDir[0] === 'e' || globalDir[0] === 'w') && globalDir.reverse();
  39330. return globalDir.join('');
  39331. }
  39332. else {
  39333. var map = {w: 'left', e: 'right', n: 'top', s: 'bottom'};
  39334. var inverseMap = {left: 'w', right: 'e', top: 'n', bottom: 's'};
  39335. var globalDir = graphic.transformDirection(
  39336. map[localDirection], getTransform(controller)
  39337. );
  39338. return inverseMap[globalDir];
  39339. }
  39340. }
  39341. function driftRect(toRectRange, fromRectRange, controller, cover, name, dx, dy, e) {
  39342. var brushOption = cover.__brushOption;
  39343. var rectRange = toRectRange(brushOption.range);
  39344. var localDelta = toLocalDelta(controller, dx, dy);
  39345. each(name.split(''), function (namePart) {
  39346. var ind = DIRECTION_MAP[namePart];
  39347. rectRange[ind[0]][ind[1]] += localDelta[ind[0]];
  39348. });
  39349. brushOption.range = fromRectRange(formatRectRange(
  39350. rectRange[0][0], rectRange[1][0], rectRange[0][1], rectRange[1][1]
  39351. ));
  39352. updateCoverAfterCreation(controller, cover);
  39353. trigger(controller, {isEnd: false});
  39354. }
  39355. function driftPolygon(controller, cover, dx, dy, e) {
  39356. var range = cover.__brushOption.range;
  39357. var localDelta = toLocalDelta(controller, dx, dy);
  39358. each(range, function (point) {
  39359. point[0] += localDelta[0];
  39360. point[1] += localDelta[1];
  39361. });
  39362. updateCoverAfterCreation(controller, cover);
  39363. trigger(controller, {isEnd: false});
  39364. }
  39365. function toLocalDelta(controller, dx, dy) {
  39366. var thisGroup = controller.group;
  39367. var localD = thisGroup.transformCoordToLocal(dx, dy);
  39368. var localZero = thisGroup.transformCoordToLocal(0, 0);
  39369. return [localD[0] - localZero[0], localD[1] - localZero[1]];
  39370. }
  39371. function clipByPanel(controller, cover, data) {
  39372. var panel = getPanelByCover(controller, cover);
  39373. return (panel && panel !== true)
  39374. ? panel.clipPath(data, controller._transform)
  39375. : zrUtil.clone(data);
  39376. }
  39377. function pointsToRect(points) {
  39378. var xmin = mathMin(points[0][0], points[1][0]);
  39379. var ymin = mathMin(points[0][1], points[1][1]);
  39380. var xmax = mathMax(points[0][0], points[1][0]);
  39381. var ymax = mathMax(points[0][1], points[1][1]);
  39382. return {
  39383. x: xmin,
  39384. y: ymin,
  39385. width: xmax - xmin,
  39386. height: ymax - ymin
  39387. };
  39388. }
  39389. function resetCursor(controller, e, localCursorPoint) {
  39390. // Check active
  39391. if (!controller._brushType) {
  39392. return;
  39393. }
  39394. var zr = controller._zr;
  39395. var covers = controller._covers;
  39396. var currPanel = getPanelByPoint(controller, e, localCursorPoint);
  39397. // Check whether in covers.
  39398. if (!controller._dragging) {
  39399. for (var i = 0; i < covers.length; i++) {
  39400. var brushOption = covers[i].__brushOption;
  39401. if (currPanel
  39402. && (currPanel === true || brushOption.panelId === currPanel.panelId)
  39403. && coverRenderers[brushOption.brushType].contain(
  39404. covers[i], localCursorPoint[0], localCursorPoint[1]
  39405. )
  39406. ) {
  39407. // Use cursor style set on cover.
  39408. return;
  39409. }
  39410. }
  39411. }
  39412. currPanel && zr.setCursorStyle('crosshair');
  39413. }
  39414. function preventDefault(e) {
  39415. var rawE = e.event;
  39416. rawE.preventDefault && rawE.preventDefault();
  39417. }
  39418. function mainShapeContain(cover, x, y) {
  39419. return cover.childOfName('main').contain(x, y);
  39420. }
  39421. function updateCoverByMouse(controller, e, localCursorPoint, isEnd) {
  39422. var creatingCover = controller._creatingCover;
  39423. var panel = controller._creatingPanel;
  39424. var thisBrushOption = controller._brushOption;
  39425. var eventParams;
  39426. controller._track.push(localCursorPoint.slice());
  39427. if (shouldShowCover(controller) || creatingCover) {
  39428. if (panel && !creatingCover) {
  39429. thisBrushOption.brushMode === 'single' && clearCovers(controller);
  39430. var brushOption = zrUtil.clone(thisBrushOption);
  39431. brushOption.brushType = determineBrushType(brushOption.brushType, panel);
  39432. brushOption.panelId = panel === true ? null : panel.panelId;
  39433. creatingCover = controller._creatingCover = createCover(controller, brushOption);
  39434. controller._covers.push(creatingCover);
  39435. }
  39436. if (creatingCover) {
  39437. var coverRenderer = coverRenderers[determineBrushType(controller._brushType, panel)];
  39438. var coverBrushOption = creatingCover.__brushOption;
  39439. coverBrushOption.range = coverRenderer.getCreatingRange(
  39440. clipByPanel(controller, creatingCover, controller._track)
  39441. );
  39442. if (isEnd) {
  39443. endCreating(controller, creatingCover);
  39444. coverRenderer.updateCommon(controller, creatingCover);
  39445. }
  39446. updateCoverShape(controller, creatingCover);
  39447. eventParams = {isEnd: isEnd};
  39448. }
  39449. }
  39450. else if (
  39451. isEnd
  39452. && thisBrushOption.brushMode === 'single'
  39453. && thisBrushOption.removeOnClick
  39454. ) {
  39455. // Help user to remove covers easily, only by a tiny drag, in 'single' mode.
  39456. // But a single click do not clear covers, because user may have casual
  39457. // clicks (for example, click on other component and do not expect covers
  39458. // disappear).
  39459. // Only some cover removed, trigger action, but not every click trigger action.
  39460. if (getPanelByPoint(controller, e, localCursorPoint) && clearCovers(controller)) {
  39461. eventParams = {isEnd: isEnd, removeOnClick: true};
  39462. }
  39463. }
  39464. return eventParams;
  39465. }
  39466. function determineBrushType(brushType, panel) {
  39467. if (brushType === 'auto') {
  39468. if (true) {
  39469. zrUtil.assert(
  39470. panel && panel.defaultBrushType,
  39471. 'MUST have defaultBrushType when brushType is "atuo"'
  39472. );
  39473. }
  39474. return panel.defaultBrushType;
  39475. }
  39476. return brushType;
  39477. }
  39478. var mouseHandlers = {
  39479. mousedown: function (e) {
  39480. if (this._dragging) {
  39481. // In case some browser do not support globalOut,
  39482. // and release mose out side the browser.
  39483. handleDragEnd.call(this, e);
  39484. }
  39485. else if (!e.target || !e.target.draggable) {
  39486. preventDefault(e);
  39487. var localCursorPoint = this.group.transformCoordToLocal(e.offsetX, e.offsetY);
  39488. this._creatingCover = null;
  39489. var panel = this._creatingPanel = getPanelByPoint(this, e, localCursorPoint);
  39490. if (panel) {
  39491. this._dragging = true;
  39492. this._track = [localCursorPoint.slice()];
  39493. }
  39494. }
  39495. },
  39496. mousemove: function (e) {
  39497. var localCursorPoint = this.group.transformCoordToLocal(e.offsetX, e.offsetY);
  39498. resetCursor(this, e, localCursorPoint);
  39499. if (this._dragging) {
  39500. preventDefault(e);
  39501. var eventParams = updateCoverByMouse(this, e, localCursorPoint, false);
  39502. eventParams && trigger(this, eventParams);
  39503. }
  39504. },
  39505. mouseup: handleDragEnd //,
  39506. // FIXME
  39507. // in tooltip, globalout should not be triggered.
  39508. // globalout: handleDragEnd
  39509. };
  39510. function handleDragEnd(e) {
  39511. if (this._dragging) {
  39512. preventDefault(e);
  39513. var localCursorPoint = this.group.transformCoordToLocal(e.offsetX, e.offsetY);
  39514. var eventParams = updateCoverByMouse(this, e, localCursorPoint, true);
  39515. this._dragging = false;
  39516. this._track = [];
  39517. this._creatingCover = null;
  39518. // trigger event shoule be at final, after procedure will be nested.
  39519. eventParams && trigger(this, eventParams);
  39520. }
  39521. }
  39522. /**
  39523. * key: brushType
  39524. * @type {Object}
  39525. */
  39526. var coverRenderers = {
  39527. lineX: getLineRenderer(0),
  39528. lineY: getLineRenderer(1),
  39529. rect: {
  39530. createCover: function (controller, brushOption) {
  39531. return createBaseRectCover(
  39532. curry(
  39533. driftRect,
  39534. function (range) {
  39535. return range;
  39536. },
  39537. function (range) {
  39538. return range;
  39539. }
  39540. ),
  39541. controller,
  39542. brushOption,
  39543. ['w', 'e', 'n', 's', 'se', 'sw', 'ne', 'nw']
  39544. );
  39545. },
  39546. getCreatingRange: function (localTrack) {
  39547. var ends = getTrackEnds(localTrack);
  39548. return formatRectRange(ends[1][0], ends[1][1], ends[0][0], ends[0][1]);
  39549. },
  39550. updateCoverShape: function (controller, cover, localRange, brushOption) {
  39551. updateBaseRect(controller, cover, localRange, brushOption);
  39552. },
  39553. updateCommon: updateCommon,
  39554. contain: mainShapeContain
  39555. },
  39556. polygon: {
  39557. createCover: function (controller, brushOption) {
  39558. var cover = new graphic.Group();
  39559. // Do not use graphic.Polygon because graphic.Polyline do not close the
  39560. // border of the shape when drawing, which is a better experience for user.
  39561. cover.add(new graphic.Polyline({
  39562. name: 'main',
  39563. style: makeStyle(brushOption),
  39564. silent: true
  39565. }));
  39566. return cover;
  39567. },
  39568. getCreatingRange: function (localTrack) {
  39569. return localTrack;
  39570. },
  39571. endCreating: function (controller, cover) {
  39572. cover.remove(cover.childAt(0));
  39573. // Use graphic.Polygon close the shape.
  39574. cover.add(new graphic.Polygon({
  39575. name: 'main',
  39576. draggable: true,
  39577. drift: curry(driftPolygon, controller, cover),
  39578. ondragend: curry(trigger, controller, {isEnd: true})
  39579. }));
  39580. },
  39581. updateCoverShape: function (controller, cover, localRange, brushOption) {
  39582. cover.childAt(0).setShape({
  39583. points: clipByPanel(controller, cover, localRange)
  39584. });
  39585. },
  39586. updateCommon: updateCommon,
  39587. contain: mainShapeContain
  39588. }
  39589. };
  39590. function getLineRenderer(xyIndex) {
  39591. return {
  39592. createCover: function (controller, brushOption) {
  39593. return createBaseRectCover(
  39594. curry(
  39595. driftRect,
  39596. function (range) {
  39597. var rectRange = [range, [0, 100]];
  39598. xyIndex && rectRange.reverse();
  39599. return rectRange;
  39600. },
  39601. function (rectRange) {
  39602. return rectRange[xyIndex];
  39603. }
  39604. ),
  39605. controller,
  39606. brushOption,
  39607. [['w', 'e'], ['n', 's']][xyIndex]
  39608. );
  39609. },
  39610. getCreatingRange: function (localTrack) {
  39611. var ends = getTrackEnds(localTrack);
  39612. var min = mathMin(ends[0][xyIndex], ends[1][xyIndex]);
  39613. var max = mathMax(ends[0][xyIndex], ends[1][xyIndex]);
  39614. return [min, max];
  39615. },
  39616. updateCoverShape: function (controller, cover, localRange, brushOption) {
  39617. var otherExtent;
  39618. // If brushWidth not specified, fit the panel.
  39619. var panel = getPanelByCover(controller, cover);
  39620. if (panel !== true && panel.getLinearBrushOtherExtent) {
  39621. otherExtent = panel.getLinearBrushOtherExtent(
  39622. xyIndex, controller._transform
  39623. );
  39624. }
  39625. else {
  39626. var zr = controller._zr;
  39627. otherExtent = [0, [zr.getWidth(), zr.getHeight()][1 - xyIndex]];
  39628. }
  39629. var rectRange = [localRange, otherExtent];
  39630. xyIndex && rectRange.reverse();
  39631. updateBaseRect(controller, cover, rectRange, brushOption);
  39632. },
  39633. updateCommon: updateCommon,
  39634. contain: mainShapeContain
  39635. };
  39636. }
  39637. module.exports = BrushController;
  39638. /***/ },
  39639. /* 245 */
  39640. /***/ function(module, exports, __webpack_require__) {
  39641. var cursorHelper = __webpack_require__(185);
  39642. var BoundingRect = __webpack_require__(9);
  39643. var graphicUtil = __webpack_require__(18);
  39644. var helper = {};
  39645. helper.makeRectPanelClipPath = function (rect) {
  39646. rect = normalizeRect(rect);
  39647. return function (localPoints, transform) {
  39648. return graphicUtil.clipPointsByRect(localPoints, rect);
  39649. };
  39650. };
  39651. helper.makeLinearBrushOtherExtent = function (rect, specifiedXYIndex) {
  39652. rect = normalizeRect(rect);
  39653. return function (xyIndex) {
  39654. var idx = specifiedXYIndex != null ? specifiedXYIndex : xyIndex;
  39655. var brushWidth = idx ? rect.width : rect.height;
  39656. var base = idx ? rect.x : rect.y;
  39657. return [base, base + (brushWidth || 0)];
  39658. };
  39659. };
  39660. helper.makeRectIsTargetByCursor = function (rect, api, targetModel) {
  39661. rect = normalizeRect(rect);
  39662. return function (e, localCursorPoint, transform) {
  39663. return rect.contain(localCursorPoint[0], localCursorPoint[1])
  39664. && !cursorHelper.onIrrelevantElement(e, api, targetModel);
  39665. };
  39666. };
  39667. // Consider width/height is negative.
  39668. function normalizeRect(rect) {
  39669. return BoundingRect.create(rect);
  39670. }
  39671. module.exports = helper;
  39672. /***/ },
  39673. /* 246 */
  39674. /***/ function(module, exports, __webpack_require__) {
  39675. var zrUtil = __webpack_require__(4);
  39676. var modelUtil = __webpack_require__(5);
  39677. module.exports = function (option) {
  39678. createParallelIfNeeded(option);
  39679. mergeAxisOptionFromParallel(option);
  39680. };
  39681. /**
  39682. * Create a parallel coordinate if not exists.
  39683. * @inner
  39684. */
  39685. function createParallelIfNeeded(option) {
  39686. if (option.parallel) {
  39687. return;
  39688. }
  39689. var hasParallelSeries = false;
  39690. zrUtil.each(option.series, function (seriesOpt) {
  39691. if (seriesOpt && seriesOpt.type === 'parallel') {
  39692. hasParallelSeries = true;
  39693. }
  39694. });
  39695. if (hasParallelSeries) {
  39696. option.parallel = [{}];
  39697. }
  39698. }
  39699. /**
  39700. * Merge aixs definition from parallel option (if exists) to axis option.
  39701. * @inner
  39702. */
  39703. function mergeAxisOptionFromParallel(option) {
  39704. var axes = modelUtil.normalizeToArray(option.parallelAxis);
  39705. zrUtil.each(axes, function (axisOption) {
  39706. if (!zrUtil.isObject(axisOption)) {
  39707. return;
  39708. }
  39709. var parallelIndex = axisOption.parallelIndex || 0;
  39710. var parallelOption = modelUtil.normalizeToArray(option.parallel)[parallelIndex];
  39711. if (parallelOption && parallelOption.parallelAxisDefault) {
  39712. zrUtil.merge(axisOption, parallelOption.parallelAxisDefault, false);
  39713. }
  39714. });
  39715. }
  39716. /***/ },
  39717. /* 247 */
  39718. /***/ function(module, exports, __webpack_require__) {
  39719. var List = __webpack_require__(98);
  39720. var zrUtil = __webpack_require__(4);
  39721. var SeriesModel = __webpack_require__(78);
  39722. var completeDimensions = __webpack_require__(110);
  39723. module.exports = SeriesModel.extend({
  39724. type: 'series.parallel',
  39725. dependencies: ['parallel'],
  39726. visualColorAccessPath: 'lineStyle.normal.color',
  39727. getInitialData: function (option, ecModel) {
  39728. var parallelModel = ecModel.getComponent(
  39729. 'parallel', this.get('parallelIndex')
  39730. );
  39731. var parallelAxisIndices = parallelModel.parallelAxisIndex;
  39732. var rawData = option.data;
  39733. var modelDims = parallelModel.dimensions;
  39734. var dataDims = generateDataDims(modelDims, rawData);
  39735. var dataDimsInfo = zrUtil.map(dataDims, function (dim, dimIndex) {
  39736. var modelDimsIndex = zrUtil.indexOf(modelDims, dim);
  39737. var axisModel = modelDimsIndex >= 0 && ecModel.getComponent(
  39738. 'parallelAxis', parallelAxisIndices[modelDimsIndex]
  39739. );
  39740. if (axisModel && axisModel.get('type') === 'category') {
  39741. translateCategoryValue(axisModel, dim, rawData);
  39742. return {name: dim, type: 'ordinal'};
  39743. }
  39744. else if (modelDimsIndex < 0) {
  39745. return completeDimensions.guessOrdinal(rawData, dimIndex)
  39746. ? {name: dim, type: 'ordinal'}
  39747. : dim;
  39748. }
  39749. else {
  39750. return dim;
  39751. }
  39752. });
  39753. var list = new List(dataDimsInfo, this);
  39754. list.initData(rawData);
  39755. // Anication is forbiden in progressive data mode.
  39756. if (this.option.progressive) {
  39757. this.option.animation = false;
  39758. }
  39759. return list;
  39760. },
  39761. /**
  39762. * User can get data raw indices on 'axisAreaSelected' event received.
  39763. *
  39764. * @public
  39765. * @param {string} activeState 'active' or 'inactive' or 'normal'
  39766. * @return {Array.<number>} Raw indices
  39767. */
  39768. getRawIndicesByActiveState: function (activeState) {
  39769. var coordSys = this.coordinateSystem;
  39770. var data = this.getData();
  39771. var indices = [];
  39772. coordSys.eachActiveState(data, function (theActiveState, dataIndex) {
  39773. if (activeState === theActiveState) {
  39774. indices.push(data.getRawIndex(dataIndex));
  39775. }
  39776. });
  39777. return indices;
  39778. },
  39779. defaultOption: {
  39780. zlevel: 0, // 一级层叠
  39781. z: 2, // 二级层叠
  39782. coordinateSystem: 'parallel',
  39783. parallelIndex: 0,
  39784. label: {
  39785. normal: {
  39786. show: false
  39787. },
  39788. emphasis: {
  39789. show: false
  39790. }
  39791. },
  39792. inactiveOpacity: 0.05,
  39793. activeOpacity: 1,
  39794. lineStyle: {
  39795. normal: {
  39796. width: 1,
  39797. opacity: 0.45,
  39798. type: 'solid'
  39799. }
  39800. },
  39801. progressive: false, // 100
  39802. smooth: false,
  39803. animationEasing: 'linear'
  39804. }
  39805. });
  39806. function translateCategoryValue(axisModel, dim, rawData) {
  39807. var axisData = axisModel.get('data');
  39808. var numberDim = convertDimNameToNumber(dim);
  39809. if (axisData && axisData.length) {
  39810. zrUtil.each(rawData, function (dataItem) {
  39811. if (!dataItem) {
  39812. return;
  39813. }
  39814. // FIXME
  39815. // time consuming, should use hash?
  39816. var index = zrUtil.indexOf(axisData, dataItem[numberDim]);
  39817. dataItem[numberDim] = index >= 0 ? index : NaN;
  39818. });
  39819. }
  39820. // FIXME
  39821. // 如果没有设置axis data, 应自动算出,或者提示。
  39822. }
  39823. function convertDimNameToNumber(dimName) {
  39824. return +dimName.replace('dim', '');
  39825. }
  39826. function generateDataDims(modelDims, rawData) {
  39827. // parallelModel.dimension should not be regarded as data
  39828. // dimensions. Consider dimensions = ['dim4', 'dim2', 'dim6'];
  39829. // We detect max dim by parallelModel.dimensions and fist
  39830. // item in rawData arbitrarily.
  39831. var maxDimNum = 0;
  39832. zrUtil.each(modelDims, function (dimName) {
  39833. var numberDim = convertDimNameToNumber(dimName);
  39834. numberDim > maxDimNum && (maxDimNum = numberDim);
  39835. });
  39836. var firstItem = rawData[0];
  39837. if (firstItem && firstItem.length - 1 > maxDimNum) {
  39838. maxDimNum = firstItem.length - 1;
  39839. }
  39840. var dataDims = [];
  39841. for (var i = 0; i <= maxDimNum; i++) {
  39842. dataDims.push('dim' + i);
  39843. }
  39844. return dataDims;
  39845. }
  39846. /***/ },
  39847. /* 248 */
  39848. /***/ function(module, exports, __webpack_require__) {
  39849. var graphic = __webpack_require__(18);
  39850. var zrUtil = __webpack_require__(4);
  39851. var SMOOTH = 0.3;
  39852. var ParallelView = __webpack_require__(80).extend({
  39853. type: 'parallel',
  39854. init: function () {
  39855. /**
  39856. * @type {module:zrender/container/Group}
  39857. * @private
  39858. */
  39859. this._dataGroup = new graphic.Group();
  39860. this.group.add(this._dataGroup);
  39861. /**
  39862. * @type {module:echarts/data/List}
  39863. */
  39864. this._data;
  39865. },
  39866. /**
  39867. * @override
  39868. */
  39869. render: function (seriesModel, ecModel, api, payload) {
  39870. this._renderForNormal(seriesModel, payload);
  39871. // this[
  39872. // seriesModel.option.progressive
  39873. // ? '_renderForProgressive'
  39874. // : '_renderForNormal'
  39875. // ](seriesModel);
  39876. },
  39877. dispose: function () {},
  39878. /**
  39879. * @private
  39880. */
  39881. _renderForNormal: function (seriesModel, payload) {
  39882. var dataGroup = this._dataGroup;
  39883. var data = seriesModel.getData();
  39884. var oldData = this._data;
  39885. var coordSys = seriesModel.coordinateSystem;
  39886. var dimensions = coordSys.dimensions;
  39887. var option = seriesModel.option;
  39888. var smooth = option.smooth ? SMOOTH : null;
  39889. // Consider switch between progressive and not.
  39890. // oldData && oldData.__plProgressive && dataGroup.removeAll();
  39891. data.diff(oldData)
  39892. .add(add)
  39893. .update(update)
  39894. .remove(remove)
  39895. .execute();
  39896. // Update style
  39897. updateElCommon(data, smooth);
  39898. // First create
  39899. if (!this._data) {
  39900. var clipPath = createGridClipShape(
  39901. coordSys, seriesModel, function () {
  39902. // Callback will be invoked immediately if there is no animation
  39903. setTimeout(function () {
  39904. dataGroup.removeClipPath();
  39905. });
  39906. }
  39907. );
  39908. dataGroup.setClipPath(clipPath);
  39909. }
  39910. this._data = data;
  39911. function add(newDataIndex) {
  39912. addEl(data, dataGroup, newDataIndex, dimensions, coordSys, null, smooth);
  39913. }
  39914. function update(newDataIndex, oldDataIndex) {
  39915. var line = oldData.getItemGraphicEl(oldDataIndex);
  39916. var points = createLinePoints(data, newDataIndex, dimensions, coordSys);
  39917. data.setItemGraphicEl(newDataIndex, line);
  39918. var animationModel = (payload && payload.animation === false) ? null : seriesModel;
  39919. graphic.updateProps(line, {shape: {points: points}}, animationModel, newDataIndex);
  39920. }
  39921. function remove(oldDataIndex) {
  39922. var line = oldData.getItemGraphicEl(oldDataIndex);
  39923. dataGroup.remove(line);
  39924. }
  39925. },
  39926. /**
  39927. * @private
  39928. */
  39929. // _renderForProgressive: function (seriesModel) {
  39930. // var dataGroup = this._dataGroup;
  39931. // var data = seriesModel.getData();
  39932. // var oldData = this._data;
  39933. // var coordSys = seriesModel.coordinateSystem;
  39934. // var dimensions = coordSys.dimensions;
  39935. // var option = seriesModel.option;
  39936. // var progressive = option.progressive;
  39937. // var smooth = option.smooth ? SMOOTH : null;
  39938. // // In progressive animation is disabled, so use simple data diff,
  39939. // // which effects performance less.
  39940. // // (Typically performance for data with length 7000+ like:
  39941. // // simpleDiff: 60ms, addEl: 184ms,
  39942. // // in RMBP 2.4GHz intel i7, OSX 10.9 chrome 50.0.2661.102 (64-bit))
  39943. // if (simpleDiff(oldData, data, dimensions)) {
  39944. // dataGroup.removeAll();
  39945. // data.each(function (dataIndex) {
  39946. // addEl(data, dataGroup, dataIndex, dimensions, coordSys);
  39947. // });
  39948. // }
  39949. // updateElCommon(data, progressive, smooth);
  39950. // // Consider switch between progressive and not.
  39951. // data.__plProgressive = true;
  39952. // this._data = data;
  39953. // },
  39954. /**
  39955. * @override
  39956. */
  39957. remove: function () {
  39958. this._dataGroup && this._dataGroup.removeAll();
  39959. this._data = null;
  39960. }
  39961. });
  39962. function createGridClipShape(coordSys, seriesModel, cb) {
  39963. var parallelModel = coordSys.model;
  39964. var rect = coordSys.getRect();
  39965. var rectEl = new graphic.Rect({
  39966. shape: {
  39967. x: rect.x,
  39968. y: rect.y,
  39969. width: rect.width,
  39970. height: rect.height
  39971. }
  39972. });
  39973. var dim = parallelModel.get('layout') === 'horizontal' ? 'width' : 'height';
  39974. rectEl.setShape(dim, 0);
  39975. graphic.initProps(rectEl, {
  39976. shape: {
  39977. width: rect.width,
  39978. height: rect.height
  39979. }
  39980. }, seriesModel, cb);
  39981. return rectEl;
  39982. }
  39983. function createLinePoints(data, dataIndex, dimensions, coordSys) {
  39984. var points = [];
  39985. for (var i = 0; i < dimensions.length; i++) {
  39986. var dimName = dimensions[i];
  39987. var value = data.get(dimName, dataIndex);
  39988. if (!isEmptyValue(value, coordSys.getAxis(dimName).type)) {
  39989. points.push(coordSys.dataToPoint(value, dimName));
  39990. }
  39991. }
  39992. return points;
  39993. }
  39994. function addEl(data, dataGroup, dataIndex, dimensions, coordSys) {
  39995. var points = createLinePoints(data, dataIndex, dimensions, coordSys);
  39996. var line = new graphic.Polyline({
  39997. shape: {points: points},
  39998. silent: true,
  39999. z2: 10
  40000. });
  40001. dataGroup.add(line);
  40002. data.setItemGraphicEl(dataIndex, line);
  40003. }
  40004. function updateElCommon(data, smooth) {
  40005. var seriesStyleModel = data.hostModel.getModel('lineStyle.normal');
  40006. var lineStyle = seriesStyleModel.getLineStyle();
  40007. data.eachItemGraphicEl(function (line, dataIndex) {
  40008. if (data.hasItemOption) {
  40009. var itemModel = data.getItemModel(dataIndex);
  40010. var lineStyleModel = itemModel.getModel('lineStyle.normal', seriesStyleModel);
  40011. lineStyle = lineStyleModel.getLineStyle(['color', 'stroke']);
  40012. }
  40013. line.useStyle(zrUtil.extend(lineStyle, {
  40014. fill: null,
  40015. // lineStyle.color have been set to itemVisual in module:echarts/visual/seriesColor.
  40016. stroke: data.getItemVisual(dataIndex, 'color'),
  40017. // lineStyle.opacity have been set to itemVisual in parallelVisual.
  40018. opacity: data.getItemVisual(dataIndex, 'opacity')
  40019. }));
  40020. line.shape.smooth = smooth;
  40021. });
  40022. }
  40023. // function simpleDiff(oldData, newData, dimensions) {
  40024. // var oldLen;
  40025. // if (!oldData
  40026. // || !oldData.__plProgressive
  40027. // || (oldLen = oldData.count()) !== newData.count()
  40028. // ) {
  40029. // return true;
  40030. // }
  40031. // var dimLen = dimensions.length;
  40032. // for (var i = 0; i < oldLen; i++) {
  40033. // for (var j = 0; j < dimLen; j++) {
  40034. // if (oldData.get(dimensions[j], i) !== newData.get(dimensions[j], i)) {
  40035. // return true;
  40036. // }
  40037. // }
  40038. // }
  40039. // return false;
  40040. // }
  40041. // FIXME
  40042. // 公用方法?
  40043. function isEmptyValue(val, axisType) {
  40044. return axisType === 'category'
  40045. ? val == null
  40046. : (val == null || isNaN(val)); // axisType === 'value'
  40047. }
  40048. module.exports = ParallelView;
  40049. /***/ },
  40050. /* 249 */
  40051. /***/ function(module, exports) {
  40052. var opacityAccessPath = ['lineStyle', 'normal', 'opacity'];
  40053. module.exports = function (ecModel) {
  40054. ecModel.eachSeriesByType('parallel', function (seriesModel) {
  40055. var itemStyleModel = seriesModel.getModel('itemStyle.normal');
  40056. var lineStyleModel = seriesModel.getModel('lineStyle.normal');
  40057. var globalColors = ecModel.get('color');
  40058. var color = lineStyleModel.get('color')
  40059. || itemStyleModel.get('color')
  40060. || globalColors[seriesModel.seriesIndex % globalColors.length];
  40061. var inactiveOpacity = seriesModel.get('inactiveOpacity');
  40062. var activeOpacity = seriesModel.get('activeOpacity');
  40063. var lineStyle = seriesModel.getModel('lineStyle.normal').getLineStyle();
  40064. var coordSys = seriesModel.coordinateSystem;
  40065. var data = seriesModel.getData();
  40066. var opacityMap = {
  40067. normal: lineStyle.opacity,
  40068. active: activeOpacity,
  40069. inactive: inactiveOpacity
  40070. };
  40071. coordSys.eachActiveState(data, function (activeState, dataIndex) {
  40072. var itemModel = data.getItemModel(dataIndex);
  40073. var opacity = opacityMap[activeState];
  40074. if (activeState === 'normal') {
  40075. var itemOpacity = itemModel.get(opacityAccessPath, true);
  40076. itemOpacity != null && (opacity = itemOpacity);
  40077. }
  40078. data.setItemVisual(dataIndex, 'opacity', opacity);
  40079. });
  40080. data.setVisual('color', color);
  40081. });
  40082. };
  40083. /***/ },
  40084. /* 250 */
  40085. /***/ function(module, exports, __webpack_require__) {
  40086. var echarts = __webpack_require__(1);
  40087. __webpack_require__(251);
  40088. __webpack_require__(252);
  40089. echarts.registerLayout(__webpack_require__(253));
  40090. echarts.registerVisual(__webpack_require__(255));
  40091. /***/ },
  40092. /* 251 */
  40093. /***/ function(module, exports, __webpack_require__) {
  40094. /**
  40095. * @file Get initial data and define sankey view's series model
  40096. * @author Deqing Li(annong035@gmail.com)
  40097. */
  40098. var SeriesModel = __webpack_require__(78);
  40099. var createGraphFromNodeEdge = __webpack_require__(206);
  40100. var encodeHTML = __webpack_require__(6).encodeHTML;
  40101. var SankeySeries = SeriesModel.extend({
  40102. type: 'series.sankey',
  40103. layoutInfo: null,
  40104. /**
  40105. * Init a graph data structure from data in option series
  40106. *
  40107. * @param {Object} option the object used to config echarts view
  40108. * @return {module:echarts/data/List} storage initial data
  40109. */
  40110. getInitialData: function (option) {
  40111. var links = option.edges || option.links;
  40112. var nodes = option.data || option.nodes;
  40113. if (nodes && links) {
  40114. var graph = createGraphFromNodeEdge(nodes, links, this, true);
  40115. return graph.data;
  40116. }
  40117. },
  40118. /**
  40119. * Return the graphic data structure
  40120. *
  40121. * @return {module:echarts/data/Graph} graphic data structure
  40122. */
  40123. getGraph: function () {
  40124. return this.getData().graph;
  40125. },
  40126. /**
  40127. * Get edge data of graphic data structure
  40128. *
  40129. * @return {module:echarts/data/List} data structure of list
  40130. */
  40131. getEdgeData: function () {
  40132. return this.getGraph().edgeData;
  40133. },
  40134. /**
  40135. * @override
  40136. */
  40137. formatTooltip: function (dataIndex, multipleSeries, dataType) {
  40138. // dataType === 'node' or empty do not show tooltip by default
  40139. if (dataType === 'edge') {
  40140. var params = this.getDataParams(dataIndex, dataType);
  40141. var rawDataOpt = params.data;
  40142. var html = rawDataOpt.source + ' -- ' + rawDataOpt.target;
  40143. if (params.value) {
  40144. html += ' : ' + params.value;
  40145. }
  40146. return encodeHTML(html);
  40147. }
  40148. return SankeySeries.superCall(this, 'formatTooltip', dataIndex, multipleSeries);
  40149. },
  40150. defaultOption: {
  40151. zlevel: 0,
  40152. z: 2,
  40153. coordinateSystem: 'view',
  40154. layout: null,
  40155. // the position of the whole view
  40156. left: '5%',
  40157. top: '5%',
  40158. right: '20%',
  40159. bottom: '5%',
  40160. // the dx of the node
  40161. nodeWidth: 20,
  40162. // the vertical distance between two nodes
  40163. nodeGap: 8,
  40164. // the number of iterations to change the position of the node
  40165. layoutIterations: 32,
  40166. label: {
  40167. normal: {
  40168. show: true,
  40169. position: 'right',
  40170. textStyle: {
  40171. color: '#000',
  40172. fontSize: 12
  40173. }
  40174. },
  40175. emphasis: {
  40176. show: true
  40177. }
  40178. },
  40179. itemStyle: {
  40180. normal: {
  40181. borderWidth: 1,
  40182. borderColor: '#333'
  40183. }
  40184. },
  40185. lineStyle: {
  40186. normal: {
  40187. color: '#314656',
  40188. opacity: 0.2,
  40189. curveness: 0.5
  40190. },
  40191. emphasis: {
  40192. opacity: 0.6
  40193. }
  40194. },
  40195. animationEasing: 'linear',
  40196. animationDuration: 1000
  40197. }
  40198. });
  40199. module.exports = SankeySeries;
  40200. /***/ },
  40201. /* 252 */
  40202. /***/ function(module, exports, __webpack_require__) {
  40203. /**
  40204. * @file The file used to draw sankey view
  40205. * @author Deqing Li(annong035@gmail.com)
  40206. */
  40207. var graphic = __webpack_require__(18);
  40208. var zrUtil = __webpack_require__(4);
  40209. var SankeyShape = graphic.extendShape({
  40210. shape: {
  40211. x1: 0, y1: 0,
  40212. x2: 0, y2: 0,
  40213. cpx1: 0, cpy1: 0,
  40214. cpx2: 0, cpy2: 0,
  40215. extent: 0
  40216. },
  40217. buildPath: function (ctx, shape) {
  40218. var halfExtent = shape.extent / 2;
  40219. ctx.moveTo(shape.x1, shape.y1 - halfExtent);
  40220. ctx.bezierCurveTo(
  40221. shape.cpx1, shape.cpy1 - halfExtent,
  40222. shape.cpx2, shape.cpy2 - halfExtent,
  40223. shape.x2, shape.y2 - halfExtent
  40224. );
  40225. ctx.lineTo(shape.x2, shape.y2 + halfExtent);
  40226. ctx.bezierCurveTo(
  40227. shape.cpx2, shape.cpy2 + halfExtent,
  40228. shape.cpx1, shape.cpy1 + halfExtent,
  40229. shape.x1, shape.y1 + halfExtent
  40230. );
  40231. ctx.closePath();
  40232. }
  40233. });
  40234. module.exports = __webpack_require__(1).extendChartView({
  40235. type: 'sankey',
  40236. /**
  40237. * @private
  40238. * @type {module:echarts/chart/sankey/SankeySeries}
  40239. */
  40240. _model: null,
  40241. render: function (seriesModel, ecModel, api) {
  40242. var graph = seriesModel.getGraph();
  40243. var group = this.group;
  40244. var layoutInfo = seriesModel.layoutInfo;
  40245. var nodeData = seriesModel.getData();
  40246. var edgeData = seriesModel.getData('edge');
  40247. this._model = seriesModel;
  40248. group.removeAll();
  40249. group.position = [layoutInfo.x, layoutInfo.y];
  40250. // generate a bezire Curve for each edge
  40251. graph.eachEdge(function (edge) {
  40252. var curve = new SankeyShape();
  40253. curve.dataIndex = edge.dataIndex;
  40254. curve.seriesIndex = seriesModel.seriesIndex;
  40255. curve.dataType = 'edge';
  40256. var lineStyleModel = edge.getModel('lineStyle.normal');
  40257. var curvature = lineStyleModel.get('curveness');
  40258. var n1Layout = edge.node1.getLayout();
  40259. var n2Layout = edge.node2.getLayout();
  40260. var edgeLayout = edge.getLayout();
  40261. curve.shape.extent = Math.max(1, edgeLayout.dy);
  40262. var x1 = n1Layout.x + n1Layout.dx;
  40263. var y1 = n1Layout.y + edgeLayout.sy + edgeLayout.dy / 2;
  40264. var x2 = n2Layout.x;
  40265. var y2 = n2Layout.y + edgeLayout.ty + edgeLayout.dy / 2;
  40266. var cpx1 = x1 * (1 - curvature) + x2 * curvature;
  40267. var cpy1 = y1;
  40268. var cpx2 = x1 * curvature + x2 * (1 - curvature);
  40269. var cpy2 = y2;
  40270. curve.setShape({
  40271. x1: x1,
  40272. y1: y1,
  40273. x2: x2,
  40274. y2: y2,
  40275. cpx1: cpx1,
  40276. cpy1: cpy1,
  40277. cpx2: cpx2,
  40278. cpy2: cpy2
  40279. });
  40280. curve.setStyle(lineStyleModel.getItemStyle());
  40281. // Special color, use source node color or target node color
  40282. switch (curve.style.fill) {
  40283. case 'source':
  40284. curve.style.fill = edge.node1.getVisual('color');
  40285. break;
  40286. case 'target':
  40287. curve.style.fill = edge.node2.getVisual('color');
  40288. break;
  40289. }
  40290. graphic.setHoverStyle(curve, edge.getModel('lineStyle.emphasis').getItemStyle());
  40291. group.add(curve);
  40292. edgeData.setItemGraphicEl(edge.dataIndex, curve);
  40293. });
  40294. // generate a rect for each node
  40295. graph.eachNode(function (node) {
  40296. var layout = node.getLayout();
  40297. var itemModel = node.getModel();
  40298. var labelModel = itemModel.getModel('label.normal');
  40299. var textStyleModel = labelModel.getModel('textStyle');
  40300. var labelHoverModel = itemModel.getModel('label.emphasis');
  40301. var textStyleHoverModel = labelHoverModel.getModel('textStyle');
  40302. var rect = new graphic.Rect({
  40303. shape: {
  40304. x: layout.x,
  40305. y: layout.y,
  40306. width: node.getLayout().dx,
  40307. height: node.getLayout().dy
  40308. },
  40309. style: {
  40310. // Get formatted label in label.normal option
  40311. // Use node id if it is not specified
  40312. text: labelModel.get('show')
  40313. ? seriesModel.getFormattedLabel(node.dataIndex, 'normal') || node.id
  40314. // Use empty string to hide the label
  40315. : '',
  40316. textFont: textStyleModel.getFont(),
  40317. textFill: textStyleModel.getTextColor(),
  40318. textPosition: labelModel.get('position')
  40319. }
  40320. });
  40321. rect.setStyle(zrUtil.defaults(
  40322. {
  40323. fill: node.getVisual('color')
  40324. },
  40325. itemModel.getModel('itemStyle.normal').getItemStyle()
  40326. ));
  40327. graphic.setHoverStyle(rect, zrUtil.extend(
  40328. node.getModel('itemStyle.emphasis'),
  40329. {
  40330. text: labelHoverModel.get('show')
  40331. ? seriesModel.getFormattedLabel(node.dataIndex, 'emphasis') || node.id
  40332. : '',
  40333. textFont: textStyleHoverModel.getFont(),
  40334. textFill: textStyleHoverModel.getTextColor(),
  40335. textPosition: labelHoverModel.get('position')
  40336. }
  40337. ));
  40338. group.add(rect);
  40339. nodeData.setItemGraphicEl(node.dataIndex, rect);
  40340. rect.dataType = 'node';
  40341. });
  40342. if (!this._data && seriesModel.get('animation')) {
  40343. group.setClipPath(createGridClipShape(group.getBoundingRect(), seriesModel, function () {
  40344. group.removeClipPath();
  40345. }));
  40346. }
  40347. this._data = seriesModel.getData();
  40348. },
  40349. dispose: function () {}
  40350. });
  40351. // add animation to the view
  40352. function createGridClipShape(rect, seriesModel, cb) {
  40353. var rectEl = new graphic.Rect({
  40354. shape: {
  40355. x: rect.x - 10,
  40356. y: rect.y - 10,
  40357. width: 0,
  40358. height: rect.height + 20
  40359. }
  40360. });
  40361. graphic.initProps(rectEl, {
  40362. shape: {
  40363. width: rect.width + 20,
  40364. height: rect.height + 20
  40365. }
  40366. }, seriesModel, cb);
  40367. return rectEl;
  40368. }
  40369. /***/ },
  40370. /* 253 */
  40371. /***/ function(module, exports, __webpack_require__) {
  40372. /**
  40373. * @file The layout algorithm of sankey view
  40374. * @author Deqing Li(annong035@gmail.com)
  40375. */
  40376. var layout = __webpack_require__(71);
  40377. var nest = __webpack_require__(254);
  40378. var zrUtil = __webpack_require__(4);
  40379. module.exports = function (ecModel, api, payload) {
  40380. ecModel.eachSeriesByType('sankey', function (seriesModel) {
  40381. var nodeWidth = seriesModel.get('nodeWidth');
  40382. var nodeGap = seriesModel.get('nodeGap');
  40383. var layoutInfo = getViewRect(seriesModel, api);
  40384. seriesModel.layoutInfo = layoutInfo;
  40385. var width = layoutInfo.width;
  40386. var height = layoutInfo.height;
  40387. var graph = seriesModel.getGraph();
  40388. var nodes = graph.nodes;
  40389. var edges = graph.edges;
  40390. computeNodeValues(nodes);
  40391. var filteredNodes = zrUtil.filter(nodes, function (node) {
  40392. return node.getLayout().value === 0;
  40393. });
  40394. var iterations = filteredNodes.length !== 0
  40395. ? 0 : seriesModel.get('layoutIterations');
  40396. layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations);
  40397. });
  40398. };
  40399. /**
  40400. * Get the layout position of the whole view
  40401. *
  40402. * @param {module:echarts/model/Series} seriesModel the model object of sankey series
  40403. * @param {module:echarts/ExtensionAPI} api provide the API list that the developer can call
  40404. * @return {module:zrender/core/BoundingRect} size of rect to draw the sankey view
  40405. */
  40406. function getViewRect(seriesModel, api) {
  40407. return layout.getLayoutRect(
  40408. seriesModel.getBoxLayoutParams(), {
  40409. width: api.getWidth(),
  40410. height: api.getHeight()
  40411. }
  40412. );
  40413. }
  40414. function layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations) {
  40415. computeNodeBreadths(nodes, nodeWidth, width);
  40416. computeNodeDepths(nodes, edges, height, nodeGap, iterations);
  40417. computeEdgeDepths(nodes);
  40418. }
  40419. /**
  40420. * Compute the value of each node by summing the associated edge's value
  40421. *
  40422. * @param {module:echarts/data/Graph~Node} nodes node of sankey view
  40423. */
  40424. function computeNodeValues(nodes) {
  40425. zrUtil.each(nodes, function (node) {
  40426. var value1 = sum(node.outEdges, getEdgeValue);
  40427. var value2 = sum(node.inEdges, getEdgeValue);
  40428. var value = Math.max(value1, value2);
  40429. node.setLayout({value: value}, true);
  40430. });
  40431. }
  40432. /**
  40433. * Compute the x-position for each node
  40434. *
  40435. * @param {module:echarts/data/Graph~Node} nodes node of sankey view
  40436. * @param {number} nodeWidth the dx of the node
  40437. * @param {number} width the whole width of the area to draw the view
  40438. */
  40439. function computeNodeBreadths(nodes, nodeWidth, width) {
  40440. var remainNodes = nodes;
  40441. var nextNode = null;
  40442. var x = 0;
  40443. var kx = 0;
  40444. while (remainNodes.length) {
  40445. nextNode = [];
  40446. for (var i = 0, len = remainNodes.length; i < len; i++) {
  40447. var node = remainNodes[i];
  40448. node.setLayout({x: x}, true);
  40449. node.setLayout({dx: nodeWidth}, true);
  40450. for (var j = 0, lenj = node.outEdges.length; j < lenj; j++) {
  40451. nextNode.push(node.outEdges[j].node2);
  40452. }
  40453. }
  40454. remainNodes = nextNode;
  40455. ++x;
  40456. }
  40457. moveSinksRight(nodes, x);
  40458. kx = (width - nodeWidth) / (x - 1);
  40459. scaleNodeBreadths(nodes, kx);
  40460. }
  40461. /**
  40462. * All the node without outEgdes are assigned maximum x-position and
  40463. * be aligned in the last column.
  40464. *
  40465. * @param {module:echarts/data/Graph~Node} nodes node of sankey view
  40466. * @param {number} x value (x-1) use to assign to node without outEdges
  40467. * as x-position
  40468. */
  40469. function moveSinksRight(nodes, x) {
  40470. zrUtil.each(nodes, function (node) {
  40471. if (!node.outEdges.length) {
  40472. node.setLayout({x: x - 1}, true);
  40473. }
  40474. });
  40475. }
  40476. /**
  40477. * Scale node x-position to the width
  40478. *
  40479. * @param {module:echarts/data/Graph~Node} nodes node of sankey view
  40480. * @param {number} kx multiple used to scale nodes
  40481. */
  40482. function scaleNodeBreadths(nodes, kx) {
  40483. zrUtil.each(nodes, function (node) {
  40484. var nodeX = node.getLayout().x * kx;
  40485. node.setLayout({x: nodeX}, true);
  40486. });
  40487. }
  40488. /**
  40489. * Using Gauss-Seidel iterations method to compute the node depth(y-position)
  40490. *
  40491. * @param {module:echarts/data/Graph~Node} nodes node of sankey view
  40492. * @param {module:echarts/data/Graph~Edge} edges edge of sankey view
  40493. * @param {number} height the whole height of the area to draw the view
  40494. * @param {numbber} nodeGap the vertical distance between two nodes
  40495. * in the same column.
  40496. * @param {number} iterations the number of iterations for the algorithm
  40497. */
  40498. function computeNodeDepths(nodes, edges, height, nodeGap, iterations) {
  40499. var nodesByBreadth = nest()
  40500. .key(function (d) {
  40501. return d.getLayout().x;
  40502. })
  40503. .sortKeys(ascending)
  40504. .entries(nodes)
  40505. .map(function (d) {
  40506. return d.values;
  40507. });
  40508. initializeNodeDepth(nodes, nodesByBreadth, edges, height, nodeGap);
  40509. resolveCollisions(nodesByBreadth, nodeGap, height);
  40510. for (var alpha = 1; iterations > 0; iterations--) {
  40511. // 0.99 is a experience parameter, ensure that each iterations of
  40512. // changes as small as possible.
  40513. alpha *= 0.99;
  40514. relaxRightToLeft(nodesByBreadth, alpha);
  40515. resolveCollisions(nodesByBreadth, nodeGap, height);
  40516. relaxLeftToRight(nodesByBreadth, alpha);
  40517. resolveCollisions(nodesByBreadth, nodeGap, height);
  40518. }
  40519. }
  40520. /**
  40521. * Compute the original y-position for each node
  40522. *
  40523. * @param {module:echarts/data/Graph~Node} nodes node of sankey view
  40524. * @param {Array.<Array.<module:echarts/data/Graph~Node>>} nodesByBreadth
  40525. * group by the array of all sankey nodes based on the nodes x-position.
  40526. * @param {module:echarts/data/Graph~Edge} edges edge of sankey view
  40527. * @param {number} height the whole height of the area to draw the view
  40528. * @param {number} nodeGap the vertical distance between two nodes
  40529. */
  40530. function initializeNodeDepth(nodes, nodesByBreadth, edges, height, nodeGap) {
  40531. var kyArray = [];
  40532. zrUtil.each(nodesByBreadth, function (nodes) {
  40533. var n = nodes.length;
  40534. var sum = 0;
  40535. zrUtil.each(nodes, function (node) {
  40536. sum += node.getLayout().value;
  40537. });
  40538. var ky = (height - (n - 1) * nodeGap) / sum;
  40539. kyArray.push(ky);
  40540. });
  40541. kyArray.sort(function (a, b) {
  40542. return a - b;
  40543. });
  40544. var ky0 = kyArray[0];
  40545. zrUtil.each(nodesByBreadth, function (nodes) {
  40546. zrUtil.each(nodes, function (node, i) {
  40547. node.setLayout({y: i}, true);
  40548. var nodeDy = node.getLayout().value * ky0;
  40549. node.setLayout({dy: nodeDy}, true);
  40550. });
  40551. });
  40552. zrUtil.each(edges, function (edge) {
  40553. var edgeDy = +edge.getValue() * ky0;
  40554. edge.setLayout({dy: edgeDy}, true);
  40555. });
  40556. }
  40557. /**
  40558. * Resolve the collision of initialized depth (y-position)
  40559. *
  40560. * @param {Array.<Array.<module:echarts/data/Graph~Node>>} nodesByBreadth
  40561. * group by the array of all sankey nodes based on the nodes x-position.
  40562. * @param {number} nodeGap the vertical distance between two nodes
  40563. * @param {number} height the whole height of the area to draw the view
  40564. */
  40565. function resolveCollisions(nodesByBreadth, nodeGap, height) {
  40566. zrUtil.each(nodesByBreadth, function (nodes) {
  40567. var node;
  40568. var dy;
  40569. var y0 = 0;
  40570. var n = nodes.length;
  40571. var i;
  40572. nodes.sort(ascendingDepth);
  40573. for (i = 0; i < n; i++) {
  40574. node = nodes[i];
  40575. dy = y0 - node.getLayout().y;
  40576. if (dy > 0) {
  40577. var nodeY = node.getLayout().y + dy;
  40578. node.setLayout({y: nodeY}, true);
  40579. }
  40580. y0 = node.getLayout().y + node.getLayout().dy + nodeGap;
  40581. }
  40582. // if the bottommost node goes outside the bounds, push it back up
  40583. dy = y0 - nodeGap - height;
  40584. if (dy > 0) {
  40585. var nodeY = node.getLayout().y - dy;
  40586. node.setLayout({y: nodeY}, true);
  40587. y0 = node.getLayout().y;
  40588. for (i = n - 2; i >= 0; --i) {
  40589. node = nodes[i];
  40590. dy = node.getLayout().y + node.getLayout().dy + nodeGap - y0;
  40591. if (dy > 0) {
  40592. nodeY = node.getLayout().y - dy;
  40593. node.setLayout({y: nodeY}, true);
  40594. }
  40595. y0 = node.getLayout().y;
  40596. }
  40597. }
  40598. });
  40599. }
  40600. /**
  40601. * Change the y-position of the nodes, except most the right side nodes
  40602. *
  40603. * @param {Array.<Array.<module:echarts/data/Graph~Node>>} nodesByBreadth
  40604. * group by the array of all sankey nodes based on the node x-position.
  40605. * @param {number} alpha parameter used to adjust the nodes y-position
  40606. */
  40607. function relaxRightToLeft(nodesByBreadth, alpha) {
  40608. zrUtil.each(nodesByBreadth.slice().reverse(), function (nodes) {
  40609. zrUtil.each(nodes, function (node) {
  40610. if (node.outEdges.length) {
  40611. var y = sum(node.outEdges, weightedTarget) / sum(node.outEdges, getEdgeValue);
  40612. var nodeY = node.getLayout().y + (y - center(node)) * alpha;
  40613. node.setLayout({y: nodeY}, true);
  40614. }
  40615. });
  40616. });
  40617. }
  40618. function weightedTarget(edge) {
  40619. return center(edge.node2) * edge.getValue();
  40620. }
  40621. /**
  40622. * Change the y-position of the nodes, except most the left side nodes
  40623. *
  40624. * @param {Array.<Array.<module:echarts/data/Graph~Node>>} nodesByBreadth
  40625. * group by the array of all sankey nodes based on the node x-position.
  40626. * @param {number} alpha parameter used to adjust the nodes y-position
  40627. */
  40628. function relaxLeftToRight(nodesByBreadth, alpha) {
  40629. zrUtil.each(nodesByBreadth, function (nodes) {
  40630. zrUtil.each(nodes, function (node) {
  40631. if (node.inEdges.length) {
  40632. var y = sum(node.inEdges, weightedSource) / sum(node.inEdges, getEdgeValue);
  40633. var nodeY = node.getLayout().y + (y - center(node)) * alpha;
  40634. node.setLayout({y: nodeY}, true);
  40635. }
  40636. });
  40637. });
  40638. }
  40639. function weightedSource(edge) {
  40640. return center(edge.node1) * edge.getValue();
  40641. }
  40642. /**
  40643. * Compute the depth(y-position) of each edge
  40644. *
  40645. * @param {module:echarts/data/Graph~Node} nodes node of sankey view
  40646. */
  40647. function computeEdgeDepths(nodes) {
  40648. zrUtil.each(nodes, function (node) {
  40649. node.outEdges.sort(ascendingTargetDepth);
  40650. node.inEdges.sort(ascendingSourceDepth);
  40651. });
  40652. zrUtil.each(nodes, function (node) {
  40653. var sy = 0;
  40654. var ty = 0;
  40655. zrUtil.each(node.outEdges, function (edge) {
  40656. edge.setLayout({sy: sy}, true);
  40657. sy += edge.getLayout().dy;
  40658. });
  40659. zrUtil.each(node.inEdges, function (edge) {
  40660. edge.setLayout({ty: ty}, true);
  40661. ty += edge.getLayout().dy;
  40662. });
  40663. });
  40664. }
  40665. function ascendingTargetDepth(a, b) {
  40666. return a.node2.getLayout().y - b.node2.getLayout().y;
  40667. }
  40668. function ascendingSourceDepth(a, b) {
  40669. return a.node1.getLayout().y - b.node1.getLayout().y;
  40670. }
  40671. function sum(array, f) {
  40672. var sum = 0;
  40673. var len = array.length;
  40674. var i = -1;
  40675. while (++i < len) {
  40676. var value = +f.call(array, array[i], i);
  40677. if (!isNaN(value)) {
  40678. sum += value;
  40679. }
  40680. }
  40681. return sum;
  40682. }
  40683. function center(node) {
  40684. return node.getLayout().y + node.getLayout().dy / 2;
  40685. }
  40686. function ascendingDepth(a, b) {
  40687. return a.getLayout().y - b.getLayout().y;
  40688. }
  40689. function ascending(a, b) {
  40690. return a < b ? -1 : a > b ? 1 : a === b ? 0 : NaN;
  40691. }
  40692. function getEdgeValue(edge) {
  40693. return edge.getValue();
  40694. }
  40695. /***/ },
  40696. /* 254 */
  40697. /***/ function(module, exports, __webpack_require__) {
  40698. var zrUtil = __webpack_require__(4);
  40699. /**
  40700. * nest helper used to group by the array.
  40701. * can specified the keys and sort the keys.
  40702. */
  40703. function nest() {
  40704. var keysFunction = [];
  40705. var sortKeysFunction = [];
  40706. /**
  40707. * map an Array into the mapObject.
  40708. * @param {Array} array
  40709. * @param {number} depth
  40710. */
  40711. function map(array, depth) {
  40712. if (depth >= keysFunction.length) {
  40713. return array;
  40714. }
  40715. var i = -1;
  40716. var n = array.length;
  40717. var keyFunction = keysFunction[depth++];
  40718. var mapObject = {};
  40719. var valuesByKey = {};
  40720. while (++i < n) {
  40721. var keyValue = keyFunction(array[i]);
  40722. var values = valuesByKey[keyValue];
  40723. if (values) {
  40724. values.push(array[i]);
  40725. }
  40726. else {
  40727. valuesByKey[keyValue] = [array[i]];
  40728. }
  40729. }
  40730. zrUtil.each(valuesByKey, function (value, key) {
  40731. mapObject[key] = map(value, depth);
  40732. });
  40733. return mapObject;
  40734. }
  40735. /**
  40736. * transform the Map Object to multidimensional Array
  40737. * @param {Object} map
  40738. * @param {number} depth
  40739. */
  40740. function entriesMap(mapObject, depth) {
  40741. if (depth >= keysFunction.length) {
  40742. return mapObject;
  40743. }
  40744. var array = [];
  40745. var sortKeyFunction = sortKeysFunction[depth++];
  40746. zrUtil.each(mapObject, function (value, key) {
  40747. array.push({
  40748. key: key, values: entriesMap(value, depth)
  40749. });
  40750. });
  40751. if (sortKeyFunction) {
  40752. return array.sort(function (a, b) {
  40753. return sortKeyFunction(a.key, b.key);
  40754. });
  40755. }
  40756. else {
  40757. return array;
  40758. }
  40759. }
  40760. return {
  40761. /**
  40762. * specified the key to groupby the arrays.
  40763. * users can specified one more keys.
  40764. * @param {Function} d
  40765. */
  40766. key: function (d) {
  40767. keysFunction.push(d);
  40768. return this;
  40769. },
  40770. /**
  40771. * specified the comparator to sort the keys
  40772. * @param {Function} order
  40773. */
  40774. sortKeys: function (order) {
  40775. sortKeysFunction[keysFunction.length - 1] = order;
  40776. return this;
  40777. },
  40778. /**
  40779. * the array to be grouped by.
  40780. * @param {Array} array
  40781. */
  40782. entries: function (array) {
  40783. return entriesMap(map(array, 0), 0);
  40784. }
  40785. };
  40786. }
  40787. module.exports = nest;
  40788. /***/ },
  40789. /* 255 */
  40790. /***/ function(module, exports, __webpack_require__) {
  40791. /**
  40792. * @file Visual encoding for sankey view
  40793. * @author Deqing Li(annong035@gmail.com)
  40794. */
  40795. var VisualMapping = __webpack_require__(202);
  40796. var zrUtil = __webpack_require__(4);
  40797. module.exports = function (ecModel, payload) {
  40798. ecModel.eachSeriesByType('sankey', function (seriesModel) {
  40799. var graph = seriesModel.getGraph();
  40800. var nodes = graph.nodes;
  40801. nodes.sort(function (a, b) {
  40802. return a.getLayout().value - b.getLayout().value;
  40803. });
  40804. var minValue = nodes[0].getLayout().value;
  40805. var maxValue = nodes[nodes.length - 1].getLayout().value;
  40806. zrUtil.each(nodes, function (node) {
  40807. var mapping = new VisualMapping({
  40808. type: 'color',
  40809. mappingMethod: 'linear',
  40810. dataExtent: [minValue, maxValue],
  40811. visual: seriesModel.get('color')
  40812. });
  40813. var mapValueToColor = mapping.mapValueToVisual(node.getLayout().value);
  40814. node.setVisual('color', mapValueToColor);
  40815. // If set itemStyle.normal.color
  40816. var itemModel = node.getModel();
  40817. var customColor = itemModel.get('itemStyle.normal.color');
  40818. if (customColor != null) {
  40819. node.setVisual('color', customColor);
  40820. }
  40821. });
  40822. });
  40823. };
  40824. /***/ },
  40825. /* 256 */
  40826. /***/ function(module, exports, __webpack_require__) {
  40827. var echarts = __webpack_require__(1);
  40828. __webpack_require__(257);
  40829. __webpack_require__(260);
  40830. echarts.registerVisual(__webpack_require__(261));
  40831. echarts.registerLayout(__webpack_require__(262));
  40832. /***/ },
  40833. /* 257 */
  40834. /***/ function(module, exports, __webpack_require__) {
  40835. 'use strict';
  40836. var zrUtil = __webpack_require__(4);
  40837. var SeriesModel = __webpack_require__(78);
  40838. var whiskerBoxCommon = __webpack_require__(258);
  40839. var BoxplotSeries = SeriesModel.extend({
  40840. type: 'series.boxplot',
  40841. dependencies: ['xAxis', 'yAxis', 'grid'],
  40842. // TODO
  40843. // box width represents group size, so dimension should have 'size'.
  40844. /**
  40845. * @see <https://en.wikipedia.org/wiki/Box_plot>
  40846. * The meanings of 'min' and 'max' depend on user,
  40847. * and echarts do not need to know it.
  40848. * @readOnly
  40849. */
  40850. defaultValueDimensions: ['min', 'Q1', 'median', 'Q3', 'max'],
  40851. /**
  40852. * @type {Array.<string>}
  40853. * @readOnly
  40854. */
  40855. dimensions: null,
  40856. /**
  40857. * @override
  40858. */
  40859. defaultOption: {
  40860. zlevel: 0, // 一级层叠
  40861. z: 2, // 二级层叠
  40862. coordinateSystem: 'cartesian2d',
  40863. legendHoverLink: true,
  40864. hoverAnimation: true,
  40865. // xAxisIndex: 0,
  40866. // yAxisIndex: 0,
  40867. layout: null, // 'horizontal' or 'vertical'
  40868. boxWidth: [7, 50], // [min, max] can be percent of band width.
  40869. itemStyle: {
  40870. normal: {
  40871. color: '#fff',
  40872. borderWidth: 1
  40873. },
  40874. emphasis: {
  40875. borderWidth: 2,
  40876. shadowBlur: 5,
  40877. shadowOffsetX: 2,
  40878. shadowOffsetY: 2,
  40879. shadowColor: 'rgba(0,0,0,0.4)'
  40880. }
  40881. },
  40882. animationEasing: 'elasticOut',
  40883. animationDuration: 800
  40884. }
  40885. });
  40886. zrUtil.mixin(BoxplotSeries, whiskerBoxCommon.seriesModelMixin, true);
  40887. module.exports = BoxplotSeries;
  40888. /***/ },
  40889. /* 258 */
  40890. /***/ function(module, exports, __webpack_require__) {
  40891. 'use strict';
  40892. var List = __webpack_require__(98);
  40893. var completeDimensions = __webpack_require__(110);
  40894. var WhiskerBoxDraw = __webpack_require__(259);
  40895. var zrUtil = __webpack_require__(4);
  40896. var seriesModelMixin = {
  40897. /**
  40898. * @private
  40899. * @type {string}
  40900. */
  40901. _baseAxisDim: null,
  40902. /**
  40903. * @override
  40904. */
  40905. getInitialData: function (option, ecModel) {
  40906. // When both types of xAxis and yAxis are 'value', layout is
  40907. // needed to be specified by user. Otherwise, layout can be
  40908. // judged by which axis is category.
  40909. var categories;
  40910. var xAxisModel = ecModel.getComponent('xAxis', this.get('xAxisIndex'));
  40911. var yAxisModel = ecModel.getComponent('yAxis', this.get('yAxisIndex'));
  40912. var xAxisType = xAxisModel.get('type');
  40913. var yAxisType = yAxisModel.get('type');
  40914. var addOrdinal;
  40915. // FIXME
  40916. // 考虑时间轴
  40917. if (xAxisType === 'category') {
  40918. option.layout = 'horizontal';
  40919. categories = xAxisModel.getCategories();
  40920. addOrdinal = true;
  40921. }
  40922. else if (yAxisType === 'category') {
  40923. option.layout = 'vertical';
  40924. categories = yAxisModel.getCategories();
  40925. addOrdinal = true;
  40926. }
  40927. else {
  40928. option.layout = option.layout || 'horizontal';
  40929. }
  40930. var coordDims = ['x', 'y'];
  40931. var baseAxisDimIndex = option.layout === 'horizontal' ? 0 : 1;
  40932. var baseAxisDim = this._baseAxisDim = coordDims[baseAxisDimIndex];
  40933. var otherAxisDim = coordDims[1 - baseAxisDimIndex];
  40934. var data = option.data;
  40935. addOrdinal && zrUtil.each(data, function (item, index) {
  40936. zrUtil.isArray(item) && item.unshift(index);
  40937. });
  40938. var dimensions = [{
  40939. name: baseAxisDim,
  40940. otherDims: {
  40941. tooltip: false
  40942. },
  40943. dimsDef: ['base']
  40944. }, {
  40945. name: otherAxisDim,
  40946. dimsDef: this.defaultValueDimensions.slice()
  40947. }];
  40948. dimensions = completeDimensions(dimensions, data, {
  40949. encodeDef: this.get('encode'),
  40950. dimsDef: this.get('dimensions')
  40951. });
  40952. var list = new List(dimensions, this);
  40953. list.initData(data, categories ? categories.slice() : null);
  40954. return list;
  40955. },
  40956. /**
  40957. * If horizontal, base axis is x, otherwise y.
  40958. * @override
  40959. */
  40960. getBaseAxis: function () {
  40961. var dim = this._baseAxisDim;
  40962. return this.ecModel.getComponent(dim + 'Axis', this.get(dim + 'AxisIndex')).axis;
  40963. }
  40964. };
  40965. var viewMixin = {
  40966. init: function () {
  40967. /**
  40968. * Old data.
  40969. * @private
  40970. * @type {module:echarts/chart/helper/WhiskerBoxDraw}
  40971. */
  40972. var whiskerBoxDraw = this._whiskerBoxDraw = new WhiskerBoxDraw(
  40973. this.getStyleUpdater()
  40974. );
  40975. this.group.add(whiskerBoxDraw.group);
  40976. },
  40977. render: function (seriesModel, ecModel, api) {
  40978. this._whiskerBoxDraw.updateData(seriesModel.getData());
  40979. },
  40980. remove: function (ecModel) {
  40981. this._whiskerBoxDraw.remove();
  40982. }
  40983. };
  40984. module.exports = {
  40985. seriesModelMixin: seriesModelMixin,
  40986. viewMixin: viewMixin
  40987. };
  40988. /***/ },
  40989. /* 259 */
  40990. /***/ function(module, exports, __webpack_require__) {
  40991. /**
  40992. * @module echarts/chart/helper/Symbol
  40993. */
  40994. var zrUtil = __webpack_require__(4);
  40995. var graphic = __webpack_require__(18);
  40996. var Path = __webpack_require__(20);
  40997. var WhiskerPath = Path.extend({
  40998. type: 'whiskerInBox',
  40999. shape: {},
  41000. buildPath: function (ctx, shape) {
  41001. for (var i in shape) {
  41002. if (shape.hasOwnProperty(i) && i.indexOf('ends') === 0) {
  41003. var pts = shape[i];
  41004. ctx.moveTo(pts[0][0], pts[0][1]);
  41005. ctx.lineTo(pts[1][0], pts[1][1]);
  41006. }
  41007. }
  41008. }
  41009. });
  41010. /**
  41011. * @constructor
  41012. * @alias {module:echarts/chart/helper/WhiskerBox}
  41013. * @param {module:echarts/data/List} data
  41014. * @param {number} idx
  41015. * @param {Function} styleUpdater
  41016. * @param {boolean} isInit
  41017. * @extends {module:zrender/graphic/Group}
  41018. */
  41019. function WhiskerBox(data, idx, styleUpdater, isInit) {
  41020. graphic.Group.call(this);
  41021. /**
  41022. * @type {number}
  41023. * @readOnly
  41024. */
  41025. this.bodyIndex;
  41026. /**
  41027. * @type {number}
  41028. * @readOnly
  41029. */
  41030. this.whiskerIndex;
  41031. /**
  41032. * @type {Function}
  41033. */
  41034. this.styleUpdater = styleUpdater;
  41035. this._createContent(data, idx, isInit);
  41036. this.updateData(data, idx, isInit);
  41037. /**
  41038. * Last series model.
  41039. * @type {module:echarts/model/Series}
  41040. */
  41041. this._seriesModel;
  41042. }
  41043. var whiskerBoxProto = WhiskerBox.prototype;
  41044. whiskerBoxProto._createContent = function (data, idx, isInit) {
  41045. var itemLayout = data.getItemLayout(idx);
  41046. var constDim = itemLayout.chartLayout === 'horizontal' ? 1 : 0;
  41047. var count = 0;
  41048. // Whisker element.
  41049. this.add(new graphic.Polygon({
  41050. shape: {
  41051. points: isInit
  41052. ? transInit(itemLayout.bodyEnds, constDim, itemLayout)
  41053. : itemLayout.bodyEnds
  41054. },
  41055. style: {strokeNoScale: true},
  41056. z2: 100
  41057. }));
  41058. this.bodyIndex = count++;
  41059. // Box element.
  41060. var whiskerEnds = zrUtil.map(itemLayout.whiskerEnds, function (ends) {
  41061. return isInit ? transInit(ends, constDim, itemLayout) : ends;
  41062. });
  41063. this.add(new WhiskerPath({
  41064. shape: makeWhiskerEndsShape(whiskerEnds),
  41065. style: {strokeNoScale: true},
  41066. z2: 100
  41067. }));
  41068. this.whiskerIndex = count++;
  41069. };
  41070. function transInit(points, dim, itemLayout) {
  41071. return zrUtil.map(points, function (point) {
  41072. point = point.slice();
  41073. point[dim] = itemLayout.initBaseline;
  41074. return point;
  41075. });
  41076. }
  41077. function makeWhiskerEndsShape(whiskerEnds) {
  41078. // zr animation only support 2-dim array.
  41079. var shape = {};
  41080. zrUtil.each(whiskerEnds, function (ends, i) {
  41081. shape['ends' + i] = ends;
  41082. });
  41083. return shape;
  41084. }
  41085. /**
  41086. * Update symbol properties
  41087. * @param {module:echarts/data/List} data
  41088. * @param {number} idx
  41089. */
  41090. whiskerBoxProto.updateData = function (data, idx, isInit) {
  41091. var seriesModel = this._seriesModel = data.hostModel;
  41092. var itemLayout = data.getItemLayout(idx);
  41093. var updateMethod = graphic[isInit ? 'initProps' : 'updateProps'];
  41094. // this.childAt(this.bodyIndex).stopAnimation(true);
  41095. // this.childAt(this.whiskerIndex).stopAnimation(true);
  41096. updateMethod(
  41097. this.childAt(this.bodyIndex),
  41098. {shape: {points: itemLayout.bodyEnds}},
  41099. seriesModel, idx
  41100. );
  41101. updateMethod(
  41102. this.childAt(this.whiskerIndex),
  41103. {shape: makeWhiskerEndsShape(itemLayout.whiskerEnds)},
  41104. seriesModel, idx
  41105. );
  41106. this.styleUpdater.call(null, this, data, idx);
  41107. };
  41108. zrUtil.inherits(WhiskerBox, graphic.Group);
  41109. /**
  41110. * @constructor
  41111. * @alias module:echarts/chart/helper/WhiskerBoxDraw
  41112. */
  41113. function WhiskerBoxDraw(styleUpdater) {
  41114. this.group = new graphic.Group();
  41115. this.styleUpdater = styleUpdater;
  41116. }
  41117. var whiskerBoxDrawProto = WhiskerBoxDraw.prototype;
  41118. /**
  41119. * Update symbols draw by new data
  41120. * @param {module:echarts/data/List} data
  41121. */
  41122. whiskerBoxDrawProto.updateData = function (data) {
  41123. var group = this.group;
  41124. var oldData = this._data;
  41125. var styleUpdater = this.styleUpdater;
  41126. data.diff(oldData)
  41127. .add(function (newIdx) {
  41128. if (data.hasValue(newIdx)) {
  41129. var symbolEl = new WhiskerBox(data, newIdx, styleUpdater, true);
  41130. data.setItemGraphicEl(newIdx, symbolEl);
  41131. group.add(symbolEl);
  41132. }
  41133. })
  41134. .update(function (newIdx, oldIdx) {
  41135. var symbolEl = oldData.getItemGraphicEl(oldIdx);
  41136. // Empty data
  41137. if (!data.hasValue(newIdx)) {
  41138. group.remove(symbolEl);
  41139. return;
  41140. }
  41141. if (!symbolEl) {
  41142. symbolEl = new WhiskerBox(data, newIdx, styleUpdater);
  41143. }
  41144. else {
  41145. symbolEl.updateData(data, newIdx);
  41146. }
  41147. // Add back
  41148. group.add(symbolEl);
  41149. data.setItemGraphicEl(newIdx, symbolEl);
  41150. })
  41151. .remove(function (oldIdx) {
  41152. var el = oldData.getItemGraphicEl(oldIdx);
  41153. el && group.remove(el);
  41154. })
  41155. .execute();
  41156. this._data = data;
  41157. };
  41158. /**
  41159. * Remove symbols.
  41160. * @param {module:echarts/data/List} data
  41161. */
  41162. whiskerBoxDrawProto.remove = function () {
  41163. var group = this.group;
  41164. var data = this._data;
  41165. this._data = null;
  41166. data && data.eachItemGraphicEl(function (el) {
  41167. el && group.remove(el);
  41168. });
  41169. };
  41170. module.exports = WhiskerBoxDraw;
  41171. /***/ },
  41172. /* 260 */
  41173. /***/ function(module, exports, __webpack_require__) {
  41174. 'use strict';
  41175. var zrUtil = __webpack_require__(4);
  41176. var ChartView = __webpack_require__(80);
  41177. var graphic = __webpack_require__(18);
  41178. var whiskerBoxCommon = __webpack_require__(258);
  41179. var BoxplotView = ChartView.extend({
  41180. type: 'boxplot',
  41181. getStyleUpdater: function () {
  41182. return updateStyle;
  41183. },
  41184. dispose: zrUtil.noop
  41185. });
  41186. zrUtil.mixin(BoxplotView, whiskerBoxCommon.viewMixin, true);
  41187. // Update common properties
  41188. var normalStyleAccessPath = ['itemStyle', 'normal'];
  41189. var emphasisStyleAccessPath = ['itemStyle', 'emphasis'];
  41190. function updateStyle(itemGroup, data, idx) {
  41191. var itemModel = data.getItemModel(idx);
  41192. var normalItemStyleModel = itemModel.getModel(normalStyleAccessPath);
  41193. var borderColor = data.getItemVisual(idx, 'color');
  41194. // Exclude borderColor.
  41195. var itemStyle = normalItemStyleModel.getItemStyle(['borderColor']);
  41196. var whiskerEl = itemGroup.childAt(itemGroup.whiskerIndex);
  41197. whiskerEl.style.set(itemStyle);
  41198. whiskerEl.style.stroke = borderColor;
  41199. whiskerEl.dirty();
  41200. var bodyEl = itemGroup.childAt(itemGroup.bodyIndex);
  41201. bodyEl.style.set(itemStyle);
  41202. bodyEl.style.stroke = borderColor;
  41203. bodyEl.dirty();
  41204. var hoverStyle = itemModel.getModel(emphasisStyleAccessPath).getItemStyle();
  41205. graphic.setHoverStyle(itemGroup, hoverStyle);
  41206. }
  41207. module.exports = BoxplotView;
  41208. /***/ },
  41209. /* 261 */
  41210. /***/ function(module, exports) {
  41211. var borderColorQuery = ['itemStyle', 'normal', 'borderColor'];
  41212. module.exports = function (ecModel, api) {
  41213. var globalColors = ecModel.get('color');
  41214. ecModel.eachRawSeriesByType('boxplot', function (seriesModel) {
  41215. var defaulColor = globalColors[seriesModel.seriesIndex % globalColors.length];
  41216. var data = seriesModel.getData();
  41217. data.setVisual({
  41218. legendSymbol: 'roundRect',
  41219. // Use name 'color' but not 'borderColor' for legend usage and
  41220. // visual coding from other component like dataRange.
  41221. color: seriesModel.get(borderColorQuery) || defaulColor
  41222. });
  41223. // Only visible series has each data be visual encoded
  41224. if (!ecModel.isSeriesFiltered(seriesModel)) {
  41225. data.each(function (idx) {
  41226. var itemModel = data.getItemModel(idx);
  41227. data.setItemVisual(
  41228. idx,
  41229. {color: itemModel.get(borderColorQuery, true)}
  41230. );
  41231. });
  41232. }
  41233. });
  41234. };
  41235. /***/ },
  41236. /* 262 */
  41237. /***/ function(module, exports, __webpack_require__) {
  41238. var zrUtil = __webpack_require__(4);
  41239. var numberUtil = __webpack_require__(7);
  41240. var parsePercent = numberUtil.parsePercent;
  41241. var each = zrUtil.each;
  41242. module.exports = function (ecModel) {
  41243. var groupResult = groupSeriesByAxis(ecModel);
  41244. each(groupResult, function (groupItem) {
  41245. var seriesModels = groupItem.seriesModels;
  41246. if (!seriesModels.length) {
  41247. return;
  41248. }
  41249. calculateBase(groupItem);
  41250. each(seriesModels, function (seriesModel, idx) {
  41251. layoutSingleSeries(
  41252. seriesModel,
  41253. groupItem.boxOffsetList[idx],
  41254. groupItem.boxWidthList[idx]
  41255. );
  41256. });
  41257. });
  41258. };
  41259. /**
  41260. * Group series by axis.
  41261. */
  41262. function groupSeriesByAxis(ecModel) {
  41263. var result = [];
  41264. var axisList = [];
  41265. ecModel.eachSeriesByType('boxplot', function (seriesModel) {
  41266. var baseAxis = seriesModel.getBaseAxis();
  41267. var idx = zrUtil.indexOf(axisList, baseAxis);
  41268. if (idx < 0) {
  41269. idx = axisList.length;
  41270. axisList[idx] = baseAxis;
  41271. result[idx] = {axis: baseAxis, seriesModels: []};
  41272. }
  41273. result[idx].seriesModels.push(seriesModel);
  41274. });
  41275. return result;
  41276. }
  41277. /**
  41278. * Calculate offset and box width for each series.
  41279. */
  41280. function calculateBase(groupItem) {
  41281. var extent;
  41282. var baseAxis = groupItem.axis;
  41283. var seriesModels = groupItem.seriesModels;
  41284. var seriesCount = seriesModels.length;
  41285. var boxWidthList = groupItem.boxWidthList = [];
  41286. var boxOffsetList = groupItem.boxOffsetList = [];
  41287. var boundList = [];
  41288. var bandWidth;
  41289. if (baseAxis.type === 'category') {
  41290. bandWidth = baseAxis.getBandWidth();
  41291. }
  41292. else {
  41293. var maxDataCount = 0;
  41294. each(seriesModels, function (seriesModel) {
  41295. maxDataCount = Math.max(maxDataCount, seriesModel.getData().count());
  41296. });
  41297. extent = baseAxis.getExtent(),
  41298. Math.abs(extent[1] - extent[0]) / maxDataCount;
  41299. }
  41300. each(seriesModels, function (seriesModel) {
  41301. var boxWidthBound = seriesModel.get('boxWidth');
  41302. if (!zrUtil.isArray(boxWidthBound)) {
  41303. boxWidthBound = [boxWidthBound, boxWidthBound];
  41304. }
  41305. boundList.push([
  41306. parsePercent(boxWidthBound[0], bandWidth) || 0,
  41307. parsePercent(boxWidthBound[1], bandWidth) || 0
  41308. ]);
  41309. });
  41310. var availableWidth = bandWidth * 0.8 - 2;
  41311. var boxGap = availableWidth / seriesCount * 0.3;
  41312. var boxWidth = (availableWidth - boxGap * (seriesCount - 1)) / seriesCount;
  41313. var base = boxWidth / 2 - availableWidth / 2;
  41314. each(seriesModels, function (seriesModel, idx) {
  41315. boxOffsetList.push(base);
  41316. base += boxGap + boxWidth;
  41317. boxWidthList.push(
  41318. Math.min(Math.max(boxWidth, boundList[idx][0]), boundList[idx][1])
  41319. );
  41320. });
  41321. }
  41322. /**
  41323. * Calculate points location for each series.
  41324. */
  41325. function layoutSingleSeries(seriesModel, offset, boxWidth) {
  41326. var coordSys = seriesModel.coordinateSystem;
  41327. var data = seriesModel.getData();
  41328. var halfWidth = boxWidth / 2;
  41329. var chartLayout = seriesModel.get('layout');
  41330. var variableDim = chartLayout === 'horizontal' ? 0 : 1;
  41331. var constDim = 1 - variableDim;
  41332. var coordDims = ['x', 'y'];
  41333. var vDims = [];
  41334. var cDim;
  41335. zrUtil.each(data.dimensions, function (dimName) {
  41336. var dimInfo = data.getDimensionInfo(dimName);
  41337. var coordDim = dimInfo.coordDim;
  41338. if (coordDim === coordDims[constDim]) {
  41339. vDims.push(dimName);
  41340. }
  41341. else if (coordDim === coordDims[variableDim]) {
  41342. cDim = dimName;
  41343. }
  41344. });
  41345. if (cDim == null || vDims.length < 5) {
  41346. return;
  41347. }
  41348. data.each([cDim].concat(vDims), function () {
  41349. var args = arguments;
  41350. var axisDimVal = args[0];
  41351. var idx = args[vDims.length + 1];
  41352. var median = getPoint(args[3]);
  41353. var end1 = getPoint(args[1]);
  41354. var end5 = getPoint(args[5]);
  41355. var whiskerEnds = [
  41356. [end1, getPoint(args[2])],
  41357. [end5, getPoint(args[4])]
  41358. ];
  41359. layEndLine(end1);
  41360. layEndLine(end5);
  41361. layEndLine(median);
  41362. var bodyEnds = [];
  41363. addBodyEnd(whiskerEnds[0][1], 0);
  41364. addBodyEnd(whiskerEnds[1][1], 1);
  41365. data.setItemLayout(idx, {
  41366. chartLayout: chartLayout,
  41367. initBaseline: median[constDim],
  41368. median: median,
  41369. bodyEnds: bodyEnds,
  41370. whiskerEnds: whiskerEnds
  41371. });
  41372. function getPoint(val) {
  41373. var p = [];
  41374. p[variableDim] = axisDimVal;
  41375. p[constDim] = val;
  41376. var point;
  41377. if (isNaN(axisDimVal) || isNaN(val)) {
  41378. point = [NaN, NaN];
  41379. }
  41380. else {
  41381. point = coordSys.dataToPoint(p);
  41382. point[variableDim] += offset;
  41383. }
  41384. return point;
  41385. }
  41386. function addBodyEnd(point, start) {
  41387. var point1 = point.slice();
  41388. var point2 = point.slice();
  41389. point1[variableDim] += halfWidth;
  41390. point2[variableDim] -= halfWidth;
  41391. start
  41392. ? bodyEnds.push(point1, point2)
  41393. : bodyEnds.push(point2, point1);
  41394. }
  41395. function layEndLine(endCenter) {
  41396. var line = [endCenter.slice(), endCenter.slice()];
  41397. line[0][variableDim] -= halfWidth;
  41398. line[1][variableDim] += halfWidth;
  41399. whiskerEnds.push(line);
  41400. }
  41401. });
  41402. }
  41403. /***/ },
  41404. /* 263 */
  41405. /***/ function(module, exports, __webpack_require__) {
  41406. var echarts = __webpack_require__(1);
  41407. __webpack_require__(264);
  41408. __webpack_require__(265);
  41409. echarts.registerPreprocessor(
  41410. __webpack_require__(266)
  41411. );
  41412. echarts.registerVisual(__webpack_require__(267));
  41413. echarts.registerLayout(__webpack_require__(268));
  41414. /***/ },
  41415. /* 264 */
  41416. /***/ function(module, exports, __webpack_require__) {
  41417. 'use strict';
  41418. var zrUtil = __webpack_require__(4);
  41419. var SeriesModel = __webpack_require__(78);
  41420. var whiskerBoxCommon = __webpack_require__(258);
  41421. var CandlestickSeries = SeriesModel.extend({
  41422. type: 'series.candlestick',
  41423. dependencies: ['xAxis', 'yAxis', 'grid'],
  41424. /**
  41425. * @readOnly
  41426. */
  41427. defaultValueDimensions: ['open', 'close', 'lowest', 'highest'],
  41428. /**
  41429. * @type {Array.<string>}
  41430. * @readOnly
  41431. */
  41432. dimensions: null,
  41433. /**
  41434. * @override
  41435. */
  41436. defaultOption: {
  41437. zlevel: 0, // 一级层叠
  41438. z: 2, // 二级层叠
  41439. coordinateSystem: 'cartesian2d',
  41440. legendHoverLink: true,
  41441. hoverAnimation: true,
  41442. // xAxisIndex: 0,
  41443. // yAxisIndex: 0,
  41444. layout: null, // 'horizontal' or 'vertical'
  41445. itemStyle: {
  41446. normal: {
  41447. color: '#c23531', // 阳线 positive
  41448. color0: '#314656', // 阴线 negative '#c23531', '#314656'
  41449. borderWidth: 1,
  41450. // FIXME
  41451. // ec2中使用的是lineStyle.color 和 lineStyle.color0
  41452. borderColor: '#c23531',
  41453. borderColor0: '#314656'
  41454. },
  41455. emphasis: {
  41456. borderWidth: 2
  41457. }
  41458. },
  41459. barMaxWidth: null,
  41460. barMinWidth: null,
  41461. barWidth: null,
  41462. animationUpdate: false,
  41463. animationEasing: 'linear',
  41464. animationDuration: 300
  41465. },
  41466. /**
  41467. * Get dimension for shadow in dataZoom
  41468. * @return {string} dimension name
  41469. */
  41470. getShadowDim: function () {
  41471. return 'open';
  41472. },
  41473. brushSelector: function (dataIndex, data, selectors) {
  41474. var itemLayout = data.getItemLayout(dataIndex);
  41475. return selectors.rect(itemLayout.brushRect);
  41476. }
  41477. });
  41478. zrUtil.mixin(CandlestickSeries, whiskerBoxCommon.seriesModelMixin, true);
  41479. module.exports = CandlestickSeries;
  41480. /***/ },
  41481. /* 265 */
  41482. /***/ function(module, exports, __webpack_require__) {
  41483. 'use strict';
  41484. var zrUtil = __webpack_require__(4);
  41485. var ChartView = __webpack_require__(80);
  41486. var graphic = __webpack_require__(18);
  41487. var whiskerBoxCommon = __webpack_require__(258);
  41488. var CandlestickView = ChartView.extend({
  41489. type: 'candlestick',
  41490. getStyleUpdater: function () {
  41491. return updateStyle;
  41492. },
  41493. dispose: zrUtil.noop
  41494. });
  41495. zrUtil.mixin(CandlestickView, whiskerBoxCommon.viewMixin, true);
  41496. // Update common properties
  41497. var normalStyleAccessPath = ['itemStyle', 'normal'];
  41498. var emphasisStyleAccessPath = ['itemStyle', 'emphasis'];
  41499. function updateStyle(itemGroup, data, idx) {
  41500. var itemModel = data.getItemModel(idx);
  41501. var normalItemStyleModel = itemModel.getModel(normalStyleAccessPath);
  41502. var color = data.getItemVisual(idx, 'color');
  41503. var borderColor = data.getItemVisual(idx, 'borderColor') || color;
  41504. // Color must be excluded.
  41505. // Because symbol provide setColor individually to set fill and stroke
  41506. var itemStyle = normalItemStyleModel.getItemStyle(
  41507. ['color', 'color0', 'borderColor', 'borderColor0']
  41508. );
  41509. var whiskerEl = itemGroup.childAt(itemGroup.whiskerIndex);
  41510. whiskerEl.useStyle(itemStyle);
  41511. whiskerEl.style.stroke = borderColor;
  41512. var bodyEl = itemGroup.childAt(itemGroup.bodyIndex);
  41513. bodyEl.useStyle(itemStyle);
  41514. bodyEl.style.fill = color;
  41515. bodyEl.style.stroke = borderColor;
  41516. var hoverStyle = itemModel.getModel(emphasisStyleAccessPath).getItemStyle();
  41517. graphic.setHoverStyle(itemGroup, hoverStyle);
  41518. }
  41519. module.exports = CandlestickView;
  41520. /***/ },
  41521. /* 266 */
  41522. /***/ function(module, exports, __webpack_require__) {
  41523. var zrUtil = __webpack_require__(4);
  41524. module.exports = function (option) {
  41525. if (!option || !zrUtil.isArray(option.series)) {
  41526. return;
  41527. }
  41528. // Translate 'k' to 'candlestick'.
  41529. zrUtil.each(option.series, function (seriesItem) {
  41530. if (zrUtil.isObject(seriesItem) && seriesItem.type === 'k') {
  41531. seriesItem.type = 'candlestick';
  41532. }
  41533. });
  41534. };
  41535. /***/ },
  41536. /* 267 */
  41537. /***/ function(module, exports) {
  41538. var positiveBorderColorQuery = ['itemStyle', 'normal', 'borderColor'];
  41539. var negativeBorderColorQuery = ['itemStyle', 'normal', 'borderColor0'];
  41540. var positiveColorQuery = ['itemStyle', 'normal', 'color'];
  41541. var negativeColorQuery = ['itemStyle', 'normal', 'color0'];
  41542. module.exports = function (ecModel, api) {
  41543. ecModel.eachRawSeriesByType('candlestick', function (seriesModel) {
  41544. var data = seriesModel.getData();
  41545. data.setVisual({
  41546. legendSymbol: 'roundRect'
  41547. });
  41548. // Only visible series has each data be visual encoded
  41549. if (!ecModel.isSeriesFiltered(seriesModel)) {
  41550. data.each(function (idx) {
  41551. var itemModel = data.getItemModel(idx);
  41552. var sign = data.getItemLayout(idx).sign;
  41553. data.setItemVisual(
  41554. idx,
  41555. {
  41556. color: itemModel.get(
  41557. sign > 0 ? positiveColorQuery : negativeColorQuery
  41558. ),
  41559. borderColor: itemModel.get(
  41560. sign > 0 ? positiveBorderColorQuery : negativeBorderColorQuery
  41561. )
  41562. }
  41563. );
  41564. });
  41565. }
  41566. });
  41567. };
  41568. /***/ },
  41569. /* 268 */
  41570. /***/ function(module, exports, __webpack_require__) {
  41571. var zrUtil = __webpack_require__(4);
  41572. var retrieve = __webpack_require__(4).retrieve;
  41573. var parsePercent = __webpack_require__(7).parsePercent;
  41574. module.exports = function (ecModel) {
  41575. ecModel.eachSeriesByType('candlestick', function (seriesModel) {
  41576. var coordSys = seriesModel.coordinateSystem;
  41577. var data = seriesModel.getData();
  41578. var candleWidth = calculateCandleWidth(seriesModel, data);
  41579. var chartLayout = seriesModel.get('layout');
  41580. var variableDim = chartLayout === 'horizontal' ? 0 : 1;
  41581. var constDim = 1 - variableDim;
  41582. var coordDims = ['x', 'y'];
  41583. var vDims = [];
  41584. var cDim;
  41585. zrUtil.each(data.dimensions, function (dimName) {
  41586. var dimInfo = data.getDimensionInfo(dimName);
  41587. var coordDim = dimInfo.coordDim;
  41588. if (coordDim === coordDims[constDim]) {
  41589. vDims.push(dimName);
  41590. }
  41591. else if (coordDim === coordDims[variableDim]) {
  41592. cDim = dimName;
  41593. }
  41594. });
  41595. if (cDim == null || vDims.length < 4) {
  41596. return;
  41597. }
  41598. data.each([cDim].concat(vDims), function () {
  41599. var args = arguments;
  41600. var axisDimVal = args[0];
  41601. var idx = args[vDims.length + 1];
  41602. var openVal = args[1];
  41603. var closeVal = args[2];
  41604. var lowestVal = args[3];
  41605. var highestVal = args[4];
  41606. var ocLow = Math.min(openVal, closeVal);
  41607. var ocHigh = Math.max(openVal, closeVal);
  41608. var ocLowPoint = getPoint(ocLow);
  41609. var ocHighPoint = getPoint(ocHigh);
  41610. var lowestPoint = getPoint(lowestVal);
  41611. var highestPoint = getPoint(highestVal);
  41612. var whiskerEnds = [
  41613. [highestPoint, ocHighPoint],
  41614. [lowestPoint, ocLowPoint]
  41615. ];
  41616. var bodyEnds = [];
  41617. addBodyEnd(ocHighPoint, 0);
  41618. addBodyEnd(ocLowPoint, 1);
  41619. data.setItemLayout(idx, {
  41620. chartLayout: chartLayout,
  41621. sign: openVal > closeVal ? -1 : openVal < closeVal ? 1 : 0,
  41622. initBaseline: openVal > closeVal
  41623. ? ocHighPoint[constDim] : ocLowPoint[constDim], // open point.
  41624. bodyEnds: bodyEnds,
  41625. whiskerEnds: whiskerEnds,
  41626. brushRect: makeBrushRect()
  41627. });
  41628. function getPoint(val) {
  41629. var p = [];
  41630. p[variableDim] = axisDimVal;
  41631. p[constDim] = val;
  41632. return (isNaN(axisDimVal) || isNaN(val))
  41633. ? [NaN, NaN]
  41634. : coordSys.dataToPoint(p);
  41635. }
  41636. function addBodyEnd(point, start) {
  41637. var point1 = point.slice();
  41638. var point2 = point.slice();
  41639. point1[variableDim] += candleWidth / 2;
  41640. point2[variableDim] -= candleWidth / 2;
  41641. start
  41642. ? bodyEnds.push(point1, point2)
  41643. : bodyEnds.push(point2, point1);
  41644. }
  41645. function makeBrushRect() {
  41646. var pmin = getPoint(Math.min(openVal, closeVal, lowestVal, highestVal));
  41647. var pmax = getPoint(Math.max(openVal, closeVal, lowestVal, highestVal));
  41648. pmin[variableDim] -= candleWidth / 2;
  41649. pmax[variableDim] -= candleWidth / 2;
  41650. return {
  41651. x: pmin[0],
  41652. y: pmin[1],
  41653. width: constDim ? candleWidth : pmax[0] - pmin[0],
  41654. height: constDim ? pmax[1] - pmin[1] : candleWidth
  41655. };
  41656. }
  41657. }, true);
  41658. });
  41659. };
  41660. function calculateCandleWidth(seriesModel, data) {
  41661. var baseAxis = seriesModel.getBaseAxis();
  41662. var extent;
  41663. var bandWidth = baseAxis.type === 'category'
  41664. ? baseAxis.getBandWidth()
  41665. : (
  41666. extent = baseAxis.getExtent(),
  41667. Math.abs(extent[1] - extent[0]) / data.count()
  41668. );
  41669. var barMaxWidth = parsePercent(
  41670. retrieve(seriesModel.get('barMaxWidth'), bandWidth),
  41671. bandWidth
  41672. );
  41673. var barMinWidth = parsePercent(
  41674. retrieve(seriesModel.get('barMinWidth'), 1),
  41675. bandWidth
  41676. );
  41677. var barWidth = seriesModel.get('barWidth');
  41678. return barWidth != null
  41679. ? parsePercent(barWidth, bandWidth)
  41680. // Put max outer to ensure bar visible in spite of overlap.
  41681. : Math.max(Math.min(bandWidth / 2, barMaxWidth), barMinWidth);
  41682. }
  41683. /***/ },
  41684. /* 269 */
  41685. /***/ function(module, exports, __webpack_require__) {
  41686. var zrUtil = __webpack_require__(4);
  41687. var echarts = __webpack_require__(1);
  41688. __webpack_require__(270);
  41689. __webpack_require__(271);
  41690. echarts.registerVisual(zrUtil.curry(
  41691. __webpack_require__(121), 'effectScatter', 'circle', null
  41692. ));
  41693. echarts.registerLayout(zrUtil.curry(
  41694. __webpack_require__(122), 'effectScatter'
  41695. ));
  41696. /***/ },
  41697. /* 270 */
  41698. /***/ function(module, exports, __webpack_require__) {
  41699. 'use strict';
  41700. var createListFromArray = __webpack_require__(109);
  41701. var SeriesModel = __webpack_require__(78);
  41702. module.exports = SeriesModel.extend({
  41703. type: 'series.effectScatter',
  41704. dependencies: ['grid', 'polar'],
  41705. getInitialData: function (option, ecModel) {
  41706. var list = createListFromArray(option.data, this, ecModel);
  41707. return list;
  41708. },
  41709. brushSelector: 'point',
  41710. defaultOption: {
  41711. coordinateSystem: 'cartesian2d',
  41712. zlevel: 0,
  41713. z: 2,
  41714. legendHoverLink: true,
  41715. effectType: 'ripple',
  41716. progressive: 0,
  41717. // When to show the effect, option: 'render'|'emphasis'
  41718. showEffectOn: 'render',
  41719. // Ripple effect config
  41720. rippleEffect: {
  41721. period: 4,
  41722. // Scale of ripple
  41723. scale: 2.5,
  41724. // Brush type can be fill or stroke
  41725. brushType: 'fill'
  41726. },
  41727. // Cartesian coordinate system
  41728. // xAxisIndex: 0,
  41729. // yAxisIndex: 0,
  41730. // Polar coordinate system
  41731. // polarIndex: 0,
  41732. // Geo coordinate system
  41733. // geoIndex: 0,
  41734. // symbol: null, // 图形类型
  41735. symbolSize: 10 // 图形大小,半宽(半径)参数,当图形为方向或菱形则总宽度为symbolSize * 2
  41736. // symbolRotate: null, // 图形旋转控制
  41737. // large: false,
  41738. // Available when large is true
  41739. // largeThreshold: 2000,
  41740. // itemStyle: {
  41741. // normal: {
  41742. // opacity: 1
  41743. // }
  41744. // }
  41745. }
  41746. });
  41747. /***/ },
  41748. /* 271 */
  41749. /***/ function(module, exports, __webpack_require__) {
  41750. var SymbolDraw = __webpack_require__(116);
  41751. var EffectSymbol = __webpack_require__(272);
  41752. __webpack_require__(1).extendChartView({
  41753. type: 'effectScatter',
  41754. init: function () {
  41755. this._symbolDraw = new SymbolDraw(EffectSymbol);
  41756. },
  41757. render: function (seriesModel, ecModel, api) {
  41758. var data = seriesModel.getData();
  41759. var effectSymbolDraw = this._symbolDraw;
  41760. effectSymbolDraw.updateData(data);
  41761. this.group.add(effectSymbolDraw.group);
  41762. },
  41763. updateLayout: function () {
  41764. this._symbolDraw.updateLayout();
  41765. },
  41766. remove: function (ecModel, api) {
  41767. this._symbolDraw && this._symbolDraw.remove(api);
  41768. },
  41769. dispose: function () {}
  41770. });
  41771. /***/ },
  41772. /* 272 */
  41773. /***/ function(module, exports, __webpack_require__) {
  41774. /**
  41775. * Symbol with ripple effect
  41776. * @module echarts/chart/helper/EffectSymbol
  41777. */
  41778. var zrUtil = __webpack_require__(4);
  41779. var symbolUtil = __webpack_require__(111);
  41780. var graphic = __webpack_require__(18);
  41781. var numberUtil = __webpack_require__(7);
  41782. var Symbol = __webpack_require__(117);
  41783. var Group = graphic.Group;
  41784. var EFFECT_RIPPLE_NUMBER = 3;
  41785. function normalizeSymbolSize(symbolSize) {
  41786. if (!zrUtil.isArray(symbolSize)) {
  41787. symbolSize = [+symbolSize, +symbolSize];
  41788. }
  41789. return symbolSize;
  41790. }
  41791. function updateRipplePath(rippleGroup, effectCfg) {
  41792. rippleGroup.eachChild(function (ripplePath) {
  41793. ripplePath.attr({
  41794. z: effectCfg.z,
  41795. zlevel: effectCfg.zlevel,
  41796. style: {
  41797. stroke: effectCfg.brushType === 'stroke' ? effectCfg.color : null,
  41798. fill: effectCfg.brushType === 'fill' ? effectCfg.color : null
  41799. }
  41800. });
  41801. });
  41802. }
  41803. /**
  41804. * @constructor
  41805. * @param {module:echarts/data/List} data
  41806. * @param {number} idx
  41807. * @extends {module:zrender/graphic/Group}
  41808. */
  41809. function EffectSymbol(data, idx) {
  41810. Group.call(this);
  41811. var symbol = new Symbol(data, idx);
  41812. var rippleGroup = new Group();
  41813. this.add(symbol);
  41814. this.add(rippleGroup);
  41815. rippleGroup.beforeUpdate = function () {
  41816. this.attr(symbol.getScale());
  41817. };
  41818. this.updateData(data, idx);
  41819. }
  41820. var effectSymbolProto = EffectSymbol.prototype;
  41821. effectSymbolProto.stopEffectAnimation = function () {
  41822. this.childAt(1).removeAll();
  41823. };
  41824. effectSymbolProto.startEffectAnimation = function (effectCfg) {
  41825. var symbolType = effectCfg.symbolType;
  41826. var color = effectCfg.color;
  41827. var rippleGroup = this.childAt(1);
  41828. for (var i = 0; i < EFFECT_RIPPLE_NUMBER; i++) {
  41829. // var ripplePath = symbolUtil.createSymbol(
  41830. // symbolType, -0.5, -0.5, 1, 1, color
  41831. // );
  41832. // If width/height are set too small (e.g., set to 1) on ios10
  41833. // and macOS Sierra, a circle stroke become a rect, no matter what
  41834. // the scale is set. So we set width/height as 2. See #4136.
  41835. var ripplePath = symbolUtil.createSymbol(
  41836. symbolType, -1, -1, 2, 2, color
  41837. );
  41838. ripplePath.attr({
  41839. style: {
  41840. strokeNoScale: true
  41841. },
  41842. z2: 99,
  41843. silent: true,
  41844. scale: [0.5, 0.5]
  41845. });
  41846. var delay = -i / EFFECT_RIPPLE_NUMBER * effectCfg.period + effectCfg.effectOffset;
  41847. // TODO Configurable effectCfg.period
  41848. ripplePath.animate('', true)
  41849. .when(effectCfg.period, {
  41850. scale: [effectCfg.rippleScale / 2, effectCfg.rippleScale / 2]
  41851. })
  41852. .delay(delay)
  41853. .start();
  41854. ripplePath.animateStyle(true)
  41855. .when(effectCfg.period, {
  41856. opacity: 0
  41857. })
  41858. .delay(delay)
  41859. .start();
  41860. rippleGroup.add(ripplePath);
  41861. }
  41862. updateRipplePath(rippleGroup, effectCfg);
  41863. };
  41864. /**
  41865. * Update effect symbol
  41866. */
  41867. effectSymbolProto.updateEffectAnimation = function (effectCfg) {
  41868. var oldEffectCfg = this._effectCfg;
  41869. var rippleGroup = this.childAt(1);
  41870. // Must reinitialize effect if following configuration changed
  41871. var DIFFICULT_PROPS = ['symbolType', 'period', 'rippleScale'];
  41872. for (var i = 0; i < DIFFICULT_PROPS; i++) {
  41873. var propName = DIFFICULT_PROPS[i];
  41874. if (oldEffectCfg[propName] !== effectCfg[propName]) {
  41875. this.stopEffectAnimation();
  41876. this.startEffectAnimation(effectCfg);
  41877. return;
  41878. }
  41879. }
  41880. updateRipplePath(rippleGroup, effectCfg);
  41881. };
  41882. /**
  41883. * Highlight symbol
  41884. */
  41885. effectSymbolProto.highlight = function () {
  41886. this.trigger('emphasis');
  41887. };
  41888. /**
  41889. * Downplay symbol
  41890. */
  41891. effectSymbolProto.downplay = function () {
  41892. this.trigger('normal');
  41893. };
  41894. /**
  41895. * Update symbol properties
  41896. * @param {module:echarts/data/List} data
  41897. * @param {number} idx
  41898. */
  41899. effectSymbolProto.updateData = function (data, idx) {
  41900. var seriesModel = data.hostModel;
  41901. this.childAt(0).updateData(data, idx);
  41902. var rippleGroup = this.childAt(1);
  41903. var itemModel = data.getItemModel(idx);
  41904. var symbolType = data.getItemVisual(idx, 'symbol');
  41905. var symbolSize = normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize'));
  41906. var color = data.getItemVisual(idx, 'color');
  41907. rippleGroup.attr('scale', symbolSize);
  41908. rippleGroup.traverse(function (ripplePath) {
  41909. ripplePath.attr({
  41910. fill: color
  41911. });
  41912. });
  41913. var symbolOffset = itemModel.getShallow('symbolOffset');
  41914. if (symbolOffset) {
  41915. var pos = rippleGroup.position;
  41916. pos[0] = numberUtil.parsePercent(symbolOffset[0], symbolSize[0]);
  41917. pos[1] = numberUtil.parsePercent(symbolOffset[1], symbolSize[1]);
  41918. }
  41919. rippleGroup.rotation = (itemModel.getShallow('symbolRotate') || 0) * Math.PI / 180 || 0;
  41920. var effectCfg = {};
  41921. effectCfg.showEffectOn = seriesModel.get('showEffectOn');
  41922. effectCfg.rippleScale = itemModel.get('rippleEffect.scale');
  41923. effectCfg.brushType = itemModel.get('rippleEffect.brushType');
  41924. effectCfg.period = itemModel.get('rippleEffect.period') * 1000;
  41925. effectCfg.effectOffset = idx / data.count();
  41926. effectCfg.z = itemModel.getShallow('z') || 0;
  41927. effectCfg.zlevel = itemModel.getShallow('zlevel') || 0;
  41928. effectCfg.symbolType = symbolType;
  41929. effectCfg.color = color;
  41930. this.off('mouseover').off('mouseout').off('emphasis').off('normal');
  41931. if (effectCfg.showEffectOn === 'render') {
  41932. this._effectCfg
  41933. ? this.updateEffectAnimation(effectCfg)
  41934. : this.startEffectAnimation(effectCfg);
  41935. this._effectCfg = effectCfg;
  41936. }
  41937. else {
  41938. // Not keep old effect config
  41939. this._effectCfg = null;
  41940. this.stopEffectAnimation();
  41941. var symbol = this.childAt(0);
  41942. var onEmphasis = function () {
  41943. symbol.trigger('emphasis');
  41944. if (effectCfg.showEffectOn !== 'render') {
  41945. this.startEffectAnimation(effectCfg);
  41946. }
  41947. };
  41948. var onNormal = function () {
  41949. symbol.trigger('normal');
  41950. if (effectCfg.showEffectOn !== 'render') {
  41951. this.stopEffectAnimation();
  41952. }
  41953. };
  41954. this.on('mouseover', onEmphasis, this)
  41955. .on('mouseout', onNormal, this)
  41956. .on('emphasis', onEmphasis, this)
  41957. .on('normal', onNormal, this);
  41958. }
  41959. this._effectCfg = effectCfg;
  41960. };
  41961. effectSymbolProto.fadeOut = function (cb) {
  41962. this.off('mouseover').off('mouseout').off('emphasis').off('normal');
  41963. cb && cb();
  41964. };
  41965. zrUtil.inherits(EffectSymbol, Group);
  41966. module.exports = EffectSymbol;
  41967. /***/ },
  41968. /* 273 */
  41969. /***/ function(module, exports, __webpack_require__) {
  41970. __webpack_require__(274);
  41971. __webpack_require__(275);
  41972. var echarts = __webpack_require__(1);
  41973. echarts.registerLayout(
  41974. __webpack_require__(280)
  41975. );
  41976. echarts.registerVisual(
  41977. __webpack_require__(281)
  41978. );
  41979. /***/ },
  41980. /* 274 */
  41981. /***/ function(module, exports, __webpack_require__) {
  41982. 'use strict';
  41983. var SeriesModel = __webpack_require__(78);
  41984. var List = __webpack_require__(98);
  41985. var zrUtil = __webpack_require__(4);
  41986. var formatUtil = __webpack_require__(6);
  41987. var CoordinateSystem = __webpack_require__(76);
  41988. // Convert [ [{coord: []}, {coord: []}] ]
  41989. // to [ { coords: [[]] } ]
  41990. function preprocessOption (seriesOpt) {
  41991. var data = seriesOpt.data;
  41992. if (data && data[0] && data[0][0] && data[0][0].coord) {
  41993. if (true) {
  41994. console.warn('Lines data configuration has been changed to'
  41995. + ' { coords:[[1,2],[2,3]] }');
  41996. }
  41997. seriesOpt.data = zrUtil.map(data, function (itemOpt) {
  41998. var coords = [
  41999. itemOpt[0].coord, itemOpt[1].coord
  42000. ];
  42001. var target = {
  42002. coords: coords
  42003. };
  42004. if (itemOpt[0].name) {
  42005. target.fromName = itemOpt[0].name;
  42006. }
  42007. if (itemOpt[1].name) {
  42008. target.toName = itemOpt[1].name;
  42009. }
  42010. return zrUtil.mergeAll([target, itemOpt[0], itemOpt[1]]);
  42011. });
  42012. }
  42013. }
  42014. var LinesSeries = SeriesModel.extend({
  42015. type: 'series.lines',
  42016. dependencies: ['grid', 'polar'],
  42017. visualColorAccessPath: 'lineStyle.normal.color',
  42018. init: function (option) {
  42019. // Not using preprocessor because mergeOption may not have series.type
  42020. preprocessOption(option);
  42021. LinesSeries.superApply(this, 'init', arguments);
  42022. },
  42023. mergeOption: function (option) {
  42024. preprocessOption(option);
  42025. LinesSeries.superApply(this, 'mergeOption', arguments);
  42026. },
  42027. getInitialData: function (option, ecModel) {
  42028. if (true) {
  42029. var CoordSys = CoordinateSystem.get(option.coordinateSystem);
  42030. if (!CoordSys) {
  42031. throw new Error('Unkown coordinate system ' + option.coordinateSystem);
  42032. }
  42033. }
  42034. var lineData = new List(['value'], this);
  42035. lineData.hasItemOption = false;
  42036. lineData.initData(option.data, [], function (dataItem, dimName, dataIndex, dimIndex) {
  42037. // dataItem is simply coords
  42038. if (dataItem instanceof Array) {
  42039. return NaN;
  42040. }
  42041. else {
  42042. lineData.hasItemOption = true;
  42043. var value = dataItem.value;
  42044. if (value != null) {
  42045. return value instanceof Array ? value[dimIndex] : value;
  42046. }
  42047. }
  42048. });
  42049. return lineData;
  42050. },
  42051. formatTooltip: function (dataIndex) {
  42052. var data = this.getData();
  42053. var itemModel = data.getItemModel(dataIndex);
  42054. var name = itemModel.get('name');
  42055. if (name) {
  42056. return name;
  42057. }
  42058. var fromName = itemModel.get('fromName');
  42059. var toName = itemModel.get('toName');
  42060. var html = [];
  42061. fromName != null && html.push(fromName);
  42062. toName != null && html.push(toName);
  42063. return formatUtil.encodeHTML(html.join(' > '));
  42064. },
  42065. defaultOption: {
  42066. coordinateSystem: 'geo',
  42067. zlevel: 0,
  42068. z: 2,
  42069. legendHoverLink: true,
  42070. hoverAnimation: true,
  42071. // Cartesian coordinate system
  42072. xAxisIndex: 0,
  42073. yAxisIndex: 0,
  42074. symbol: ['none', 'none'],
  42075. symbolSize: [10, 10],
  42076. // Geo coordinate system
  42077. geoIndex: 0,
  42078. effect: {
  42079. show: false,
  42080. period: 4,
  42081. // Animation delay. support callback
  42082. // delay: 0,
  42083. // If move with constant speed px/sec
  42084. // period will be ignored if this property is > 0,
  42085. constantSpeed: 0,
  42086. symbol: 'circle',
  42087. symbolSize: 3,
  42088. loop: true,
  42089. // Length of trail, 0 - 1
  42090. trailLength: 0.2
  42091. // Same with lineStyle.normal.color
  42092. // color
  42093. },
  42094. large: false,
  42095. // Available when large is true
  42096. largeThreshold: 2000,
  42097. // If lines are polyline
  42098. // polyline not support curveness, label, animation
  42099. polyline: false,
  42100. label: {
  42101. normal: {
  42102. show: false,
  42103. position: 'end'
  42104. // distance: 5,
  42105. // formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调
  42106. }
  42107. },
  42108. lineStyle: {
  42109. normal: {
  42110. opacity: 0.5
  42111. }
  42112. }
  42113. }
  42114. });
  42115. /***/ },
  42116. /* 275 */
  42117. /***/ function(module, exports, __webpack_require__) {
  42118. var LineDraw = __webpack_require__(209);
  42119. var EffectLine = __webpack_require__(276);
  42120. var Line = __webpack_require__(210);
  42121. var Polyline = __webpack_require__(277);
  42122. var EffectPolyline = __webpack_require__(278);
  42123. var LargeLineDraw = __webpack_require__(279);
  42124. __webpack_require__(1).extendChartView({
  42125. type: 'lines',
  42126. init: function () {},
  42127. render: function (seriesModel, ecModel, api) {
  42128. var data = seriesModel.getData();
  42129. var lineDraw = this._lineDraw;
  42130. var hasEffect = seriesModel.get('effect.show');
  42131. var isPolyline = seriesModel.get('polyline');
  42132. var isLarge = seriesModel.get('large') && data.count() >= seriesModel.get('largeThreshold');
  42133. if (true) {
  42134. if (hasEffect && isLarge) {
  42135. console.warn('Large lines not support effect');
  42136. }
  42137. }
  42138. if (hasEffect !== this._hasEffet || isPolyline !== this._isPolyline || isLarge !== this._isLarge) {
  42139. if (lineDraw) {
  42140. lineDraw.remove();
  42141. }
  42142. lineDraw = this._lineDraw = isLarge
  42143. ? new LargeLineDraw()
  42144. : new LineDraw(
  42145. isPolyline
  42146. ? (hasEffect ? EffectPolyline : Polyline)
  42147. : (hasEffect ? EffectLine : Line)
  42148. );
  42149. this._hasEffet = hasEffect;
  42150. this._isPolyline = isPolyline;
  42151. this._isLarge = isLarge;
  42152. }
  42153. var zlevel = seriesModel.get('zlevel');
  42154. var trailLength = seriesModel.get('effect.trailLength');
  42155. var zr = api.getZr();
  42156. // Avoid the drag cause ghost shadow
  42157. // FIXME Better way ?
  42158. zr.painter.getLayer(zlevel).clear(true);
  42159. // Config layer with motion blur
  42160. if (this._lastZlevel != null) {
  42161. zr.configLayer(this._lastZlevel, {
  42162. motionBlur: false
  42163. });
  42164. }
  42165. if (hasEffect && trailLength) {
  42166. if (true) {
  42167. var notInIndividual = false;
  42168. ecModel.eachSeries(function (otherSeriesModel) {
  42169. if (otherSeriesModel !== seriesModel && otherSeriesModel.get('zlevel') === zlevel) {
  42170. notInIndividual = true;
  42171. }
  42172. });
  42173. notInIndividual && console.warn('Lines with trail effect should have an individual zlevel');
  42174. }
  42175. zr.configLayer(zlevel, {
  42176. motionBlur: true,
  42177. lastFrameAlpha: Math.max(Math.min(trailLength / 10 + 0.9, 1), 0)
  42178. });
  42179. }
  42180. this.group.add(lineDraw.group);
  42181. lineDraw.updateData(data);
  42182. this._lastZlevel = zlevel;
  42183. },
  42184. updateLayout: function (seriesModel, ecModel, api) {
  42185. this._lineDraw.updateLayout(seriesModel);
  42186. // Not use motion when dragging or zooming
  42187. var zr = api.getZr();
  42188. zr.painter.getLayer(this._lastZlevel).clear(true);
  42189. },
  42190. remove: function (ecModel, api) {
  42191. this._lineDraw && this._lineDraw.remove(api, true);
  42192. },
  42193. dispose: function () {}
  42194. });
  42195. /***/ },
  42196. /* 276 */
  42197. /***/ function(module, exports, __webpack_require__) {
  42198. /**
  42199. * Provide effect for line
  42200. * @module echarts/chart/helper/EffectLine
  42201. */
  42202. var graphic = __webpack_require__(18);
  42203. var Line = __webpack_require__(210);
  42204. var zrUtil = __webpack_require__(4);
  42205. var symbolUtil = __webpack_require__(111);
  42206. var vec2 = __webpack_require__(10);
  42207. var curveUtil = __webpack_require__(37);
  42208. /**
  42209. * @constructor
  42210. * @extends {module:zrender/graphic/Group}
  42211. * @alias {module:echarts/chart/helper/Line}
  42212. */
  42213. function EffectLine(lineData, idx, seriesScope) {
  42214. graphic.Group.call(this);
  42215. this.add(this.createLine(lineData, idx, seriesScope));
  42216. this._updateEffectSymbol(lineData, idx);
  42217. }
  42218. var effectLineProto = EffectLine.prototype;
  42219. effectLineProto.createLine = function (lineData, idx, seriesScope) {
  42220. return new Line(lineData, idx, seriesScope);
  42221. };
  42222. effectLineProto._updateEffectSymbol = function (lineData, idx) {
  42223. var itemModel = lineData.getItemModel(idx);
  42224. var effectModel = itemModel.getModel('effect');
  42225. var size = effectModel.get('symbolSize');
  42226. var symbolType = effectModel.get('symbol');
  42227. if (!zrUtil.isArray(size)) {
  42228. size = [size, size];
  42229. }
  42230. var color = effectModel.get('color') || lineData.getItemVisual(idx, 'color');
  42231. var symbol = this.childAt(1);
  42232. if (this._symbolType !== symbolType) {
  42233. // Remove previous
  42234. this.remove(symbol);
  42235. symbol = symbolUtil.createSymbol(
  42236. symbolType, -0.5, -0.5, 1, 1, color
  42237. );
  42238. symbol.z2 = 100;
  42239. symbol.culling = true;
  42240. this.add(symbol);
  42241. }
  42242. // Symbol may be removed if loop is false
  42243. if (!symbol) {
  42244. return;
  42245. }
  42246. // Shadow color is same with color in default
  42247. symbol.setStyle('shadowColor', color);
  42248. symbol.setStyle(effectModel.getItemStyle(['color']));
  42249. symbol.attr('scale', size);
  42250. symbol.setColor(color);
  42251. symbol.attr('scale', size);
  42252. this._symbolType = symbolType;
  42253. this._updateEffectAnimation(lineData, effectModel, idx);
  42254. };
  42255. effectLineProto._updateEffectAnimation = function (lineData, effectModel, idx) {
  42256. var symbol = this.childAt(1);
  42257. if (!symbol) {
  42258. return;
  42259. }
  42260. var self = this;
  42261. var points = lineData.getItemLayout(idx);
  42262. var period = effectModel.get('period') * 1000;
  42263. var loop = effectModel.get('loop');
  42264. var constantSpeed = effectModel.get('constantSpeed');
  42265. var delayExpr = zrUtil.retrieve(effectModel.get('delay'), function (idx) {
  42266. return idx / lineData.count() * period / 3;
  42267. });
  42268. var isDelayFunc = typeof delayExpr === 'function';
  42269. // Ignore when updating
  42270. symbol.ignore = true;
  42271. this.updateAnimationPoints(symbol, points);
  42272. if (constantSpeed > 0) {
  42273. period = this.getLineLength(symbol) / constantSpeed * 1000;
  42274. }
  42275. if (period !== this._period || loop !== this._loop) {
  42276. symbol.stopAnimation();
  42277. var delay = delayExpr;
  42278. if (isDelayFunc) {
  42279. delay = delayExpr(idx);
  42280. }
  42281. if (symbol.__t > 0) {
  42282. delay = -period * symbol.__t;
  42283. }
  42284. symbol.__t = 0;
  42285. var animator = symbol.animate('', loop)
  42286. .when(period, {
  42287. __t: 1
  42288. })
  42289. .delay(delay)
  42290. .during(function () {
  42291. self.updateSymbolPosition(symbol);
  42292. });
  42293. if (!loop) {
  42294. animator.done(function () {
  42295. self.remove(symbol);
  42296. });
  42297. }
  42298. animator.start();
  42299. }
  42300. this._period = period;
  42301. this._loop = loop;
  42302. };
  42303. effectLineProto.getLineLength = function (symbol) {
  42304. // Not so accurate
  42305. return (vec2.dist(symbol.__p1, symbol.__cp1)
  42306. + vec2.dist(symbol.__cp1, symbol.__p2));
  42307. };
  42308. effectLineProto.updateAnimationPoints = function (symbol, points) {
  42309. symbol.__p1 = points[0];
  42310. symbol.__p2 = points[1];
  42311. symbol.__cp1 = points[2] || [
  42312. (points[0][0] + points[1][0]) / 2,
  42313. (points[0][1] + points[1][1]) / 2
  42314. ];
  42315. };
  42316. effectLineProto.updateData = function (lineData, idx, seriesScope) {
  42317. this.childAt(0).updateData(lineData, idx, seriesScope);
  42318. this._updateEffectSymbol(lineData, idx);
  42319. };
  42320. effectLineProto.updateSymbolPosition = function (symbol) {
  42321. var p1 = symbol.__p1;
  42322. var p2 = symbol.__p2;
  42323. var cp1 = symbol.__cp1;
  42324. var t = symbol.__t;
  42325. var pos = symbol.position;
  42326. var quadraticAt = curveUtil.quadraticAt;
  42327. var quadraticDerivativeAt = curveUtil.quadraticDerivativeAt;
  42328. pos[0] = quadraticAt(p1[0], cp1[0], p2[0], t);
  42329. pos[1] = quadraticAt(p1[1], cp1[1], p2[1], t);
  42330. // Tangent
  42331. var tx = quadraticDerivativeAt(p1[0], cp1[0], p2[0], t);
  42332. var ty = quadraticDerivativeAt(p1[1], cp1[1], p2[1], t);
  42333. symbol.rotation = -Math.atan2(ty, tx) - Math.PI / 2;
  42334. symbol.ignore = false;
  42335. };
  42336. effectLineProto.updateLayout = function (lineData, idx) {
  42337. this.childAt(0).updateLayout(lineData, idx);
  42338. var effectModel = lineData.getItemModel(idx).getModel('effect');
  42339. this._updateEffectAnimation(lineData, effectModel, idx);
  42340. };
  42341. zrUtil.inherits(EffectLine, graphic.Group);
  42342. module.exports = EffectLine;
  42343. /***/ },
  42344. /* 277 */
  42345. /***/ function(module, exports, __webpack_require__) {
  42346. /**
  42347. * @module echarts/chart/helper/Line
  42348. */
  42349. var graphic = __webpack_require__(18);
  42350. var zrUtil = __webpack_require__(4);
  42351. /**
  42352. * @constructor
  42353. * @extends {module:zrender/graphic/Group}
  42354. * @alias {module:echarts/chart/helper/Polyline}
  42355. */
  42356. function Polyline(lineData, idx, seriesScope) {
  42357. graphic.Group.call(this);
  42358. this._createPolyline(lineData, idx, seriesScope);
  42359. }
  42360. var polylineProto = Polyline.prototype;
  42361. polylineProto._createPolyline = function (lineData, idx, seriesScope) {
  42362. // var seriesModel = lineData.hostModel;
  42363. var points = lineData.getItemLayout(idx);
  42364. var line = new graphic.Polyline({
  42365. shape: {
  42366. points: points
  42367. }
  42368. });
  42369. this.add(line);
  42370. this._updateCommonStl(lineData, idx, seriesScope);
  42371. };
  42372. polylineProto.updateData = function (lineData, idx, seriesScope) {
  42373. var seriesModel = lineData.hostModel;
  42374. var line = this.childAt(0);
  42375. var target = {
  42376. shape: {
  42377. points: lineData.getItemLayout(idx)
  42378. }
  42379. };
  42380. graphic.updateProps(line, target, seriesModel, idx);
  42381. this._updateCommonStl(lineData, idx, seriesScope);
  42382. };
  42383. polylineProto._updateCommonStl = function (lineData, idx, seriesScope) {
  42384. var line = this.childAt(0);
  42385. var itemModel = lineData.getItemModel(idx);
  42386. var visualColor = lineData.getItemVisual(idx, 'color');
  42387. var lineStyle = seriesScope && seriesScope.lineStyle;
  42388. var hoverLineStyle = seriesScope && seriesScope.hoverLineStyle;
  42389. if (!seriesScope || lineData.hasItemOption) {
  42390. lineStyle = itemModel.getModel('lineStyle.normal').getLineStyle();
  42391. hoverLineStyle = itemModel.getModel('lineStyle.emphasis').getLineStyle();
  42392. }
  42393. line.useStyle(zrUtil.defaults(
  42394. {
  42395. strokeNoScale: true,
  42396. fill: 'none',
  42397. stroke: visualColor
  42398. },
  42399. lineStyle
  42400. ));
  42401. line.hoverStyle = hoverLineStyle;
  42402. graphic.setHoverStyle(this);
  42403. };
  42404. polylineProto.updateLayout = function (lineData, idx) {
  42405. var polyline = this.childAt(0);
  42406. polyline.setShape('points', lineData.getItemLayout(idx));
  42407. };
  42408. zrUtil.inherits(Polyline, graphic.Group);
  42409. module.exports = Polyline;
  42410. /***/ },
  42411. /* 278 */
  42412. /***/ function(module, exports, __webpack_require__) {
  42413. /**
  42414. * Provide effect for line
  42415. * @module echarts/chart/helper/EffectLine
  42416. */
  42417. var Polyline = __webpack_require__(277);
  42418. var zrUtil = __webpack_require__(4);
  42419. var EffectLine = __webpack_require__(276);
  42420. var vec2 = __webpack_require__(10);
  42421. /**
  42422. * @constructor
  42423. * @extends {module:echarts/chart/helper/EffectLine}
  42424. * @alias {module:echarts/chart/helper/Polyline}
  42425. */
  42426. function EffectPolyline(lineData, idx, seriesScope) {
  42427. EffectLine.call(this, lineData, idx, seriesScope);
  42428. this._lastFrame = 0;
  42429. this._lastFramePercent = 0;
  42430. }
  42431. var effectPolylineProto = EffectPolyline.prototype;
  42432. // Overwrite
  42433. effectPolylineProto.createLine = function (lineData, idx, seriesScope) {
  42434. return new Polyline(lineData, idx, seriesScope);
  42435. };
  42436. // Overwrite
  42437. effectPolylineProto.updateAnimationPoints = function (symbol, points) {
  42438. this._points = points;
  42439. var accLenArr = [0];
  42440. var len = 0;
  42441. for (var i = 1; i < points.length; i++) {
  42442. var p1 = points[i - 1];
  42443. var p2 = points[i];
  42444. len += vec2.dist(p1, p2);
  42445. accLenArr.push(len);
  42446. }
  42447. if (len === 0) {
  42448. return;
  42449. }
  42450. for (var i = 0; i < accLenArr.length; i++) {
  42451. accLenArr[i] /= len;
  42452. }
  42453. this._offsets = accLenArr;
  42454. this._length = len;
  42455. };
  42456. // Overwrite
  42457. effectPolylineProto.getLineLength = function (symbol) {
  42458. return this._length;
  42459. };
  42460. // Overwrite
  42461. effectPolylineProto.updateSymbolPosition = function (symbol) {
  42462. var t = symbol.__t;
  42463. var points = this._points;
  42464. var offsets = this._offsets;
  42465. var len = points.length;
  42466. if (!offsets) {
  42467. // Has length 0
  42468. return;
  42469. }
  42470. var lastFrame = this._lastFrame;
  42471. var frame;
  42472. if (t < this._lastFramePercent) {
  42473. // Start from the next frame
  42474. // PENDING start from lastFrame ?
  42475. var start = Math.min(lastFrame + 1, len - 1);
  42476. for (frame = start; frame >= 0; frame--) {
  42477. if (offsets[frame] <= t) {
  42478. break;
  42479. }
  42480. }
  42481. // PENDING really need to do this ?
  42482. frame = Math.min(frame, len - 2);
  42483. }
  42484. else {
  42485. for (var frame = lastFrame; frame < len; frame++) {
  42486. if (offsets[frame] > t) {
  42487. break;
  42488. }
  42489. }
  42490. frame = Math.min(frame - 1, len - 2);
  42491. }
  42492. vec2.lerp(
  42493. symbol.position, points[frame], points[frame + 1],
  42494. (t - offsets[frame]) / (offsets[frame + 1] - offsets[frame])
  42495. );
  42496. var tx = points[frame + 1][0] - points[frame][0];
  42497. var ty = points[frame + 1][1] - points[frame][1];
  42498. symbol.rotation = -Math.atan2(ty, tx) - Math.PI / 2;
  42499. this._lastFrame = frame;
  42500. this._lastFramePercent = t;
  42501. symbol.ignore = false;
  42502. };
  42503. zrUtil.inherits(EffectPolyline, EffectLine);
  42504. module.exports = EffectPolyline;
  42505. /***/ },
  42506. /* 279 */
  42507. /***/ function(module, exports, __webpack_require__) {
  42508. // TODO Batch by color
  42509. var graphic = __webpack_require__(18);
  42510. var quadraticContain = __webpack_require__(42);
  42511. var lineContain = __webpack_require__(40);
  42512. var LargeLineShape = graphic.extendShape({
  42513. shape: {
  42514. polyline: false,
  42515. segs: []
  42516. },
  42517. buildPath: function (path, shape) {
  42518. var segs = shape.segs;
  42519. var isPolyline = shape.polyline;
  42520. for (var i = 0; i < segs.length; i++) {
  42521. var seg = segs[i];
  42522. if (isPolyline) {
  42523. path.moveTo(seg[0][0], seg[0][1]);
  42524. for (var j = 1; j < seg.length; j++) {
  42525. path.lineTo(seg[j][0], seg[j][1]);
  42526. }
  42527. }
  42528. else {
  42529. path.moveTo(seg[0][0], seg[0][1]);
  42530. if (seg.length > 2) {
  42531. path.quadraticCurveTo(seg[2][0], seg[2][1], seg[1][0], seg[1][1]);
  42532. }
  42533. else {
  42534. path.lineTo(seg[1][0], seg[1][1]);
  42535. }
  42536. }
  42537. }
  42538. },
  42539. findDataIndex: function (x, y) {
  42540. var shape = this.shape;
  42541. var segs = shape.segs;
  42542. var isPolyline = shape.polyline;
  42543. var lineWidth = Math.max(this.style.lineWidth, 1);
  42544. // Not consider transform
  42545. for (var i = 0; i < segs.length; i++) {
  42546. var seg = segs[i];
  42547. if (isPolyline) {
  42548. for (var j = 1; j < seg.length; j++) {
  42549. if (lineContain.containStroke(
  42550. seg[j - 1][0], seg[j - 1][1], seg[j][0], seg[j][1], lineWidth, x, y
  42551. )) {
  42552. return i;
  42553. }
  42554. }
  42555. }
  42556. else {
  42557. if (seg.length > 2) {
  42558. if (quadraticContain.containStroke(
  42559. seg[0][0], seg[0][1], seg[2][0], seg[2][1], seg[1][0], seg[1][1], lineWidth, x, y
  42560. )) {
  42561. return i;
  42562. }
  42563. }
  42564. else {
  42565. if (lineContain.containStroke(
  42566. seg[0][0], seg[0][1], seg[1][0], seg[1][1], lineWidth, x, y
  42567. )) {
  42568. return i;
  42569. }
  42570. }
  42571. }
  42572. }
  42573. return -1;
  42574. }
  42575. });
  42576. function LargeLineDraw() {
  42577. this.group = new graphic.Group();
  42578. this._lineEl = new LargeLineShape();
  42579. }
  42580. var largeLineProto = LargeLineDraw.prototype;
  42581. /**
  42582. * Update symbols draw by new data
  42583. * @param {module:echarts/data/List} data
  42584. */
  42585. largeLineProto.updateData = function (data) {
  42586. this.group.removeAll();
  42587. var lineEl = this._lineEl;
  42588. var seriesModel = data.hostModel;
  42589. lineEl.setShape({
  42590. segs: data.mapArray(data.getItemLayout),
  42591. polyline: seriesModel.get('polyline')
  42592. });
  42593. lineEl.useStyle(
  42594. seriesModel.getModel('lineStyle.normal').getLineStyle()
  42595. );
  42596. var visualColor = data.getVisual('color');
  42597. if (visualColor) {
  42598. lineEl.setStyle('stroke', visualColor);
  42599. }
  42600. lineEl.setStyle('fill');
  42601. // Enable tooltip
  42602. // PENDING May have performance issue when path is extremely large
  42603. lineEl.seriesIndex = seriesModel.seriesIndex;
  42604. lineEl.on('mousemove', function (e) {
  42605. lineEl.dataIndex = null;
  42606. var dataIndex = lineEl.findDataIndex(e.offsetX, e.offsetY);
  42607. if (dataIndex > 0) {
  42608. // Provide dataIndex for tooltip
  42609. lineEl.dataIndex = dataIndex;
  42610. }
  42611. });
  42612. // Add back
  42613. this.group.add(lineEl);
  42614. };
  42615. largeLineProto.updateLayout = function (seriesModel) {
  42616. var data = seriesModel.getData();
  42617. this._lineEl.setShape({
  42618. segs: data.mapArray(data.getItemLayout)
  42619. });
  42620. };
  42621. largeLineProto.remove = function () {
  42622. this.group.removeAll();
  42623. };
  42624. module.exports = LargeLineDraw;
  42625. /***/ },
  42626. /* 280 */
  42627. /***/ function(module, exports, __webpack_require__) {
  42628. module.exports = function (ecModel) {
  42629. ecModel.eachSeriesByType('lines', function (seriesModel) {
  42630. var coordSys = seriesModel.coordinateSystem;
  42631. var lineData = seriesModel.getData();
  42632. // FIXME Use data dimensions ?
  42633. lineData.each(function (idx) {
  42634. var itemModel = lineData.getItemModel(idx);
  42635. var coords = (itemModel.option instanceof Array) ?
  42636. itemModel.option : itemModel.get('coords');
  42637. if (true) {
  42638. if (!(coords instanceof Array && coords.length > 0 && coords[0] instanceof Array)) {
  42639. throw new Error('Invalid coords ' + JSON.stringify(coords) + '. Lines must have 2d coords array in data item.');
  42640. }
  42641. }
  42642. var pts = [];
  42643. if (seriesModel.get('polyline')) {
  42644. for (var i = 0; i < coords.length; i++) {
  42645. pts.push(coordSys.dataToPoint(coords[i]));
  42646. }
  42647. }
  42648. else {
  42649. pts[0] = coordSys.dataToPoint(coords[0]);
  42650. pts[1] = coordSys.dataToPoint(coords[1]);
  42651. var curveness = itemModel.get('lineStyle.normal.curveness');
  42652. if (+curveness) {
  42653. pts[2] = [
  42654. (pts[0][0] + pts[1][0]) / 2 - (pts[0][1] - pts[1][1]) * curveness,
  42655. (pts[0][1] + pts[1][1]) / 2 - (pts[1][0] - pts[0][0]) * curveness
  42656. ];
  42657. }
  42658. }
  42659. lineData.setItemLayout(idx, pts);
  42660. });
  42661. });
  42662. };
  42663. /***/ },
  42664. /* 281 */
  42665. /***/ function(module, exports) {
  42666. function normalize(a) {
  42667. if (!(a instanceof Array)) {
  42668. a = [a, a];
  42669. }
  42670. return a;
  42671. }
  42672. module.exports = function (ecModel) {
  42673. ecModel.eachSeriesByType('lines', function (seriesModel) {
  42674. var data = seriesModel.getData();
  42675. var symbolType = normalize(seriesModel.get('symbol'));
  42676. var symbolSize = normalize(seriesModel.get('symbolSize'));
  42677. var opacityQuery = 'lineStyle.normal.opacity'.split('.');
  42678. data.setVisual('fromSymbol', symbolType && symbolType[0]);
  42679. data.setVisual('toSymbol', symbolType && symbolType[1]);
  42680. data.setVisual('fromSymbolSize', symbolSize && symbolSize[0]);
  42681. data.setVisual('toSymbolSize', symbolSize && symbolSize[1]);
  42682. data.setVisual('opacity', seriesModel.get(opacityQuery));
  42683. data.each(function (idx) {
  42684. var itemModel = data.getItemModel(idx);
  42685. var symbolType = normalize(itemModel.getShallow('symbol', true));
  42686. var symbolSize = normalize(itemModel.getShallow('symbolSize', true));
  42687. var opacity = itemModel.get(opacityQuery);
  42688. symbolType[0] && data.setItemVisual(idx, 'fromSymbol', symbolType[0]);
  42689. symbolType[1] && data.setItemVisual(idx, 'toSymbol', symbolType[1]);
  42690. symbolSize[0] && data.setItemVisual(idx, 'fromSymbolSize', symbolSize[0]);
  42691. symbolSize[1] && data.setItemVisual(idx, 'toSymbolSize', symbolSize[1]);
  42692. data.setItemVisual(idx, 'opacity', opacity);
  42693. });
  42694. });
  42695. };
  42696. /***/ },
  42697. /* 282 */
  42698. /***/ function(module, exports, __webpack_require__) {
  42699. __webpack_require__(283);
  42700. __webpack_require__(284);
  42701. /***/ },
  42702. /* 283 */
  42703. /***/ function(module, exports, __webpack_require__) {
  42704. var SeriesModel = __webpack_require__(78);
  42705. var createListFromArray = __webpack_require__(109);
  42706. module.exports = SeriesModel.extend({
  42707. type: 'series.heatmap',
  42708. getInitialData: function (option, ecModel) {
  42709. return createListFromArray(option.data, this, ecModel);
  42710. },
  42711. defaultOption: {
  42712. // Cartesian2D or geo
  42713. coordinateSystem: 'cartesian2d',
  42714. zlevel: 0,
  42715. z: 2,
  42716. // Cartesian coordinate system
  42717. // xAxisIndex: 0,
  42718. // yAxisIndex: 0,
  42719. // Geo coordinate system
  42720. geoIndex: 0,
  42721. blurSize: 30,
  42722. pointSize: 20,
  42723. maxOpacity: 1,
  42724. minOpacity: 0
  42725. }
  42726. });
  42727. /***/ },
  42728. /* 284 */
  42729. /***/ function(module, exports, __webpack_require__) {
  42730. var graphic = __webpack_require__(18);
  42731. var HeatmapLayer = __webpack_require__(285);
  42732. var zrUtil = __webpack_require__(4);
  42733. function getIsInPiecewiseRange(dataExtent, pieceList, selected) {
  42734. var dataSpan = dataExtent[1] - dataExtent[0];
  42735. pieceList = zrUtil.map(pieceList, function (piece) {
  42736. return {
  42737. interval: [
  42738. (piece.interval[0] - dataExtent[0]) / dataSpan,
  42739. (piece.interval[1] - dataExtent[0]) / dataSpan
  42740. ]
  42741. };
  42742. });
  42743. var len = pieceList.length;
  42744. var lastIndex = 0;
  42745. return function (val) {
  42746. // Try to find in the location of the last found
  42747. for (var i = lastIndex; i < len; i++) {
  42748. var interval = pieceList[i].interval;
  42749. if (interval[0] <= val && val <= interval[1]) {
  42750. lastIndex = i;
  42751. break;
  42752. }
  42753. }
  42754. if (i === len) { // Not found, back interation
  42755. for (var i = lastIndex - 1; i >= 0; i--) {
  42756. var interval = pieceList[i].interval;
  42757. if (interval[0] <= val && val <= interval[1]) {
  42758. lastIndex = i;
  42759. break;
  42760. }
  42761. }
  42762. }
  42763. return i >= 0 && i < len && selected[i];
  42764. };
  42765. }
  42766. function getIsInContinuousRange(dataExtent, range) {
  42767. var dataSpan = dataExtent[1] - dataExtent[0];
  42768. range = [
  42769. (range[0] - dataExtent[0]) / dataSpan,
  42770. (range[1] - dataExtent[0]) / dataSpan
  42771. ];
  42772. return function (val) {
  42773. return val >= range[0] && val <= range[1];
  42774. };
  42775. }
  42776. function isGeoCoordSys(coordSys) {
  42777. var dimensions = coordSys.dimensions;
  42778. // Not use coorSys.type === 'geo' because coordSys maybe extended
  42779. return dimensions[0] === 'lng' && dimensions[1] === 'lat';
  42780. }
  42781. module.exports = __webpack_require__(1).extendChartView({
  42782. type: 'heatmap',
  42783. render: function (seriesModel, ecModel, api) {
  42784. var visualMapOfThisSeries;
  42785. ecModel.eachComponent('visualMap', function (visualMap) {
  42786. visualMap.eachTargetSeries(function (targetSeries) {
  42787. if (targetSeries === seriesModel) {
  42788. visualMapOfThisSeries = visualMap;
  42789. }
  42790. });
  42791. });
  42792. if (true) {
  42793. if (!visualMapOfThisSeries) {
  42794. throw new Error('Heatmap must use with visualMap');
  42795. }
  42796. }
  42797. this.group.removeAll();
  42798. var coordSys = seriesModel.coordinateSystem;
  42799. if (coordSys.type === 'cartesian2d' || coordSys.type === 'calendar') {
  42800. this._renderOnCartesianAndCalendar(coordSys, seriesModel, api);
  42801. }
  42802. else if (isGeoCoordSys(coordSys)) {
  42803. this._renderOnGeo(
  42804. coordSys, seriesModel, visualMapOfThisSeries, api
  42805. );
  42806. }
  42807. },
  42808. dispose: function () {},
  42809. _renderOnCartesianAndCalendar: function (coordSys, seriesModel, api) {
  42810. if (coordSys.type === 'cartesian2d') {
  42811. var xAxis = coordSys.getAxis('x');
  42812. var yAxis = coordSys.getAxis('y');
  42813. if (true) {
  42814. if (!(xAxis.type === 'category' && yAxis.type === 'category')) {
  42815. throw new Error('Heatmap on cartesian must have two category axes');
  42816. }
  42817. if (!(xAxis.onBand && yAxis.onBand)) {
  42818. throw new Error('Heatmap on cartesian must have two axes with boundaryGap true');
  42819. }
  42820. }
  42821. var width = xAxis.getBandWidth();
  42822. var height = yAxis.getBandWidth();
  42823. }
  42824. var group = this.group;
  42825. var data = seriesModel.getData();
  42826. var itemStyleQuery = 'itemStyle.normal';
  42827. var hoverItemStyleQuery = 'itemStyle.emphasis';
  42828. var labelQuery = 'label.normal';
  42829. var hoverLabelQuery = 'label.emphasis';
  42830. var style = seriesModel.getModel(itemStyleQuery).getItemStyle(['color']);
  42831. var hoverStl = seriesModel.getModel(hoverItemStyleQuery).getItemStyle();
  42832. var labelModel = seriesModel.getModel('label.normal');
  42833. var hoverLabelModel = seriesModel.getModel('label.emphasis');
  42834. var coordSysType = coordSys.type;
  42835. var dataDims = coordSysType === 'cartesian2d'
  42836. ? [
  42837. seriesModel.coordDimToDataDim('x')[0],
  42838. seriesModel.coordDimToDataDim('y')[0],
  42839. seriesModel.coordDimToDataDim('value')[0]
  42840. ]
  42841. : [
  42842. seriesModel.coordDimToDataDim('time')[0],
  42843. seriesModel.coordDimToDataDim('value')[0]
  42844. ];
  42845. data.each(function (idx) {
  42846. var rect;
  42847. if (coordSysType === 'cartesian2d') {
  42848. // Ignore empty data
  42849. if (isNaN(data.get(dataDims[2], idx))) {
  42850. return;
  42851. }
  42852. var point = coordSys.dataToPoint([
  42853. data.get(dataDims[0], idx),
  42854. data.get(dataDims[1], idx)
  42855. ]);
  42856. rect = new graphic.Rect({
  42857. shape: {
  42858. x: point[0] - width / 2,
  42859. y: point[1] - height / 2,
  42860. width: width,
  42861. height: height
  42862. },
  42863. style: {
  42864. fill: data.getItemVisual(idx, 'color'),
  42865. opacity: data.getItemVisual(idx, 'opacity')
  42866. }
  42867. });
  42868. }
  42869. else {
  42870. // Ignore empty data
  42871. if (isNaN(data.get(dataDims[1], idx))) {
  42872. return;
  42873. }
  42874. rect = new graphic.Rect({
  42875. z2: 1,
  42876. shape: coordSys.dataToRect([data.get(dataDims[0], idx)]).contentShape,
  42877. style: {
  42878. fill: data.getItemVisual(idx, 'color'),
  42879. opacity: data.getItemVisual(idx, 'opacity')
  42880. }
  42881. });
  42882. }
  42883. var itemModel = data.getItemModel(idx);
  42884. // Optimization for large datset
  42885. if (data.hasItemOption) {
  42886. style = itemModel.getModel(itemStyleQuery).getItemStyle(['color']);
  42887. hoverStl = itemModel.getModel(hoverItemStyleQuery).getItemStyle();
  42888. labelModel = itemModel.getModel(labelQuery);
  42889. hoverLabelModel = itemModel.getModel(hoverLabelQuery);
  42890. }
  42891. var rawValue = seriesModel.getRawValue(idx);
  42892. var defaultText = '-';
  42893. if (rawValue && rawValue[2] != null) {
  42894. defaultText = rawValue[2];
  42895. }
  42896. if (labelModel.getShallow('show')) {
  42897. graphic.setText(style, labelModel);
  42898. style.text = seriesModel.getFormattedLabel(idx, 'normal') || defaultText;
  42899. }
  42900. if (hoverLabelModel.getShallow('show')) {
  42901. graphic.setText(hoverStl, hoverLabelModel);
  42902. hoverStl.text = seriesModel.getFormattedLabel(idx, 'emphasis') || defaultText;
  42903. }
  42904. rect.setStyle(style);
  42905. graphic.setHoverStyle(rect, data.hasItemOption ? hoverStl : zrUtil.extend({}, hoverStl));
  42906. group.add(rect);
  42907. data.setItemGraphicEl(idx, rect);
  42908. });
  42909. },
  42910. _renderOnGeo: function (geo, seriesModel, visualMapModel, api) {
  42911. var inRangeVisuals = visualMapModel.targetVisuals.inRange;
  42912. var outOfRangeVisuals = visualMapModel.targetVisuals.outOfRange;
  42913. // if (!visualMapping) {
  42914. // throw new Error('Data range must have color visuals');
  42915. // }
  42916. var data = seriesModel.getData();
  42917. var hmLayer = this._hmLayer || (this._hmLayer || new HeatmapLayer());
  42918. hmLayer.blurSize = seriesModel.get('blurSize');
  42919. hmLayer.pointSize = seriesModel.get('pointSize');
  42920. hmLayer.minOpacity = seriesModel.get('minOpacity');
  42921. hmLayer.maxOpacity = seriesModel.get('maxOpacity');
  42922. var rect = geo.getViewRect().clone();
  42923. var roamTransform = geo.getRoamTransform().transform;
  42924. rect.applyTransform(roamTransform);
  42925. // Clamp on viewport
  42926. var x = Math.max(rect.x, 0);
  42927. var y = Math.max(rect.y, 0);
  42928. var x2 = Math.min(rect.width + rect.x, api.getWidth());
  42929. var y2 = Math.min(rect.height + rect.y, api.getHeight());
  42930. var width = x2 - x;
  42931. var height = y2 - y;
  42932. var points = data.mapArray(['lng', 'lat', 'value'], function (lng, lat, value) {
  42933. var pt = geo.dataToPoint([lng, lat]);
  42934. pt[0] -= x;
  42935. pt[1] -= y;
  42936. pt.push(value);
  42937. return pt;
  42938. });
  42939. var dataExtent = visualMapModel.getExtent();
  42940. var isInRange = visualMapModel.type === 'visualMap.continuous'
  42941. ? getIsInContinuousRange(dataExtent, visualMapModel.option.range)
  42942. : getIsInPiecewiseRange(
  42943. dataExtent, visualMapModel.getPieceList(), visualMapModel.option.selected
  42944. );
  42945. hmLayer.update(
  42946. points, width, height,
  42947. inRangeVisuals.color.getNormalizer(),
  42948. {
  42949. inRange: inRangeVisuals.color.getColorMapper(),
  42950. outOfRange: outOfRangeVisuals.color.getColorMapper()
  42951. },
  42952. isInRange
  42953. );
  42954. var img = new graphic.Image({
  42955. style: {
  42956. width: width,
  42957. height: height,
  42958. x: x,
  42959. y: y,
  42960. image: hmLayer.canvas
  42961. },
  42962. silent: true
  42963. });
  42964. this.group.add(img);
  42965. }
  42966. });
  42967. /***/ },
  42968. /* 285 */
  42969. /***/ function(module, exports, __webpack_require__) {
  42970. /**
  42971. * @file defines echarts Heatmap Chart
  42972. * @author Ovilia (me@zhangwenli.com)
  42973. * Inspired by https://github.com/mourner/simpleheat
  42974. *
  42975. * @module
  42976. */
  42977. var GRADIENT_LEVELS = 256;
  42978. var zrUtil = __webpack_require__(4);
  42979. /**
  42980. * Heatmap Chart
  42981. *
  42982. * @class
  42983. */
  42984. function Heatmap() {
  42985. var canvas = zrUtil.createCanvas();
  42986. this.canvas = canvas;
  42987. this.blurSize = 30;
  42988. this.pointSize = 20;
  42989. this.maxOpacity = 1;
  42990. this.minOpacity = 0;
  42991. this._gradientPixels = {};
  42992. }
  42993. Heatmap.prototype = {
  42994. /**
  42995. * Renders Heatmap and returns the rendered canvas
  42996. * @param {Array} data array of data, each has x, y, value
  42997. * @param {number} width canvas width
  42998. * @param {number} height canvas height
  42999. */
  43000. update: function(data, width, height, normalize, colorFunc, isInRange) {
  43001. var brush = this._getBrush();
  43002. var gradientInRange = this._getGradient(data, colorFunc, 'inRange');
  43003. var gradientOutOfRange = this._getGradient(data, colorFunc, 'outOfRange');
  43004. var r = this.pointSize + this.blurSize;
  43005. var canvas = this.canvas;
  43006. var ctx = canvas.getContext('2d');
  43007. var len = data.length;
  43008. canvas.width = width;
  43009. canvas.height = height;
  43010. for (var i = 0; i < len; ++i) {
  43011. var p = data[i];
  43012. var x = p[0];
  43013. var y = p[1];
  43014. var value = p[2];
  43015. // calculate alpha using value
  43016. var alpha = normalize(value);
  43017. // draw with the circle brush with alpha
  43018. ctx.globalAlpha = alpha;
  43019. ctx.drawImage(brush, x - r, y - r);
  43020. }
  43021. // colorize the canvas using alpha value and set with gradient
  43022. var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  43023. var pixels = imageData.data;
  43024. var offset = 0;
  43025. var pixelLen = pixels.length;
  43026. var minOpacity = this.minOpacity;
  43027. var maxOpacity = this.maxOpacity;
  43028. var diffOpacity = maxOpacity - minOpacity;
  43029. while(offset < pixelLen) {
  43030. var alpha = pixels[offset + 3] / 256;
  43031. var gradientOffset = Math.floor(alpha * (GRADIENT_LEVELS - 1)) * 4;
  43032. // Simple optimize to ignore the empty data
  43033. if (alpha > 0) {
  43034. var gradient = isInRange(alpha) ? gradientInRange : gradientOutOfRange;
  43035. // Any alpha > 0 will be mapped to [minOpacity, maxOpacity]
  43036. alpha > 0 && (alpha = alpha * diffOpacity + minOpacity);
  43037. pixels[offset++] = gradient[gradientOffset];
  43038. pixels[offset++] = gradient[gradientOffset + 1];
  43039. pixels[offset++] = gradient[gradientOffset + 2];
  43040. pixels[offset++] = gradient[gradientOffset + 3] * alpha * 256;
  43041. }
  43042. else {
  43043. offset += 4;
  43044. }
  43045. }
  43046. ctx.putImageData(imageData, 0, 0);
  43047. return canvas;
  43048. },
  43049. /**
  43050. * get canvas of a black circle brush used for canvas to draw later
  43051. * @private
  43052. * @returns {Object} circle brush canvas
  43053. */
  43054. _getBrush: function() {
  43055. var brushCanvas = this._brushCanvas || (this._brushCanvas = zrUtil.createCanvas());
  43056. // set brush size
  43057. var r = this.pointSize + this.blurSize;
  43058. var d = r * 2;
  43059. brushCanvas.width = d;
  43060. brushCanvas.height = d;
  43061. var ctx = brushCanvas.getContext('2d');
  43062. ctx.clearRect(0, 0, d, d);
  43063. // in order to render shadow without the distinct circle,
  43064. // draw the distinct circle in an invisible place,
  43065. // and use shadowOffset to draw shadow in the center of the canvas
  43066. ctx.shadowOffsetX = d;
  43067. ctx.shadowBlur = this.blurSize;
  43068. // draw the shadow in black, and use alpha and shadow blur to generate
  43069. // color in color map
  43070. ctx.shadowColor = '#000';
  43071. // draw circle in the left to the canvas
  43072. ctx.beginPath();
  43073. ctx.arc(-r, r, this.pointSize, 0, Math.PI * 2, true);
  43074. ctx.closePath();
  43075. ctx.fill();
  43076. return brushCanvas;
  43077. },
  43078. /**
  43079. * get gradient color map
  43080. * @private
  43081. */
  43082. _getGradient: function (data, colorFunc, state) {
  43083. var gradientPixels = this._gradientPixels;
  43084. var pixelsSingleState = gradientPixels[state] || (gradientPixels[state] = new Uint8ClampedArray(256 * 4));
  43085. var color = [0, 0, 0, 0];
  43086. var off = 0;
  43087. for (var i = 0; i < 256; i++) {
  43088. colorFunc[state](i / 255, true, color);
  43089. pixelsSingleState[off++] = color[0];
  43090. pixelsSingleState[off++] = color[1];
  43091. pixelsSingleState[off++] = color[2];
  43092. pixelsSingleState[off++] = color[3];
  43093. }
  43094. return pixelsSingleState;
  43095. }
  43096. };
  43097. module.exports = Heatmap;
  43098. /***/ },
  43099. /* 286 */
  43100. /***/ function(module, exports, __webpack_require__) {
  43101. var zrUtil = __webpack_require__(4);
  43102. __webpack_require__(125);
  43103. __webpack_require__(287);
  43104. __webpack_require__(288);
  43105. var barLayoutGrid = __webpack_require__(145);
  43106. var echarts = __webpack_require__(1);
  43107. echarts.registerLayout(zrUtil.curry(barLayoutGrid, 'pictorialBar'));
  43108. echarts.registerVisual(zrUtil.curry(
  43109. __webpack_require__(121), 'pictorialBar', 'roundRect', null
  43110. ));
  43111. // In case developer forget to include grid component
  43112. __webpack_require__(124);
  43113. /***/ },
  43114. /* 287 */
  43115. /***/ function(module, exports, __webpack_require__) {
  43116. var PictorialBarSeries = __webpack_require__(141).extend({
  43117. type: 'series.pictorialBar',
  43118. dependencies: ['grid'],
  43119. defaultOption: {
  43120. symbol: 'circle', // Customized bar shape
  43121. symbolSize: null, // Can be ['100%', '100%'], null means auto.
  43122. symbolRotate: null,
  43123. symbolPosition: null, // 'start' or 'end' or 'center', null means auto.
  43124. symbolOffset: null,
  43125. symbolMargin: null, // start margin and end margin. Can be a number or a percent string.
  43126. // Auto margin by defualt.
  43127. symbolRepeat: false, // false/null/undefined, means no repeat.
  43128. // Can be true, means auto calculate repeat times and cut by data.
  43129. // Can be a number, specifies repeat times, and do not cut by data.
  43130. // Can be 'fixed', means auto calculate repeat times but do not cut by data.
  43131. symbolRepeatDirection: 'end', // 'end' means from 'start' to 'end'.
  43132. symbolClip: false,
  43133. symbolBoundingData: null,
  43134. symbolPatternSize: 400, // 400 * 400 px
  43135. barGap: '-100%', // In most case, overlap is needed.
  43136. // z can be set in data item, which is z2 actually.
  43137. // Disable progressive
  43138. progressive: 0,
  43139. hoverAnimation: false // Open only when needed.
  43140. },
  43141. getInitialData: function (option) {
  43142. // Disable stack.
  43143. option.stack = null;
  43144. return PictorialBarSeries.superApply(this, 'getInitialData', arguments);
  43145. }
  43146. });
  43147. module.exports = PictorialBarSeries;
  43148. /***/ },
  43149. /* 288 */
  43150. /***/ function(module, exports, __webpack_require__) {
  43151. var zrUtil = __webpack_require__(4);
  43152. var graphic = __webpack_require__(18);
  43153. var symbolUtil = __webpack_require__(111);
  43154. var numberUtil = __webpack_require__(7);
  43155. var helper = __webpack_require__(143);
  43156. var parsePercent = numberUtil.parsePercent;
  43157. var BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'normal', 'borderWidth'];
  43158. // index: +isHorizontal
  43159. var LAYOUT_ATTRS = [
  43160. {xy: 'x', wh: 'width', index: 0, posDesc: ['left', 'right']},
  43161. {xy: 'y', wh: 'height', index: 1, posDesc: ['top', 'bottom']}
  43162. ];
  43163. var pathForLineWidth = new graphic.Circle();
  43164. var BarView = __webpack_require__(1).extendChartView({
  43165. type: 'pictorialBar',
  43166. render: function (seriesModel, ecModel, api) {
  43167. var group = this.group;
  43168. var data = seriesModel.getData();
  43169. var oldData = this._data;
  43170. var cartesian = seriesModel.coordinateSystem;
  43171. var baseAxis = cartesian.getBaseAxis();
  43172. var isHorizontal = !!baseAxis.isHorizontal();
  43173. var coordSysRect = cartesian.grid.getRect();
  43174. var opt = {
  43175. ecSize: {width: api.getWidth(), height: api.getHeight()},
  43176. seriesModel: seriesModel,
  43177. coordSys: cartesian,
  43178. coordSysExtent: [
  43179. [coordSysRect.x, coordSysRect.x + coordSysRect.width],
  43180. [coordSysRect.y, coordSysRect.y + coordSysRect.height]
  43181. ],
  43182. isHorizontal: isHorizontal,
  43183. valueDim: LAYOUT_ATTRS[+isHorizontal],
  43184. categoryDim: LAYOUT_ATTRS[1 - isHorizontal]
  43185. };
  43186. data.diff(oldData)
  43187. .add(function (dataIndex) {
  43188. if (!data.hasValue(dataIndex)) {
  43189. return;
  43190. }
  43191. var itemModel = getItemModel(data, dataIndex);
  43192. var symbolMeta = getSymbolMeta(data, dataIndex, itemModel, opt);
  43193. var bar = createBar(data, opt, symbolMeta);
  43194. data.setItemGraphicEl(dataIndex, bar);
  43195. group.add(bar);
  43196. updateCommon(bar, opt, symbolMeta);
  43197. })
  43198. .update(function (newIndex, oldIndex) {
  43199. var bar = oldData.getItemGraphicEl(oldIndex);
  43200. if (!data.hasValue(newIndex)) {
  43201. group.remove(bar);
  43202. return;
  43203. }
  43204. var itemModel = getItemModel(data, newIndex);
  43205. var symbolMeta = getSymbolMeta(data, newIndex, itemModel, opt);
  43206. var pictorialShapeStr = getShapeStr(data, symbolMeta);
  43207. if (bar && pictorialShapeStr !== bar.__pictorialShapeStr) {
  43208. group.remove(bar);
  43209. data.setItemGraphicEl(newIndex, null);
  43210. bar = null;
  43211. }
  43212. if (bar) {
  43213. updateBar(bar, opt, symbolMeta);
  43214. }
  43215. else {
  43216. bar = createBar(data, opt, symbolMeta, true);
  43217. }
  43218. data.setItemGraphicEl(newIndex, bar);
  43219. bar.__pictorialSymbolMeta = symbolMeta;
  43220. // Add back
  43221. group.add(bar);
  43222. updateCommon(bar, opt, symbolMeta);
  43223. })
  43224. .remove(function (dataIndex) {
  43225. var bar = oldData.getItemGraphicEl(dataIndex);
  43226. bar && removeBar(oldData, dataIndex, bar.__pictorialSymbolMeta.animationModel, bar);
  43227. })
  43228. .execute();
  43229. this._data = data;
  43230. return this.group;
  43231. },
  43232. dispose: zrUtil.noop,
  43233. remove: function (ecModel, api) {
  43234. var group = this.group;
  43235. var data = this._data;
  43236. if (ecModel.get('animation')) {
  43237. if (data) {
  43238. data.eachItemGraphicEl(function (bar) {
  43239. removeBar(data, bar.dataIndex, ecModel, bar);
  43240. });
  43241. }
  43242. }
  43243. else {
  43244. group.removeAll();
  43245. }
  43246. }
  43247. });
  43248. // Set or calculate default value about symbol, and calculate layout info.
  43249. function getSymbolMeta(data, dataIndex, itemModel, opt) {
  43250. var layout = data.getItemLayout(dataIndex);
  43251. var symbolRepeat = itemModel.get('symbolRepeat');
  43252. var symbolClip = itemModel.get('symbolClip');
  43253. var symbolPosition = itemModel.get('symbolPosition') || 'start';
  43254. var symbolRotate = itemModel.get('symbolRotate');
  43255. var rotation = (symbolRotate || 0) * Math.PI / 180 || 0;
  43256. var symbolPatternSize = itemModel.get('symbolPatternSize') || 2;
  43257. var isAnimationEnabled = itemModel.isAnimationEnabled();
  43258. var symbolMeta = {
  43259. dataIndex: dataIndex,
  43260. layout: layout,
  43261. itemModel: itemModel,
  43262. symbolType: data.getItemVisual(dataIndex, 'symbol') || 'circle',
  43263. color: data.getItemVisual(dataIndex, 'color'),
  43264. symbolClip: symbolClip,
  43265. symbolRepeat: symbolRepeat,
  43266. symbolRepeatDirection: itemModel.get('symbolRepeatDirection'),
  43267. symbolPatternSize: symbolPatternSize,
  43268. rotation: rotation,
  43269. animationModel: isAnimationEnabled ? itemModel : null,
  43270. hoverAnimation: isAnimationEnabled && itemModel.get('hoverAnimation'),
  43271. z2: itemModel.getShallow('z', true) || 0
  43272. };
  43273. prepareBarLength(itemModel, symbolRepeat, layout, opt, symbolMeta);
  43274. prepareSymbolSize(
  43275. data, dataIndex, layout, symbolRepeat, symbolClip, symbolMeta.boundingLength,
  43276. symbolMeta.pxSign, symbolPatternSize, opt, symbolMeta
  43277. );
  43278. prepareLineWidth(itemModel, symbolMeta.symbolScale, rotation, opt, symbolMeta);
  43279. var symbolSize = symbolMeta.symbolSize;
  43280. var symbolOffset = itemModel.get('symbolOffset');
  43281. if (zrUtil.isArray(symbolOffset)) {
  43282. symbolOffset = [
  43283. parsePercent(symbolOffset[0], symbolSize[0]),
  43284. parsePercent(symbolOffset[1], symbolSize[1])
  43285. ];
  43286. }
  43287. prepareLayoutInfo(
  43288. itemModel, symbolSize, layout, symbolRepeat, symbolClip, symbolOffset,
  43289. symbolPosition, symbolMeta.valueLineWidth, symbolMeta.boundingLength, symbolMeta.repeatCutLength,
  43290. opt, symbolMeta
  43291. );
  43292. return symbolMeta;
  43293. }
  43294. // bar length can be negative.
  43295. function prepareBarLength(itemModel, symbolRepeat, layout, opt, output) {
  43296. var valueDim = opt.valueDim;
  43297. var symbolBoundingData = itemModel.get('symbolBoundingData');
  43298. var valueAxis = opt.coordSys.getOtherAxis(opt.coordSys.getBaseAxis());
  43299. var zeroPx = valueAxis.toGlobalCoord(valueAxis.dataToCoord(0));
  43300. var boundingLength = output.boundingLength = symbolBoundingData != null
  43301. ? valueAxis.toGlobalCoord(valueAxis.dataToCoord(valueAxis.scale.parse(symbolBoundingData))) - zeroPx
  43302. : symbolRepeat
  43303. ? opt.coordSysExtent[valueDim.index][1 - +(layout[valueDim.wh] <= 0)] - zeroPx
  43304. : layout[valueDim.wh];
  43305. if (symbolRepeat) {
  43306. output.repeatCutLength = layout[valueDim.wh];
  43307. }
  43308. output.pxSign = boundingLength > 0 ? 1 : boundingLength < 0 ? -1 : 0;
  43309. }
  43310. // Support ['100%', '100%']
  43311. function prepareSymbolSize(
  43312. data, dataIndex, layout, symbolRepeat, symbolClip, boundingLength,
  43313. pxSign, symbolPatternSize, opt, output
  43314. ) {
  43315. var valueDim = opt.valueDim;
  43316. var categoryDim = opt.categoryDim;
  43317. var categorySize = Math.abs(layout[categoryDim.wh]);
  43318. var symbolSize = data.getItemVisual(dataIndex, 'symbolSize');
  43319. if (zrUtil.isArray(symbolSize)) {
  43320. symbolSize = symbolSize.slice();
  43321. }
  43322. else {
  43323. if (symbolSize == null) {
  43324. symbolSize = '100%';
  43325. }
  43326. symbolSize = [symbolSize, symbolSize];
  43327. }
  43328. // Note: percentage symbolSize (like '100%') do not consider lineWidth, because it is
  43329. // to complicated to calculate real percent value if considering scaled lineWidth.
  43330. // So the actual size will bigger than layout size if lineWidth is bigger than zero,
  43331. // which can be tolerated in pictorial chart.
  43332. symbolSize[categoryDim.index] = parsePercent(
  43333. symbolSize[categoryDim.index],
  43334. categorySize
  43335. );
  43336. symbolSize[valueDim.index] = parsePercent(
  43337. symbolSize[valueDim.index],
  43338. symbolRepeat ? categorySize : Math.abs(boundingLength)
  43339. );
  43340. output.symbolSize = symbolSize;
  43341. // If x or y is less than zero, show reversed shape.
  43342. var symbolScale = output.symbolScale = [
  43343. symbolSize[0] / symbolPatternSize,
  43344. symbolSize[1] / symbolPatternSize
  43345. ];
  43346. // Follow convention, 'right' and 'top' is the normal scale.
  43347. symbolScale[valueDim.index] *= (opt.isHorizontal ? -1 : 1) * pxSign;
  43348. }
  43349. function prepareLineWidth(itemModel, symbolScale, rotation, opt, output) {
  43350. // In symbols are drawn with scale, so do not need to care about the case that width
  43351. // or height are too small. But symbol use strokeNoScale, where acture lineWidth should
  43352. // be calculated.
  43353. var valueLineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0;
  43354. if (valueLineWidth) {
  43355. pathForLineWidth.attr({
  43356. scale: symbolScale.slice(),
  43357. rotation: rotation
  43358. });
  43359. pathForLineWidth.updateTransform();
  43360. valueLineWidth /= pathForLineWidth.getLineScale();
  43361. valueLineWidth *= symbolScale[opt.valueDim.index];
  43362. }
  43363. output.valueLineWidth = valueLineWidth;
  43364. }
  43365. function prepareLayoutInfo(
  43366. itemModel, symbolSize, layout, symbolRepeat, symbolClip, symbolOffset,
  43367. symbolPosition, valueLineWidth, boundingLength, repeatCutLength, opt, output
  43368. ) {
  43369. var categoryDim = opt.categoryDim;
  43370. var valueDim = opt.valueDim;
  43371. var pxSign = output.pxSign;
  43372. var unitLength = Math.max(symbolSize[valueDim.index] + valueLineWidth, 0);
  43373. var pathLen = unitLength;
  43374. // Note: rotation will not effect the layout of symbols, because user may
  43375. // want symbols to rotate on its center, which should not be translated
  43376. // when rotating.
  43377. if (symbolRepeat) {
  43378. var absBoundingLength = Math.abs(boundingLength);
  43379. var symbolMargin = zrUtil.retrieve(itemModel.get('symbolMargin'), '15%') + '';
  43380. var hasEndGap = false;
  43381. if (symbolMargin.lastIndexOf('!') === symbolMargin.length - 1) {
  43382. hasEndGap = true;
  43383. symbolMargin = symbolMargin.slice(0, symbolMargin.length - 1);
  43384. }
  43385. symbolMargin = parsePercent(symbolMargin, symbolSize[valueDim.index]);
  43386. var uLenWithMargin = Math.max(unitLength + symbolMargin * 2, 0);
  43387. // When symbol margin is less than 0, margin at both ends will be subtracted
  43388. // to ensure that all of the symbols will not be overflow the given area.
  43389. var endFix = hasEndGap ? 0 : symbolMargin * 2;
  43390. // Both final repeatTimes and final symbolMargin area calculated based on
  43391. // boundingLength.
  43392. var repeatSpecified = numberUtil.isNumeric(symbolRepeat);
  43393. var repeatTimes = repeatSpecified
  43394. ? symbolRepeat
  43395. : toIntTimes((absBoundingLength + endFix) / uLenWithMargin);
  43396. // Adjust calculate margin, to ensure each symbol is displayed
  43397. // entirely in the given layout area.
  43398. var mDiff = absBoundingLength - repeatTimes * unitLength;
  43399. symbolMargin = mDiff / 2 / (hasEndGap ? repeatTimes : repeatTimes - 1);
  43400. uLenWithMargin = unitLength + symbolMargin * 2;
  43401. endFix = hasEndGap ? 0 : symbolMargin * 2;
  43402. // Update repeatTimes when not all symbol will be shown.
  43403. if (!repeatSpecified && symbolRepeat !== 'fixed') {
  43404. repeatTimes = repeatCutLength
  43405. ? toIntTimes((Math.abs(repeatCutLength) + endFix) / uLenWithMargin)
  43406. : 0;
  43407. }
  43408. pathLen = repeatTimes * uLenWithMargin - endFix;
  43409. output.repeatTimes = repeatTimes;
  43410. output.symbolMargin = symbolMargin;
  43411. }
  43412. var sizeFix = pxSign * (pathLen / 2);
  43413. var pathPosition = output.pathPosition = [];
  43414. pathPosition[categoryDim.index] = layout[categoryDim.wh] / 2;
  43415. pathPosition[valueDim.index] = symbolPosition === 'start'
  43416. ? sizeFix
  43417. : symbolPosition === 'end'
  43418. ? boundingLength - sizeFix
  43419. : boundingLength / 2; // 'center'
  43420. if (symbolOffset) {
  43421. pathPosition[0] += symbolOffset[0];
  43422. pathPosition[1] += symbolOffset[1];
  43423. }
  43424. var bundlePosition = output.bundlePosition = [];
  43425. bundlePosition[categoryDim.index] = layout[categoryDim.xy];
  43426. bundlePosition[valueDim.index] = layout[valueDim.xy];
  43427. var barRectShape = output.barRectShape = zrUtil.extend({}, layout);
  43428. barRectShape[valueDim.wh] = pxSign * Math.max(
  43429. Math.abs(layout[valueDim.wh]), Math.abs(pathPosition[valueDim.index] + sizeFix)
  43430. );
  43431. barRectShape[categoryDim.wh] = layout[categoryDim.wh];
  43432. var clipShape = output.clipShape = {};
  43433. // Consider that symbol may be overflow layout rect.
  43434. clipShape[categoryDim.xy] = -layout[categoryDim.xy];
  43435. clipShape[categoryDim.wh] = opt.ecSize[categoryDim.wh];
  43436. clipShape[valueDim.xy] = 0;
  43437. clipShape[valueDim.wh] = layout[valueDim.wh];
  43438. }
  43439. function createPath(symbolMeta) {
  43440. var symbolPatternSize = symbolMeta.symbolPatternSize;
  43441. var path = symbolUtil.createSymbol(
  43442. // Consider texture img, make a big size.
  43443. symbolMeta.symbolType,
  43444. -symbolPatternSize / 2,
  43445. -symbolPatternSize / 2,
  43446. symbolPatternSize,
  43447. symbolPatternSize,
  43448. symbolMeta.color
  43449. );
  43450. path.attr({
  43451. culling: true
  43452. });
  43453. path.type !== 'image' && path.setStyle({
  43454. strokeNoScale: true
  43455. });
  43456. return path;
  43457. }
  43458. function createOrUpdateRepeatSymbols(bar, opt, symbolMeta, isUpdate) {
  43459. var bundle = bar.__pictorialBundle;
  43460. var symbolSize = symbolMeta.symbolSize;
  43461. var valueLineWidth = symbolMeta.valueLineWidth;
  43462. var pathPosition = symbolMeta.pathPosition;
  43463. var valueDim = opt.valueDim;
  43464. var repeatTimes = symbolMeta.repeatTimes || 0;
  43465. var index = 0;
  43466. var unit = symbolSize[opt.valueDim.index] + valueLineWidth + symbolMeta.symbolMargin * 2;
  43467. eachPath(bar, function (path) {
  43468. path.__pictorialAnimationIndex = index;
  43469. path.__pictorialRepeatTimes = repeatTimes;
  43470. if (index < repeatTimes) {
  43471. updateAttr(path, null, makeTarget(index), symbolMeta, isUpdate);
  43472. }
  43473. else {
  43474. updateAttr(path, null, {scale: [0, 0]}, symbolMeta, isUpdate, function () {
  43475. bundle.remove(path);
  43476. });
  43477. }
  43478. updateHoverAnimation(path, symbolMeta);
  43479. index++;
  43480. });
  43481. for (; index < repeatTimes; index++) {
  43482. var path = createPath(symbolMeta);
  43483. path.__pictorialAnimationIndex = index;
  43484. path.__pictorialRepeatTimes = repeatTimes;
  43485. bundle.add(path);
  43486. var target = makeTarget(index, true);
  43487. updateAttr(
  43488. path,
  43489. {
  43490. position: target.position,
  43491. scale: [0, 0]
  43492. },
  43493. {
  43494. scale: target.scale,
  43495. rotation: target.rotation
  43496. },
  43497. symbolMeta,
  43498. isUpdate
  43499. );
  43500. // FIXME
  43501. // If all emphasis/normal through action.
  43502. path
  43503. .on('mouseover', onMouseOver)
  43504. .on('mouseout', onMouseOut);
  43505. updateHoverAnimation(path, symbolMeta);
  43506. }
  43507. function makeTarget(index) {
  43508. var position = pathPosition.slice();
  43509. // (start && pxSign > 0) || (end && pxSign < 0): i = repeatTimes - index
  43510. // Otherwise: i = index;
  43511. var pxSign = symbolMeta.pxSign;
  43512. var i = index;
  43513. if (symbolMeta.symbolRepeatDirection === 'start' ? pxSign > 0 : pxSign < 0) {
  43514. i = repeatTimes - 1 - index;
  43515. }
  43516. position[valueDim.index] = unit * (i - repeatTimes / 2 + 0.5) + pathPosition[valueDim.index];
  43517. return {
  43518. position: position,
  43519. scale: symbolMeta.symbolScale.slice(),
  43520. rotation: symbolMeta.rotation
  43521. };
  43522. }
  43523. function onMouseOver() {
  43524. eachPath(bar, function (path) {
  43525. path.trigger('emphasis');
  43526. });
  43527. }
  43528. function onMouseOut() {
  43529. eachPath(bar, function (path) {
  43530. path.trigger('normal');
  43531. });
  43532. }
  43533. }
  43534. function createOrUpdateSingleSymbol(bar, opt, symbolMeta, isUpdate) {
  43535. var bundle = bar.__pictorialBundle;
  43536. var mainPath = bar.__pictorialMainPath;
  43537. if (!mainPath) {
  43538. mainPath = bar.__pictorialMainPath = createPath(symbolMeta);
  43539. bundle.add(mainPath);
  43540. updateAttr(
  43541. mainPath,
  43542. {
  43543. position: symbolMeta.pathPosition.slice(),
  43544. scale: [0, 0],
  43545. rotation: symbolMeta.rotation
  43546. },
  43547. {
  43548. scale: symbolMeta.symbolScale.slice()
  43549. },
  43550. symbolMeta,
  43551. isUpdate
  43552. );
  43553. mainPath
  43554. .on('mouseover', onMouseOver)
  43555. .on('mouseout', onMouseOut);
  43556. }
  43557. else {
  43558. updateAttr(
  43559. mainPath,
  43560. null,
  43561. {
  43562. position: symbolMeta.pathPosition.slice(),
  43563. scale: symbolMeta.symbolScale.slice(),
  43564. rotation: symbolMeta.rotation
  43565. },
  43566. symbolMeta,
  43567. isUpdate
  43568. );
  43569. }
  43570. updateHoverAnimation(mainPath, symbolMeta);
  43571. function onMouseOver() {
  43572. this.trigger('emphasis');
  43573. }
  43574. function onMouseOut() {
  43575. this.trigger('normal');
  43576. }
  43577. }
  43578. // bar rect is used for label.
  43579. function createOrUpdateBarRect(bar, symbolMeta, isUpdate) {
  43580. var rectShape = zrUtil.extend({}, symbolMeta.barRectShape);
  43581. var barRect = bar.__pictorialBarRect;
  43582. if (!barRect) {
  43583. barRect = bar.__pictorialBarRect = new graphic.Rect({
  43584. z2: 2,
  43585. shape: rectShape,
  43586. silent: true,
  43587. style: {
  43588. stroke: 'transparent',
  43589. fill: 'transparent',
  43590. lineWidth: 0
  43591. }
  43592. });
  43593. bar.add(barRect);
  43594. }
  43595. else {
  43596. updateAttr(barRect, null, {shape: rectShape}, symbolMeta, isUpdate);
  43597. }
  43598. }
  43599. function createOrUpdateClip(bar, opt, symbolMeta, isUpdate) {
  43600. // If not clip, symbol will be remove and rebuilt.
  43601. if (symbolMeta.symbolClip) {
  43602. var clipPath = bar.__pictorialClipPath;
  43603. var clipShape = zrUtil.extend({}, symbolMeta.clipShape);
  43604. var valueDim = opt.valueDim;
  43605. var animationModel = symbolMeta.animationModel;
  43606. var dataIndex = symbolMeta.dataIndex;
  43607. if (clipPath) {
  43608. graphic.updateProps(
  43609. clipPath, {shape: clipShape}, animationModel, dataIndex
  43610. );
  43611. }
  43612. else {
  43613. clipShape[valueDim.wh] = 0;
  43614. clipPath = new graphic.Rect({shape: clipShape});
  43615. bar.__pictorialBundle.setClipPath(clipPath);
  43616. bar.__pictorialClipPath = clipPath;
  43617. var target = {};
  43618. target[valueDim.wh] = symbolMeta.clipShape[valueDim.wh];
  43619. graphic[isUpdate ? 'updateProps' : 'initProps'](
  43620. clipPath, {shape: target}, animationModel, dataIndex
  43621. );
  43622. }
  43623. }
  43624. }
  43625. function getItemModel(data, dataIndex) {
  43626. var itemModel = data.getItemModel(dataIndex);
  43627. itemModel.getAnimationDelayParams = getAnimationDelayParams;
  43628. itemModel.isAnimationEnabled = isAnimationEnabled;
  43629. return itemModel;
  43630. }
  43631. function getAnimationDelayParams(path) {
  43632. // The order is the same as the z-order, see `symbolRepeatDiretion`.
  43633. return {
  43634. index: path.__pictorialAnimationIndex,
  43635. count: path.__pictorialRepeatTimes
  43636. };
  43637. }
  43638. function isAnimationEnabled() {
  43639. // `animation` prop can be set on itemModel in pictorial bar chart.
  43640. return this.parentModel.isAnimationEnabled() && !!this.getShallow('animation');
  43641. }
  43642. function updateHoverAnimation(path, symbolMeta) {
  43643. path.off('emphasis').off('normal');
  43644. var scale = symbolMeta.symbolScale.slice();
  43645. symbolMeta.hoverAnimation && path
  43646. .on('emphasis', function() {
  43647. this.animateTo({
  43648. scale: [scale[0] * 1.1, scale[1] * 1.1]
  43649. }, 400, 'elasticOut');
  43650. })
  43651. .on('normal', function() {
  43652. this.animateTo({
  43653. scale: scale.slice()
  43654. }, 400, 'elasticOut');
  43655. });
  43656. }
  43657. function createBar(data, opt, symbolMeta, isUpdate) {
  43658. // bar is the main element for each data.
  43659. var bar = new graphic.Group();
  43660. // bundle is used for location and clip.
  43661. var bundle = new graphic.Group();
  43662. bar.add(bundle);
  43663. bar.__pictorialBundle = bundle;
  43664. bundle.attr('position', symbolMeta.bundlePosition.slice());
  43665. if (symbolMeta.symbolRepeat) {
  43666. createOrUpdateRepeatSymbols(bar, opt, symbolMeta);
  43667. }
  43668. else {
  43669. createOrUpdateSingleSymbol(bar, opt, symbolMeta);
  43670. }
  43671. createOrUpdateBarRect(bar, symbolMeta, isUpdate);
  43672. createOrUpdateClip(bar, opt, symbolMeta, isUpdate);
  43673. bar.__pictorialShapeStr = getShapeStr(data, symbolMeta);
  43674. bar.__pictorialSymbolMeta = symbolMeta;
  43675. return bar;
  43676. }
  43677. function updateBar(bar, opt, symbolMeta) {
  43678. var animationModel = symbolMeta.animationModel;
  43679. var dataIndex = symbolMeta.dataIndex;
  43680. var bundle = bar.__pictorialBundle;
  43681. graphic.updateProps(
  43682. bundle, {position: symbolMeta.bundlePosition.slice()}, animationModel, dataIndex
  43683. );
  43684. if (symbolMeta.symbolRepeat) {
  43685. createOrUpdateRepeatSymbols(bar, opt, symbolMeta, true);
  43686. }
  43687. else {
  43688. createOrUpdateSingleSymbol(bar, opt, symbolMeta, true);
  43689. }
  43690. createOrUpdateBarRect(bar, symbolMeta, true);
  43691. createOrUpdateClip(bar, opt, symbolMeta, true);
  43692. }
  43693. function removeBar(data, dataIndex, animationModel, bar) {
  43694. // Not show text when animating
  43695. var labelRect = bar.__pictorialBarRect;
  43696. labelRect && (labelRect.style.text = '');
  43697. var pathes = [];
  43698. eachPath(bar, function (path) {
  43699. pathes.push(path);
  43700. });
  43701. bar.__pictorialMainPath && pathes.push(bar.__pictorialMainPath);
  43702. // I do not find proper remove animation for clip yet.
  43703. bar.__pictorialClipPath && (animationModel = null);
  43704. zrUtil.each(pathes, function (path) {
  43705. graphic.updateProps(
  43706. path, {scale: [0, 0]}, animationModel, dataIndex,
  43707. function () {
  43708. bar.parent && bar.parent.remove(bar);
  43709. }
  43710. );
  43711. });
  43712. data.setItemGraphicEl(dataIndex, null);
  43713. }
  43714. function getShapeStr(data, symbolMeta) {
  43715. return [
  43716. data.getItemVisual(symbolMeta.dataIndex, 'symbol') || 'none',
  43717. !!symbolMeta.symbolRepeat,
  43718. !!symbolMeta.symbolClip
  43719. ].join(':');
  43720. }
  43721. function eachPath(bar, cb, context) {
  43722. // Do not use Group#eachChild, because it do not support remove.
  43723. zrUtil.each(bar.__pictorialBundle.children(), function (el) {
  43724. el !== bar.__pictorialBarRect && cb.call(context, el);
  43725. });
  43726. }
  43727. function updateAttr(el, immediateAttrs, animationAttrs, symbolMeta, isUpdate, cb) {
  43728. immediateAttrs && el.attr(immediateAttrs);
  43729. // when symbolCip used, only clip path has init animation, otherwise it would be weird effect.
  43730. if (symbolMeta.symbolClip && !isUpdate) {
  43731. animationAttrs && el.attr(animationAttrs);
  43732. }
  43733. else {
  43734. animationAttrs && graphic[isUpdate ? 'updateProps' : 'initProps'](
  43735. el, animationAttrs, symbolMeta.animationModel, symbolMeta.dataIndex, cb
  43736. );
  43737. }
  43738. }
  43739. function updateCommon(bar, opt, symbolMeta) {
  43740. var color = symbolMeta.color;
  43741. var dataIndex = symbolMeta.dataIndex;
  43742. var itemModel = symbolMeta.itemModel;
  43743. // Color must be excluded.
  43744. // Because symbol provide setColor individually to set fill and stroke
  43745. var normalStyle = itemModel.getModel('itemStyle.normal').getItemStyle(['color']);
  43746. var hoverStyle = itemModel.getModel('itemStyle.emphasis').getItemStyle();
  43747. eachPath(bar, function (path) {
  43748. // PENDING setColor should be before setStyle!!!
  43749. path.setColor(color);
  43750. path.setStyle(zrUtil.defaults(
  43751. {
  43752. fill: color,
  43753. opacity: symbolMeta.opacity
  43754. },
  43755. normalStyle
  43756. ));
  43757. graphic.setHoverStyle(path, hoverStyle);
  43758. path.z2 = symbolMeta.z2;
  43759. });
  43760. var barRectHoverStyle = {};
  43761. var barPositionOutside = opt.valueDim.posDesc[+(symbolMeta.boundingLength > 0)];
  43762. var barRect = bar.__pictorialBarRect;
  43763. helper.setLabel(
  43764. barRect.style, barRectHoverStyle, itemModel,
  43765. color, opt.seriesModel, dataIndex, barPositionOutside
  43766. );
  43767. graphic.setHoverStyle(barRect, barRectHoverStyle);
  43768. }
  43769. function toIntTimes(times) {
  43770. var roundedTimes = Math.round(times);
  43771. // Escapse accurate error
  43772. return Math.abs(times - roundedTimes) < 1e-4
  43773. ? roundedTimes
  43774. : Math.ceil(times);
  43775. }
  43776. module.exports = BarView;
  43777. /***/ },
  43778. /* 289 */
  43779. /***/ function(module, exports, __webpack_require__) {
  43780. var echarts = __webpack_require__(1);
  43781. var zrUtil = __webpack_require__(4);
  43782. __webpack_require__(290);
  43783. __webpack_require__(307);
  43784. __webpack_require__(308);
  43785. echarts.registerLayout(__webpack_require__(310));
  43786. echarts.registerVisual(__webpack_require__(311));
  43787. echarts.registerProcessor(
  43788. zrUtil.curry(__webpack_require__(154), 'themeRiver')
  43789. );
  43790. /***/ },
  43791. /* 290 */
  43792. /***/ function(module, exports, __webpack_require__) {
  43793. __webpack_require__(291);
  43794. __webpack_require__(294);
  43795. __webpack_require__(296);
  43796. __webpack_require__(297);
  43797. __webpack_require__(306);
  43798. var echarts = __webpack_require__(1);
  43799. echarts.extendComponentView({
  43800. type: 'single'
  43801. });
  43802. /***/ },
  43803. /* 291 */
  43804. /***/ function(module, exports, __webpack_require__) {
  43805. /**
  43806. * Single coordinate system creator.
  43807. */
  43808. var Single = __webpack_require__(292);
  43809. /**
  43810. * Create single coordinate system and inject it into seriesModel.
  43811. *
  43812. * @param {module:echarts/model/Global} ecModel
  43813. * @param {module:echarts/ExtensionAPI} api
  43814. * @return {Array.<module:echarts/coord/single/Single>}
  43815. */
  43816. function create(ecModel, api) {
  43817. var singles = [];
  43818. ecModel.eachComponent('singleAxis', function(axisModel, idx) {
  43819. var single = new Single(axisModel, ecModel, api);
  43820. single.name = 'single_' + idx;
  43821. single.resize(axisModel, api);
  43822. axisModel.coordinateSystem = single;
  43823. singles.push(single);
  43824. });
  43825. ecModel.eachSeries(function (seriesModel) {
  43826. if (seriesModel.get('coordinateSystem') === 'singleAxis') {
  43827. var singleAxisModel = ecModel.queryComponents({
  43828. mainType: 'singleAxis',
  43829. index: seriesModel.get('singleAxisIndex'),
  43830. id: seriesModel.get('singleAxisId')
  43831. })[0];
  43832. seriesModel.coordinateSystem = singleAxisModel && singleAxisModel.coordinateSystem;
  43833. }
  43834. });
  43835. return singles;
  43836. }
  43837. __webpack_require__(76).register('single', {
  43838. create: create,
  43839. dimensions: Single.prototype.dimensions
  43840. });
  43841. /***/ },
  43842. /* 292 */
  43843. /***/ function(module, exports, __webpack_require__) {
  43844. /**
  43845. * Single coordinates system.
  43846. */
  43847. var SingleAxis = __webpack_require__(293);
  43848. var axisHelper = __webpack_require__(101);
  43849. var layout = __webpack_require__(71);
  43850. /**
  43851. * Create a single coordinates system.
  43852. *
  43853. * @param {module:echarts/coord/single/AxisModel} axisModel
  43854. * @param {module:echarts/model/Global} ecModel
  43855. * @param {module:echarts/ExtensionAPI} api
  43856. */
  43857. function Single(axisModel, ecModel, api) {
  43858. /**
  43859. * @type {string}
  43860. * @readOnly
  43861. */
  43862. this.dimension = 'single';
  43863. /**
  43864. * Add it just for draw tooltip.
  43865. *
  43866. * @type {Array.<string>}
  43867. * @readOnly
  43868. */
  43869. this.dimensions = ['single'];
  43870. /**
  43871. * @private
  43872. * @type {module:echarts/coord/single/SingleAxis}.
  43873. */
  43874. this._axis = null;
  43875. /**
  43876. * @private
  43877. * @type {module:zrender/core/BoundingRect}
  43878. */
  43879. this._rect;
  43880. this._init(axisModel, ecModel, api);
  43881. /**
  43882. * @type {module:echarts/coord/single/AxisModel}
  43883. */
  43884. this.model = axisModel;
  43885. }
  43886. Single.prototype = {
  43887. type: 'singleAxis',
  43888. axisPointerEnabled: true,
  43889. constructor: Single,
  43890. /**
  43891. * Initialize single coordinate system.
  43892. *
  43893. * @param {module:echarts/coord/single/AxisModel} axisModel
  43894. * @param {module:echarts/model/Global} ecModel
  43895. * @param {module:echarts/ExtensionAPI} api
  43896. * @private
  43897. */
  43898. _init: function (axisModel, ecModel, api) {
  43899. var dim = this.dimension;
  43900. var axis = new SingleAxis(
  43901. dim,
  43902. axisHelper.createScaleByModel(axisModel),
  43903. [0, 0],
  43904. axisModel.get('type'),
  43905. axisModel.get('position')
  43906. );
  43907. var isCategory = axis.type === 'category';
  43908. axis.onBand = isCategory && axisModel.get('boundaryGap');
  43909. axis.inverse = axisModel.get('inverse');
  43910. axis.orient = axisModel.get('orient');
  43911. axisModel.axis = axis;
  43912. axis.model = axisModel;
  43913. axis.coordinateSystem = this;
  43914. this._axis = axis;
  43915. },
  43916. /**
  43917. * Update axis scale after data processed
  43918. * @param {module:echarts/model/Global} ecModel
  43919. * @param {module:echarts/ExtensionAPI} api
  43920. */
  43921. update: function (ecModel, api) {
  43922. ecModel.eachSeries(function (seriesModel) {
  43923. if (seriesModel.coordinateSystem === this) {
  43924. var data = seriesModel.getData();
  43925. var dim = this.dimension;
  43926. this._axis.scale.unionExtentFromData(
  43927. data, seriesModel.coordDimToDataDim(dim)
  43928. );
  43929. axisHelper.niceScaleExtent(this._axis.scale, this._axis.model);
  43930. }
  43931. }, this);
  43932. },
  43933. /**
  43934. * Resize the single coordinate system.
  43935. *
  43936. * @param {module:echarts/coord/single/AxisModel} axisModel
  43937. * @param {module:echarts/ExtensionAPI} api
  43938. */
  43939. resize: function (axisModel, api) {
  43940. this._rect = layout.getLayoutRect(
  43941. {
  43942. left: axisModel.get('left'),
  43943. top: axisModel.get('top'),
  43944. right: axisModel.get('right'),
  43945. bottom: axisModel.get('bottom'),
  43946. width: axisModel.get('width'),
  43947. height: axisModel.get('height')
  43948. },
  43949. {
  43950. width: api.getWidth(),
  43951. height: api.getHeight()
  43952. }
  43953. );
  43954. this._adjustAxis();
  43955. },
  43956. /**
  43957. * @return {module:zrender/core/BoundingRect}
  43958. */
  43959. getRect: function () {
  43960. return this._rect;
  43961. },
  43962. /**
  43963. * @private
  43964. */
  43965. _adjustAxis: function () {
  43966. var rect = this._rect;
  43967. var axis = this._axis;
  43968. var isHorizontal = axis.isHorizontal();
  43969. var extent = isHorizontal ? [0, rect.width] : [0, rect.height];
  43970. var idx = axis.reverse ? 1 : 0;
  43971. axis.setExtent(extent[idx], extent[1 - idx]);
  43972. this._updateAxisTransform(axis, isHorizontal ? rect.x : rect.y);
  43973. },
  43974. /**
  43975. * @param {module:echarts/coord/single/SingleAxis} axis
  43976. * @param {number} coordBase
  43977. */
  43978. _updateAxisTransform: function (axis, coordBase) {
  43979. var axisExtent = axis.getExtent();
  43980. var extentSum = axisExtent[0] + axisExtent[1];
  43981. var isHorizontal = axis.isHorizontal();
  43982. axis.toGlobalCoord = isHorizontal
  43983. ? function (coord) {
  43984. return coord + coordBase;
  43985. }
  43986. : function (coord) {
  43987. return extentSum - coord + coordBase;
  43988. };
  43989. axis.toLocalCoord = isHorizontal
  43990. ? function (coord) {
  43991. return coord - coordBase;
  43992. }
  43993. : function (coord) {
  43994. return extentSum - coord + coordBase;
  43995. };
  43996. },
  43997. /**
  43998. * Get axis.
  43999. *
  44000. * @return {module:echarts/coord/single/SingleAxis}
  44001. */
  44002. getAxis: function () {
  44003. return this._axis;
  44004. },
  44005. /**
  44006. * Get axis, add it just for draw tooltip.
  44007. *
  44008. * @return {[type]} [description]
  44009. */
  44010. getBaseAxis: function () {
  44011. return this._axis;
  44012. },
  44013. /**
  44014. * @return {Array.<module:echarts/coord/Axis>}
  44015. */
  44016. getAxes: function () {
  44017. return [this._axis];
  44018. },
  44019. /**
  44020. * @return {Object} {baseAxes: [], otherAxes: []}
  44021. */
  44022. getTooltipAxes: function () {
  44023. return {baseAxes: [this.getAxis()]};
  44024. },
  44025. /**
  44026. * If contain point.
  44027. *
  44028. * @param {Array.<number>} point
  44029. * @return {boolean}
  44030. */
  44031. containPoint: function (point) {
  44032. var rect = this.getRect();
  44033. var axis = this.getAxis();
  44034. var orient = axis.orient;
  44035. if (orient === 'horizontal') {
  44036. return axis.contain(axis.toLocalCoord(point[0]))
  44037. && (point[1] >= rect.y && point[1] <= (rect.y + rect.height));
  44038. }
  44039. else {
  44040. return axis.contain(axis.toLocalCoord(point[1]))
  44041. && (point[0] >= rect.y && point[0] <= (rect.y + rect.height));
  44042. }
  44043. },
  44044. /**
  44045. * @param {Array.<number>} point
  44046. * @return {Array.<number>}
  44047. */
  44048. pointToData: function (point) {
  44049. var axis = this.getAxis();
  44050. return [axis.coordToData(axis.toLocalCoord(
  44051. point[axis.orient === 'horizontal' ? 0 : 1]
  44052. ))];
  44053. },
  44054. /**
  44055. * Convert the series data to concrete point.
  44056. *
  44057. * @param {number|Array.<number>} val
  44058. * @return {Array.<number>}
  44059. */
  44060. dataToPoint: function (val) {
  44061. var axis = this.getAxis();
  44062. var rect = this.getRect();
  44063. var pt = [];
  44064. var idx = axis.orient === 'horizontal' ? 0 : 1;
  44065. if (val instanceof Array) {
  44066. val = val[0];
  44067. }
  44068. pt[idx] = axis.toGlobalCoord(axis.dataToCoord(+val));
  44069. pt[1 - idx] = idx === 0 ? (rect.y + rect.height / 2) : (rect.x + rect.width / 2);
  44070. return pt;
  44071. }
  44072. };
  44073. module.exports = Single;
  44074. /***/ },
  44075. /* 293 */
  44076. /***/ function(module, exports, __webpack_require__) {
  44077. var zrUtil = __webpack_require__(4);
  44078. var Axis = __webpack_require__(100);
  44079. /**
  44080. * @constructor module:echarts/coord/single/SingleAxis
  44081. * @extends {module:echarts/coord/Axis}
  44082. * @param {string} dim
  44083. * @param {*} scale
  44084. * @param {Array.<number>} coordExtent
  44085. * @param {string} axisType
  44086. * @param {string} position
  44087. */
  44088. var SingleAxis = function (dim, scale, coordExtent, axisType, position) {
  44089. Axis.call(this, dim, scale, coordExtent);
  44090. /**
  44091. * Axis type
  44092. * - 'category'
  44093. * - 'value'
  44094. * - 'time'
  44095. * - 'log'
  44096. * @type {string}
  44097. */
  44098. this.type = axisType || 'value';
  44099. /**
  44100. * Axis position
  44101. * - 'top'
  44102. * - 'bottom'
  44103. * - 'left'
  44104. * - 'right'
  44105. * @type {string}
  44106. */
  44107. this.position = position || 'bottom';
  44108. /**
  44109. * Axis orient
  44110. * - 'horizontal'
  44111. * - 'vertical'
  44112. * @type {[type]}
  44113. */
  44114. this.orient = null;
  44115. /**
  44116. * @type {number}
  44117. */
  44118. this._labelInterval = null;
  44119. };
  44120. SingleAxis.prototype = {
  44121. constructor: SingleAxis,
  44122. /**
  44123. * Axis model
  44124. * @type {module:echarts/coord/single/AxisModel}
  44125. */
  44126. model: null,
  44127. /**
  44128. * Judge the orient of the axis.
  44129. * @return {boolean}
  44130. */
  44131. isHorizontal: function () {
  44132. var position = this.position;
  44133. return position === 'top' || position === 'bottom';
  44134. },
  44135. /**
  44136. * @override
  44137. */
  44138. pointToData: function (point, clamp) {
  44139. return this.coordinateSystem.pointToData(point, clamp)[0];
  44140. },
  44141. /**
  44142. * Convert the local coord(processed by dataToCoord())
  44143. * to global coord(concrete pixel coord).
  44144. * designated by module:echarts/coord/single/Single.
  44145. * @type {Function}
  44146. */
  44147. toGlobalCoord: null,
  44148. /**
  44149. * Convert the global coord to local coord.
  44150. * designated by module:echarts/coord/single/Single.
  44151. * @type {Function}
  44152. */
  44153. toLocalCoord: null
  44154. };
  44155. zrUtil.inherits(SingleAxis, Axis);
  44156. module.exports = SingleAxis;
  44157. /***/ },
  44158. /* 294 */
  44159. /***/ function(module, exports, __webpack_require__) {
  44160. var AxisBuilder = __webpack_require__(135);
  44161. var zrUtil = __webpack_require__(4);
  44162. var graphic = __webpack_require__(18);
  44163. var singleAxisHelper = __webpack_require__(295);
  44164. var getInterval = AxisBuilder.getInterval;
  44165. var ifIgnoreOnTick = AxisBuilder.ifIgnoreOnTick;
  44166. var axisBuilderAttrs = [
  44167. 'axisLine', 'axisLabel', 'axisTick', 'axisName'
  44168. ];
  44169. var selfBuilderAttr = 'splitLine';
  44170. var SingleAxisView = __webpack_require__(136).extend({
  44171. type: 'singleAxis',
  44172. axisPointerClass: 'SingleAxisPointer',
  44173. render: function (axisModel, ecModel, api, payload) {
  44174. var group = this.group;
  44175. group.removeAll();
  44176. var layout = singleAxisHelper.layout(axisModel);
  44177. var axisBuilder = new AxisBuilder(axisModel, layout);
  44178. zrUtil.each(axisBuilderAttrs, axisBuilder.add, axisBuilder);
  44179. group.add(axisBuilder.getGroup());
  44180. if (axisModel.get(selfBuilderAttr + '.show')) {
  44181. this['_' + selfBuilderAttr](axisModel, layout.labelInterval);
  44182. }
  44183. SingleAxisView.superCall(this, 'render', axisModel, ecModel, api, payload);
  44184. },
  44185. _splitLine: function(axisModel, labelInterval) {
  44186. var axis = axisModel.axis;
  44187. if (axis.scale.isBlank()) {
  44188. return;
  44189. }
  44190. var splitLineModel = axisModel.getModel('splitLine');
  44191. var lineStyleModel = splitLineModel.getModel('lineStyle');
  44192. var lineWidth = lineStyleModel.get('width');
  44193. var lineColors = lineStyleModel.get('color');
  44194. var lineInterval = getInterval(splitLineModel, labelInterval);
  44195. lineColors = lineColors instanceof Array ? lineColors : [lineColors];
  44196. var gridRect = axisModel.coordinateSystem.getRect();
  44197. var isHorizontal = axis.isHorizontal();
  44198. var splitLines = [];
  44199. var lineCount = 0;
  44200. var ticksCoords = axis.getTicksCoords();
  44201. var p1 = [];
  44202. var p2 = [];
  44203. for (var i = 0; i < ticksCoords.length; ++i) {
  44204. if (ifIgnoreOnTick(axis, i, lineInterval)) {
  44205. continue;
  44206. }
  44207. var tickCoord = axis.toGlobalCoord(ticksCoords[i]);
  44208. if (isHorizontal) {
  44209. p1[0] = tickCoord;
  44210. p1[1] = gridRect.y;
  44211. p2[0] = tickCoord;
  44212. p2[1] = gridRect.y + gridRect.height;
  44213. }
  44214. else {
  44215. p1[0] = gridRect.x;
  44216. p1[1] = tickCoord;
  44217. p2[0] = gridRect.x + gridRect.width;
  44218. p2[1] = tickCoord;
  44219. }
  44220. var colorIndex = (lineCount++) % lineColors.length;
  44221. splitLines[colorIndex] = splitLines[colorIndex] || [];
  44222. splitLines[colorIndex].push(new graphic.Line(
  44223. graphic.subPixelOptimizeLine({
  44224. shape: {
  44225. x1: p1[0],
  44226. y1: p1[1],
  44227. x2: p2[0],
  44228. y2: p2[1]
  44229. },
  44230. style: {
  44231. lineWidth: lineWidth
  44232. },
  44233. silent: true
  44234. })));
  44235. }
  44236. for (var i = 0; i < splitLines.length; ++i) {
  44237. this.group.add(graphic.mergePath(splitLines[i], {
  44238. style: {
  44239. stroke: lineColors[i % lineColors.length],
  44240. lineDash: lineStyleModel.getLineDash(lineWidth),
  44241. lineWidth: lineWidth
  44242. },
  44243. silent: true
  44244. }));
  44245. }
  44246. }
  44247. });
  44248. module.exports = SingleAxisView;
  44249. /***/ },
  44250. /* 295 */
  44251. /***/ function(module, exports, __webpack_require__) {
  44252. var zrUtil = __webpack_require__(4);
  44253. var helper = {};
  44254. /**
  44255. * @param {Object} opt {labelInside}
  44256. * @return {Object} {
  44257. * position, rotation, labelDirection, labelOffset,
  44258. * tickDirection, labelRotate, labelInterval, z2
  44259. * }
  44260. */
  44261. helper.layout = function (axisModel, opt) {
  44262. opt = opt || {};
  44263. var single = axisModel.coordinateSystem;
  44264. var axis = axisModel.axis;
  44265. var layout = {};
  44266. var axisPosition = axis.position;
  44267. var orient = axis.orient;
  44268. var rect = single.getRect();
  44269. var rectBound = [rect.x, rect.x + rect.width, rect.y, rect.y + rect.height];
  44270. var positionMap = {
  44271. horizontal: {top: rectBound[2], bottom: rectBound[3]},
  44272. vertical: {left: rectBound[0], right: rectBound[1]}
  44273. };
  44274. layout.position = [
  44275. orient === 'vertical'
  44276. ? positionMap.vertical[axisPosition]
  44277. : rectBound[0],
  44278. orient === 'horizontal'
  44279. ? positionMap.horizontal[axisPosition]
  44280. : rectBound[3]
  44281. ];
  44282. var r = {horizontal: 0, vertical: 1};
  44283. layout.rotation = Math.PI / 2 * r[orient];
  44284. var directionMap = {top: -1, bottom: 1, right: 1, left: -1};
  44285. layout.labelDirection = layout.tickDirection
  44286. = layout.nameDirection
  44287. = directionMap[axisPosition];
  44288. if (axisModel.get('axisTick.inside')) {
  44289. layout.tickDirection = -layout.tickDirection;
  44290. }
  44291. if (zrUtil.retrieve(opt.labelInside, axisModel.get('axisLabel.inside'))) {
  44292. layout.labelDirection = -layout.labelDirection;
  44293. }
  44294. var labelRotation = opt.rotate;
  44295. labelRotation == null && (labelRotation = axisModel.get('axisLabel.rotate'));
  44296. layout.labelRotation = axisPosition === 'top' ? -labelRotation : labelRotation;
  44297. layout.labelInterval = axis.getLabelInterval();
  44298. layout.z2 = 1;
  44299. return layout;
  44300. };
  44301. module.exports = helper;
  44302. /***/ },
  44303. /* 296 */
  44304. /***/ function(module, exports, __webpack_require__) {
  44305. var ComponentModel = __webpack_require__(69);
  44306. var axisModelCreator = __webpack_require__(131);
  44307. var zrUtil = __webpack_require__(4);
  44308. var AxisModel = ComponentModel.extend({
  44309. type: 'singleAxis',
  44310. layoutMode: 'box',
  44311. /**
  44312. * @type {module:echarts/coord/single/SingleAxis}
  44313. */
  44314. axis: null,
  44315. /**
  44316. * @type {module:echarts/coord/single/Single}
  44317. */
  44318. coordinateSystem: null,
  44319. /**
  44320. * @override
  44321. */
  44322. getCoordSysModel: function () {
  44323. return this;
  44324. }
  44325. });
  44326. var defaultOption = {
  44327. left: '5%',
  44328. top: '5%',
  44329. right: '5%',
  44330. bottom: '5%',
  44331. type: 'value',
  44332. position: 'bottom',
  44333. orient: 'horizontal',
  44334. axisLine: {
  44335. show: true,
  44336. lineStyle: {
  44337. width: 2,
  44338. type: 'solid'
  44339. }
  44340. },
  44341. // Single coordinate system and single axis is the,
  44342. // which is used as the parent tooltip model.
  44343. // same model, so we set default tooltip show as true.
  44344. tooltip: {
  44345. show: true
  44346. },
  44347. axisTick: {
  44348. show: true,
  44349. length: 6,
  44350. lineStyle: {
  44351. width: 2
  44352. }
  44353. },
  44354. axisLabel: {
  44355. show: true,
  44356. interval: 'auto'
  44357. },
  44358. splitLine: {
  44359. show: true,
  44360. lineStyle: {
  44361. type: 'dashed',
  44362. opacity: 0.2
  44363. }
  44364. }
  44365. };
  44366. function getAxisType(axisName, option) {
  44367. return option.type || (option.data ? 'category' : 'value');
  44368. }
  44369. zrUtil.merge(AxisModel.prototype, __webpack_require__(112));
  44370. axisModelCreator('single', AxisModel, getAxisType, defaultOption);
  44371. module.exports = AxisModel;
  44372. /***/ },
  44373. /* 297 */
  44374. /***/ function(module, exports, __webpack_require__) {
  44375. var echarts = __webpack_require__(1);
  44376. var axisPointerModelHelper = __webpack_require__(137);
  44377. var axisTrigger = __webpack_require__(298);
  44378. var zrUtil = __webpack_require__(4);
  44379. __webpack_require__(300);
  44380. __webpack_require__(301);
  44381. // CartesianAxisPointer is not supposed to be required here. But consider
  44382. // echarts.simple.js and online build tooltip, which only require gridSimple,
  44383. // CartesianAxisPointer should be able to required somewhere.
  44384. __webpack_require__(303);
  44385. echarts.registerPreprocessor(function (option) {
  44386. // Always has a global axisPointerModel for default setting.
  44387. if (option) {
  44388. (!option.axisPointer || option.axisPointer.length === 0)
  44389. && (option.axisPointer = {});
  44390. var link = option.axisPointer.link;
  44391. // Normalize to array to avoid object mergin. But if link
  44392. // is not set, remain null/undefined, otherwise it will
  44393. // override existent link setting.
  44394. if (link && !zrUtil.isArray(link)) {
  44395. option.axisPointer.link = [link];
  44396. }
  44397. }
  44398. });
  44399. // This process should proformed after coordinate systems created
  44400. // and series data processed. So put it on statistic processing stage.
  44401. echarts.registerProcessor(echarts.PRIORITY.PROCESSOR.STATISTIC, function (ecModel, api) {
  44402. // Build axisPointerModel, mergin tooltip.axisPointer model for each axis.
  44403. // allAxesInfo should be updated when setOption performed.
  44404. ecModel.getComponent('axisPointer').coordSysAxesInfo
  44405. = axisPointerModelHelper.collect(ecModel, api);
  44406. });
  44407. // Broadcast to all views.
  44408. echarts.registerAction({
  44409. type: 'updateAxisPointer',
  44410. event: 'updateAxisPointer',
  44411. update: ':updateAxisPointer'
  44412. }, function (payload, ecModel, api) {
  44413. var outputFinder = axisTrigger(
  44414. ecModel.getComponent('axisPointer').coordSysAxesInfo,
  44415. payload.currTrigger,
  44416. [payload.x, payload.y],
  44417. payload,
  44418. payload.dispatchAction || zrUtil.bind(api.dispatchAction, api),
  44419. ecModel,
  44420. api,
  44421. payload.tooltipOption
  44422. );
  44423. return outputFinder;
  44424. });
  44425. /***/ },
  44426. /* 298 */
  44427. /***/ function(module, exports, __webpack_require__) {
  44428. var zrUtil = __webpack_require__(4);
  44429. var modelUtil = __webpack_require__(5);
  44430. var modelHelper = __webpack_require__(137);
  44431. var findPointFromSeries = __webpack_require__(299);
  44432. var each = zrUtil.each;
  44433. var curry = zrUtil.curry;
  44434. var get = modelUtil.makeGetter();
  44435. /**
  44436. * Basic logic: check all axis, if they do not demand show/highlight,
  44437. * then hide/downplay them.
  44438. *
  44439. * @param {Object} coordSysAxesInfo
  44440. * @param {string} [currTrigger] 'click' | 'mousemove' | 'leave'
  44441. * @param {Array.<number>} [point] x and y, which are mandatory, specify a point to
  44442. * tigger axisPointer and tooltip.
  44443. * @param {Object} [finder] {
  44444. * seriesIndex, dataIndex,
  44445. * axesInfo: [{
  44446. * axisDim: 'x'|'y'|'angle'|..., axisIndex: ..., value: ...
  44447. * }, ...]
  44448. * }
  44449. * These properties, which are optional, restrict target axes.
  44450. * @param {Function} dispatchAction
  44451. * @param {module:echarts/ExtensionAPI} api
  44452. * @param {Object} [tooltipOption]
  44453. * @return {Object} content of event obj for echarts.connect.
  44454. */
  44455. function axisTrigger(
  44456. coordSysAxesInfo, currTrigger, point, finder, dispatchAction,
  44457. ecModel, api, tooltipOption
  44458. ) {
  44459. finder = finder || {};
  44460. if (illegalPoint(point)) {
  44461. // Used in the default behavior of `connection`: use the sample seriesIndex
  44462. // and dataIndex. And also used in the tooltipView trigger.
  44463. point = findPointFromSeries({
  44464. seriesIndex: finder.seriesIndex,
  44465. // Do not use dataIndexInside from other ec instance.
  44466. // FIXME: auto detect it?
  44467. dataIndex: finder.dataIndex
  44468. }, ecModel).point;
  44469. }
  44470. var isIllegalPoint = illegalPoint(point);
  44471. // Axis and value can be specified when calling dispatchAction({type: 'updateAxisPointer'}).
  44472. // Notice: In this case, it is difficult to get the `point` (which is necessary to show
  44473. // tooltip, so if point is not given, we just use the point found by sample seriesIndex
  44474. // and dataIndex.
  44475. var inputAxesInfo = finder.axesInfo;
  44476. var axesInfo = coordSysAxesInfo.axesInfo;
  44477. var shouldHide = currTrigger === 'leave' || illegalPoint(point);
  44478. var outputFinder = {};
  44479. var showValueMap = {};
  44480. var dataByCoordSys = {list: [], map: {}};
  44481. var updaters = {
  44482. showPointer: curry(showPointer, showValueMap),
  44483. showTooltip: curry(showTooltip, dataByCoordSys)
  44484. };
  44485. // Process for triggered axes.
  44486. each(coordSysAxesInfo.coordSysMap, function (coordSys, coordSysKey) {
  44487. // If a point given, it must be contained by the coordinate system.
  44488. var coordSysContainsPoint = isIllegalPoint || coordSys.containPoint(point);
  44489. each(coordSysAxesInfo.coordSysAxesInfo[coordSysKey], function (axisInfo, key) {
  44490. var axis = axisInfo.axis;
  44491. var inputAxisInfo = findInputAxisInfo(inputAxesInfo, axisInfo);
  44492. // If no inputAxesInfo, no axis is restricted.
  44493. if (!shouldHide && coordSysContainsPoint && (!inputAxesInfo || inputAxisInfo)) {
  44494. var val = inputAxisInfo && inputAxisInfo.value;
  44495. if (val == null && !isIllegalPoint) {
  44496. val = axis.pointToData(point);
  44497. }
  44498. val != null && processOnAxis(axisInfo, val, updaters, false, outputFinder);
  44499. }
  44500. });
  44501. });
  44502. // Process for linked axes.
  44503. var linkTriggers = {};
  44504. each(axesInfo, function (tarAxisInfo, tarKey) {
  44505. var linkGroup = tarAxisInfo.linkGroup;
  44506. // If axis has been triggered in the previous stage, it should not be triggered by link.
  44507. if (linkGroup && !showValueMap[tarKey]) {
  44508. each(linkGroup.axesInfo, function (srcAxisInfo, srcKey) {
  44509. var srcValItem = showValueMap[srcKey];
  44510. // If srcValItem exist, source axis is triggered, so link to target axis.
  44511. if (srcAxisInfo !== tarAxisInfo && srcValItem) {
  44512. var val = srcValItem.value;
  44513. linkGroup.mapper && (val = tarAxisInfo.axis.scale.parse(linkGroup.mapper(
  44514. val, makeMapperParam(srcAxisInfo), makeMapperParam(tarAxisInfo)
  44515. )));
  44516. linkTriggers[tarAxisInfo.key] = val;
  44517. }
  44518. });
  44519. }
  44520. });
  44521. each(linkTriggers, function (val, tarKey) {
  44522. processOnAxis(axesInfo[tarKey], val, updaters, true, outputFinder);
  44523. });
  44524. updateModelActually(showValueMap, axesInfo, outputFinder);
  44525. dispatchTooltipActually(dataByCoordSys, point, tooltipOption, dispatchAction);
  44526. dispatchHighDownActually(axesInfo, dispatchAction, api);
  44527. return outputFinder;
  44528. }
  44529. function processOnAxis(axisInfo, newValue, updaters, dontSnap, outputFinder) {
  44530. var axis = axisInfo.axis;
  44531. if (axis.scale.isBlank() || !axis.containData(newValue)) {
  44532. return;
  44533. }
  44534. if (!axisInfo.involveSeries) {
  44535. updaters.showPointer(axisInfo, newValue);
  44536. return;
  44537. }
  44538. // Heavy calculation. So put it after axis.containData checking.
  44539. var payloadInfo = buildPayloadsBySeries(newValue, axisInfo);
  44540. var payloadBatch = payloadInfo.payloadBatch;
  44541. var snapToValue = payloadInfo.snapToValue;
  44542. // Fill content of event obj for echarts.connect.
  44543. // By defualt use the first involved series data as a sample to connect.
  44544. if (payloadBatch[0] && outputFinder.seriesIndex == null) {
  44545. zrUtil.extend(outputFinder, payloadBatch[0]);
  44546. }
  44547. // If no linkSource input, this process is for collecting link
  44548. // target, where snap should not be accepted.
  44549. if (!dontSnap && axisInfo.snap) {
  44550. if (axis.containData(snapToValue) && snapToValue != null) {
  44551. newValue = snapToValue;
  44552. }
  44553. }
  44554. updaters.showPointer(axisInfo, newValue, payloadBatch, outputFinder);
  44555. // Tooltip should always be snapToValue, otherwise there will be
  44556. // incorrect "axis value ~ series value" mapping displayed in tooltip.
  44557. updaters.showTooltip(axisInfo, payloadInfo, snapToValue);
  44558. }
  44559. function buildPayloadsBySeries(value, axisInfo) {
  44560. var axis = axisInfo.axis;
  44561. var dim = axis.dim;
  44562. var snapToValue = value;
  44563. var payloadBatch = [];
  44564. var minDist = Number.MAX_VALUE;
  44565. var minDiff = -1;
  44566. each(axisInfo.seriesModels, function (series, idx) {
  44567. var dataDim = series.coordDimToDataDim(dim);
  44568. var seriesNestestValue;
  44569. var dataIndices;
  44570. if (series.getAxisTooltipData) {
  44571. var result = series.getAxisTooltipData(dataDim, value, axis);
  44572. dataIndices = result.dataIndices;
  44573. seriesNestestValue = result.nestestValue;
  44574. }
  44575. else {
  44576. dataIndices = series.getData().indicesOfNearest(
  44577. dataDim[0],
  44578. value,
  44579. // Add a threshold to avoid find the wrong dataIndex
  44580. // when data length is not same.
  44581. false, axis.type === 'category' ? 0.5 : null
  44582. );
  44583. if (!dataIndices.length) {
  44584. return;
  44585. }
  44586. seriesNestestValue = series.getData().get(dataDim[0], dataIndices[0]);
  44587. }
  44588. if (seriesNestestValue == null || !isFinite(seriesNestestValue)) {
  44589. return;
  44590. }
  44591. var diff = value - seriesNestestValue;
  44592. var dist = Math.abs(diff);
  44593. // Consider category case
  44594. if (dist <= minDist) {
  44595. if (dist < minDist || (diff >= 0 && minDiff < 0)) {
  44596. minDist = dist;
  44597. minDiff = diff;
  44598. snapToValue = seriesNestestValue;
  44599. payloadBatch.length = 0;
  44600. }
  44601. each(dataIndices, function (dataIndex) {
  44602. payloadBatch.push({
  44603. seriesIndex: series.seriesIndex,
  44604. dataIndexInside: dataIndex,
  44605. dataIndex: series.getData().getRawIndex(dataIndex)
  44606. });
  44607. });
  44608. }
  44609. });
  44610. return {
  44611. payloadBatch: payloadBatch,
  44612. snapToValue: snapToValue
  44613. };
  44614. }
  44615. function showPointer(showValueMap, axisInfo, value, payloadBatch) {
  44616. showValueMap[axisInfo.key] = {value: value, payloadBatch: payloadBatch};
  44617. }
  44618. function showTooltip(dataByCoordSys, axisInfo, payloadInfo, value) {
  44619. var payloadBatch = payloadInfo.payloadBatch;
  44620. var axis = axisInfo.axis;
  44621. var axisModel = axis.model;
  44622. var axisPointerModel = axisInfo.axisPointerModel;
  44623. // If no data, do not create anything in dataByCoordSys,
  44624. // whose length will be used to judge whether dispatch action.
  44625. if (!axisInfo.triggerTooltip || !payloadBatch.length) {
  44626. return;
  44627. }
  44628. var coordSysModel = axisInfo.coordSys.model;
  44629. var coordSysKey = modelHelper.makeKey(coordSysModel);
  44630. var coordSysItem = dataByCoordSys.map[coordSysKey];
  44631. if (!coordSysItem) {
  44632. coordSysItem = dataByCoordSys.map[coordSysKey] = {
  44633. coordSysId: coordSysModel.id,
  44634. coordSysIndex: coordSysModel.componentIndex,
  44635. coordSysType: coordSysModel.type,
  44636. coordSysMainType: coordSysModel.mainType,
  44637. dataByAxis: []
  44638. };
  44639. dataByCoordSys.list.push(coordSysItem);
  44640. }
  44641. coordSysItem.dataByAxis.push({
  44642. axisDim: axis.dim,
  44643. axisIndex: axisModel.componentIndex,
  44644. axisType: axisModel.type,
  44645. axisId: axisModel.id,
  44646. value: value,
  44647. // Caustion: viewHelper.getValueLabel is actually on "view stage", which
  44648. // depends that all models have been updated. So it should not be performed
  44649. // here. Considering axisPointerModel used here is volatile, which is hard
  44650. // to be retrieve in TooltipView, we prepare parameters here.
  44651. valueLabelOpt: {
  44652. precision: axisPointerModel.get('label.precision'),
  44653. formatter: axisPointerModel.get('label.formatter')
  44654. },
  44655. seriesDataIndices: payloadBatch.slice()
  44656. });
  44657. }
  44658. function updateModelActually(showValueMap, axesInfo, outputFinder) {
  44659. var outputAxesInfo = outputFinder.axesInfo = [];
  44660. // Basic logic: If no 'show' required, 'hide' this axisPointer.
  44661. each(axesInfo, function (axisInfo, key) {
  44662. var option = axisInfo.axisPointerModel.option;
  44663. var valItem = showValueMap[key];
  44664. if (valItem) {
  44665. !axisInfo.useHandle && (option.status = 'show');
  44666. option.value = valItem.value;
  44667. // For label formatter param and highlight.
  44668. option.seriesDataIndices = (valItem.payloadBatch || []).slice();
  44669. }
  44670. // When always show (e.g., handle used), remain
  44671. // original value and status.
  44672. else {
  44673. // If hide, value still need to be set, consider
  44674. // click legend to toggle axis blank.
  44675. !axisInfo.useHandle && (option.status = 'hide');
  44676. }
  44677. // If status is 'hide', should be no info in payload.
  44678. option.status === 'show' && outputAxesInfo.push({
  44679. axisDim: axisInfo.axis.dim,
  44680. axisIndex: axisInfo.axis.model.componentIndex,
  44681. value: option.value
  44682. });
  44683. });
  44684. }
  44685. function dispatchTooltipActually(dataByCoordSys, point, tooltipOption, dispatchAction) {
  44686. // Basic logic: If no showTip required, hideTip will be dispatched.
  44687. if (illegalPoint(point) || !dataByCoordSys.list.length) {
  44688. dispatchAction({type: 'hideTip'});
  44689. return;
  44690. }
  44691. // In most case only one axis (or event one series is used). It is
  44692. // convinient to fetch payload.seriesIndex and payload.dataIndex
  44693. // dirtectly. So put the first seriesIndex and dataIndex of the first
  44694. // axis on the payload.
  44695. var sampleItem = ((dataByCoordSys.list[0].dataByAxis[0] || {}).seriesDataIndices || [])[0] || {};
  44696. dispatchAction({
  44697. type: 'showTip',
  44698. escapeConnect: true,
  44699. x: point[0],
  44700. y: point[1],
  44701. tooltipOption: tooltipOption,
  44702. dataIndexInside: sampleItem.dataIndexInside,
  44703. dataIndex: sampleItem.dataIndex,
  44704. seriesIndex: sampleItem.seriesIndex,
  44705. dataByCoordSys: dataByCoordSys.list
  44706. });
  44707. }
  44708. function dispatchHighDownActually(axesInfo, dispatchAction, api) {
  44709. // FIXME
  44710. // highlight status modification shoule be a stage of main process?
  44711. // (Consider confilct (e.g., legend and axisPointer) and setOption)
  44712. var zr = api.getZr();
  44713. var highDownKey = 'axisPointerLastHighlights';
  44714. var lastHighlights = get(zr)[highDownKey] || {};
  44715. var newHighlights = get(zr)[highDownKey] = {};
  44716. // Update highlight/downplay status according to axisPointer model.
  44717. // Build hash map and remove duplicate incidentally.
  44718. each(axesInfo, function (axisInfo, key) {
  44719. var option = axisInfo.axisPointerModel.option;
  44720. option.status === 'show' && each(option.seriesDataIndices, function (batchItem) {
  44721. var key = batchItem.seriesIndex + ' | ' + batchItem.dataIndex;
  44722. newHighlights[key] = batchItem;
  44723. });
  44724. });
  44725. // Diff.
  44726. var toHighlight = [];
  44727. var toDownplay = [];
  44728. zrUtil.each(lastHighlights, function (batchItem, key) {
  44729. !newHighlights[key] && toDownplay.push(batchItem);
  44730. });
  44731. zrUtil.each(newHighlights, function (batchItem, key) {
  44732. !lastHighlights[key] && toHighlight.push(batchItem);
  44733. });
  44734. toDownplay.length && api.dispatchAction({
  44735. type: 'downplay', escapeConnect: true, batch: toDownplay
  44736. });
  44737. toHighlight.length && api.dispatchAction({
  44738. type: 'highlight', escapeConnect: true, batch: toHighlight
  44739. });
  44740. }
  44741. function findInputAxisInfo(inputAxesInfo, axisInfo) {
  44742. for (var i = 0; i < (inputAxesInfo || []).length; i++) {
  44743. var inputAxisInfo = inputAxesInfo[i];
  44744. if (axisInfo.axis.dim === inputAxisInfo.axisDim
  44745. && axisInfo.axis.model.componentIndex === inputAxisInfo.axisIndex
  44746. ) {
  44747. return inputAxisInfo;
  44748. }
  44749. }
  44750. }
  44751. function makeMapperParam(axisInfo) {
  44752. var axisModel = axisInfo.axis.model;
  44753. var item = {};
  44754. var dim = item.axisDim = axisInfo.axis.dim;
  44755. item.axisIndex = item[dim + 'AxisIndex'] = axisModel.componentIndex;
  44756. item.axisName = item[dim + 'AxisName'] = axisModel.name;
  44757. item.axisId = item[dim + 'AxisId'] = axisModel.id;
  44758. return item;
  44759. }
  44760. function illegalPoint(point) {
  44761. return !point || point[0] == null || isNaN(point[0]) || point[1] == null || isNaN(point[1]);
  44762. }
  44763. module.exports = axisTrigger;
  44764. /***/ },
  44765. /* 299 */
  44766. /***/ function(module, exports, __webpack_require__) {
  44767. var zrUtil = __webpack_require__(4);
  44768. var modelUtil = __webpack_require__(5);
  44769. /**
  44770. * @param {Object} finder contains {seriesIndex, dataIndex, dataIndexInside}
  44771. * @param {module:echarts/model/Global} ecModel
  44772. * @return {Object} {point: [x, y], el: ...} point Will not be null.
  44773. */
  44774. module.exports = function (finder, ecModel) {
  44775. var point = [];
  44776. var seriesIndex = finder.seriesIndex;
  44777. var seriesModel;
  44778. if (seriesIndex == null || !(
  44779. seriesModel = ecModel.getSeriesByIndex(seriesIndex)
  44780. )) {
  44781. return {point: []};
  44782. }
  44783. var data = seriesModel.getData();
  44784. var dataIndex = modelUtil.queryDataIndex(data, finder);
  44785. if (dataIndex == null || zrUtil.isArray(dataIndex)) {
  44786. return {point: []};
  44787. }
  44788. var el = data.getItemGraphicEl(dataIndex);
  44789. var coordSys = seriesModel.coordinateSystem;
  44790. if (seriesModel.getTooltipPosition) {
  44791. point = seriesModel.getTooltipPosition(dataIndex) || [];
  44792. }
  44793. else if (coordSys && coordSys.dataToPoint) {
  44794. point = coordSys.dataToPoint(
  44795. data.getValues(
  44796. zrUtil.map(coordSys.dimensions, function (dim) {
  44797. return seriesModel.coordDimToDataDim(dim)[0];
  44798. }), dataIndex, true
  44799. )
  44800. ) || [];
  44801. }
  44802. else if (el) {
  44803. // Use graphic bounding rect
  44804. var rect = el.getBoundingRect().clone();
  44805. rect.applyTransform(el.transform);
  44806. point = [
  44807. rect.x + rect.width / 2,
  44808. rect.y + rect.height / 2
  44809. ];
  44810. }
  44811. return {point: point, el: el};
  44812. };
  44813. /***/ },
  44814. /* 300 */
  44815. /***/ function(module, exports, __webpack_require__) {
  44816. var echarts = __webpack_require__(1);
  44817. var AxisPointerModel = echarts.extendComponentModel({
  44818. type: 'axisPointer',
  44819. coordSysAxesInfo: null,
  44820. defaultOption: {
  44821. // 'auto' means that show when triggered by tooltip or handle.
  44822. show: 'auto',
  44823. // 'click' | 'mousemove' | 'none'
  44824. triggerOn: null, // set default in AxisPonterView.js
  44825. zlevel: 0,
  44826. z: 50,
  44827. type: 'line',
  44828. // axispointer triggered by tootip determine snap automatically,
  44829. // see `modelHelper`.
  44830. snap: false,
  44831. triggerTooltip: true,
  44832. value: null,
  44833. status: null, // Init value depends on whether handle is used.
  44834. // [group0, group1, ...]
  44835. // Each group can be: {
  44836. // mapper: function () {},
  44837. // singleTooltip: 'multiple', // 'multiple' or 'single'
  44838. // xAxisId: ...,
  44839. // yAxisName: ...,
  44840. // angleAxisIndex: ...
  44841. // }
  44842. // mapper: can be ignored.
  44843. // input: {axisInfo, value}
  44844. // output: {axisInfo, value}
  44845. link: [],
  44846. // Do not set 'auto' here, otherwise global animation: false
  44847. // will not effect at this axispointer.
  44848. animation: null,
  44849. animationDurationUpdate: 200,
  44850. lineStyle: {
  44851. color: '#aaa',
  44852. width: 1,
  44853. type: 'solid'
  44854. },
  44855. shadowStyle: {
  44856. color: 'rgba(150,150,150,0.3)'
  44857. },
  44858. label: {
  44859. show: true,
  44860. formatter: null, // string | Function
  44861. precision: 'auto', // Or a number like 0, 1, 2 ...
  44862. margin: 3,
  44863. textStyle: {
  44864. color: '#fff'
  44865. },
  44866. padding: [5, 7, 5, 7],
  44867. backgroundColor: 'auto', // default: axis line color
  44868. borderColor: null,
  44869. borderWidth: 0,
  44870. shadowBlur: 3,
  44871. shadowColor: '#aaa'
  44872. // Considering applicability, common style should
  44873. // better not have shadowOffset.
  44874. // shadowOffsetX: 0,
  44875. // shadowOffsetY: 2
  44876. },
  44877. handle: {
  44878. show: false,
  44879. icon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4h1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7v-1.2h6.6z M13.3,22H6.7v-1.2h6.6z M13.3,19.6H6.7v-1.2h6.6z', // jshint ignore:line
  44880. size: 45,
  44881. // handle margin is from symbol center to axis, which is stable when circular move.
  44882. margin: 50,
  44883. // color: '#1b8bbd'
  44884. // color: '#2f4554'
  44885. color: '#333',
  44886. shadowBlur: 3,
  44887. shadowColor: '#aaa',
  44888. shadowOffsetX: 0,
  44889. shadowOffsetY: 2,
  44890. // For mobile performance
  44891. throttle: 40
  44892. }
  44893. }
  44894. });
  44895. module.exports = AxisPointerModel;
  44896. /***/ },
  44897. /* 301 */
  44898. /***/ function(module, exports, __webpack_require__) {
  44899. var globalListener = __webpack_require__(302);
  44900. var AxisPonterView = __webpack_require__(1).extendComponentView({
  44901. type: 'axisPointer',
  44902. render: function (globalAxisPointerModel, ecModel, api) {
  44903. var globalTooltipModel = ecModel.getComponent('tooltip');
  44904. var triggerOn = globalAxisPointerModel.get('triggerOn')
  44905. || (globalTooltipModel && globalTooltipModel.get('triggerOn') || 'mousemove|click');
  44906. // Register global listener in AxisPointerView to enable
  44907. // AxisPointerView to be independent to Tooltip.
  44908. globalListener.register(
  44909. 'axisPointer',
  44910. api,
  44911. function (currTrigger, e, dispatchAction) {
  44912. // If 'none', it is not controlled by mouse totally.
  44913. if (triggerOn !== 'none'
  44914. && (currTrigger === 'leave' || triggerOn.indexOf(currTrigger) >= 0)
  44915. ) {
  44916. dispatchAction({
  44917. type: 'updateAxisPointer',
  44918. currTrigger: currTrigger,
  44919. x: e && e.offsetX,
  44920. y: e && e.offsetY
  44921. });
  44922. }
  44923. }
  44924. );
  44925. },
  44926. /**
  44927. * @override
  44928. */
  44929. remove: function (ecModel, api) {
  44930. globalListener.disopse(api.getZr(), 'axisPointer');
  44931. AxisPonterView.superApply(this._model, 'remove', arguments);
  44932. },
  44933. /**
  44934. * @override
  44935. */
  44936. dispose: function (ecModel, api) {
  44937. globalListener.unregister('axisPointer', api);
  44938. AxisPonterView.superApply(this._model, 'dispose', arguments);
  44939. }
  44940. });
  44941. /***/ },
  44942. /* 302 */
  44943. /***/ function(module, exports, __webpack_require__) {
  44944. var env = __webpack_require__(2);
  44945. var zrUtil = __webpack_require__(4);
  44946. var get = __webpack_require__(5).makeGetter();
  44947. var each = zrUtil.each;
  44948. var globalListener = {};
  44949. /**
  44950. * @param {string} key
  44951. * @param {module:echarts/ExtensionAPI} api
  44952. * @param {Function} handler
  44953. * param: {string} currTrigger
  44954. * param: {Array.<number>} point
  44955. */
  44956. globalListener.register = function (key, api, handler) {
  44957. if (env.node) {
  44958. return;
  44959. }
  44960. var zr = api.getZr();
  44961. get(zr).records || (get(zr).records = {});
  44962. initGlobalListeners(zr, api);
  44963. var record = get(zr).records[key] || (get(zr).records[key] = {});
  44964. record.handler = handler;
  44965. };
  44966. function initGlobalListeners(zr, api) {
  44967. if (get(zr).initialized) {
  44968. return;
  44969. }
  44970. get(zr).initialized = true;
  44971. useHandler('click', zrUtil.curry(doEnter, 'click'));
  44972. useHandler('mousemove', zrUtil.curry(doEnter, 'mousemove'));
  44973. // useHandler('mouseout', onLeave);
  44974. useHandler('globalout', onLeave);
  44975. function useHandler(eventType, cb) {
  44976. zr.on(eventType, function (e) {
  44977. var dis = makeDispatchAction(api);
  44978. each(get(zr).records, function (record) {
  44979. record && cb(record, e, dis.dispatchAction);
  44980. });
  44981. dispatchTooltipFinally(dis.pendings, api);
  44982. });
  44983. }
  44984. }
  44985. function dispatchTooltipFinally(pendings, api) {
  44986. var showLen = pendings.showTip.length;
  44987. var hideLen = pendings.hideTip.length;
  44988. var actuallyPayload;
  44989. if (showLen) {
  44990. actuallyPayload = pendings.showTip[showLen - 1];
  44991. }
  44992. else if (hideLen) {
  44993. actuallyPayload = pendings.hideTip[hideLen - 1];
  44994. }
  44995. if (actuallyPayload) {
  44996. actuallyPayload.dispatchAction = null;
  44997. api.dispatchAction(actuallyPayload);
  44998. }
  44999. }
  45000. function onLeave(record, e, dispatchAction) {
  45001. record.handler('leave', null, dispatchAction);
  45002. }
  45003. function doEnter(currTrigger, record, e, dispatchAction) {
  45004. record.handler(currTrigger, e, dispatchAction);
  45005. }
  45006. function makeDispatchAction(api) {
  45007. var pendings = {
  45008. showTip: [],
  45009. hideTip: []
  45010. };
  45011. // FIXME
  45012. // better approach?
  45013. // 'showTip' and 'hideTip' can be triggered by axisPointer and tooltip,
  45014. // which may be conflict, (axisPointer call showTip but tooltip call hideTip);
  45015. // So we have to add "final stage" to merge those dispatched actions.
  45016. var dispatchAction = function (payload) {
  45017. var pendingList = pendings[payload.type];
  45018. if (pendingList) {
  45019. pendingList.push(payload);
  45020. }
  45021. else {
  45022. payload.dispatchAction = dispatchAction;
  45023. api.dispatchAction(payload);
  45024. }
  45025. };
  45026. return {
  45027. dispatchAction: dispatchAction,
  45028. pendings: pendings
  45029. };
  45030. }
  45031. /**
  45032. * @param {string} key
  45033. * @param {module:echarts/ExtensionAPI} api
  45034. */
  45035. globalListener.unregister = function (key, api) {
  45036. if (env.node) {
  45037. return;
  45038. }
  45039. var zr = api.getZr();
  45040. var record = (get(zr).records || {})[key];
  45041. if (record) {
  45042. get(zr).records[key] = null;
  45043. }
  45044. };
  45045. module.exports = globalListener;
  45046. /***/ },
  45047. /* 303 */
  45048. /***/ function(module, exports, __webpack_require__) {
  45049. 'use strict';
  45050. var graphic = __webpack_require__(18);
  45051. var BaseAxisPointer = __webpack_require__(304);
  45052. var viewHelper = __webpack_require__(305);
  45053. var cartesianAxisHelper = __webpack_require__(138);
  45054. var AxisView = __webpack_require__(136);
  45055. var CartesianAxisPointer = BaseAxisPointer.extend({
  45056. /**
  45057. * @override
  45058. */
  45059. makeElOption: function (elOption, value, axisModel, axisPointerModel, api) {
  45060. var axis = axisModel.axis;
  45061. var grid = axis.grid;
  45062. var axisPointerType = axisPointerModel.get('type');
  45063. var otherExtent = getCartesian(grid, axis).getOtherAxis(axis).getGlobalExtent();
  45064. var pixelValue = axis.toGlobalCoord(axis.dataToCoord(value, true));
  45065. if (axisPointerType && axisPointerType !== 'none') {
  45066. var elStyle = viewHelper.buildElStyle(axisPointerModel);
  45067. var pointerOption = pointerShapeBuilder[axisPointerType](
  45068. axis, pixelValue, otherExtent, elStyle
  45069. );
  45070. pointerOption.style = elStyle;
  45071. elOption.graphicKey = pointerOption.type;
  45072. elOption.pointer = pointerOption;
  45073. }
  45074. var layoutInfo = cartesianAxisHelper.layout(grid.model, axisModel);
  45075. viewHelper.buildCartesianSingleLabelElOption(
  45076. value, elOption, layoutInfo, axisModel, axisPointerModel, api
  45077. );
  45078. },
  45079. /**
  45080. * @override
  45081. */
  45082. getHandleTransform: function (value, axisModel, axisPointerModel) {
  45083. var layoutInfo = cartesianAxisHelper.layout(axisModel.axis.grid.model, axisModel, {
  45084. labelInside: false
  45085. });
  45086. layoutInfo.labelMargin = axisPointerModel.get('handle.margin');
  45087. return {
  45088. position: viewHelper.getTransformedPosition(axisModel.axis, value, layoutInfo),
  45089. rotation: layoutInfo.rotation + (layoutInfo.labelDirection < 0 ? Math.PI : 0)
  45090. };
  45091. },
  45092. /**
  45093. * @override
  45094. */
  45095. updateHandleTransform: function (transform, delta, axisModel, axisPointerModel) {
  45096. var axis = axisModel.axis;
  45097. var grid = axis.grid;
  45098. var axisExtent = axis.getGlobalExtent(true);
  45099. var otherExtent = getCartesian(grid, axis).getOtherAxis(axis).getGlobalExtent();
  45100. var dimIndex = axis.dim === 'x' ? 0 : 1;
  45101. var currPosition = transform.position;
  45102. currPosition[dimIndex] += delta[dimIndex];
  45103. currPosition[dimIndex] = Math.min(axisExtent[1], currPosition[dimIndex]);
  45104. currPosition[dimIndex] = Math.max(axisExtent[0], currPosition[dimIndex]);
  45105. var cursorOtherValue = (otherExtent[1] + otherExtent[0]) / 2;
  45106. var cursorPoint = [cursorOtherValue, cursorOtherValue];
  45107. cursorPoint[dimIndex] = currPosition[dimIndex];
  45108. // Make tooltip do not overlap axisPointer and in the middle of the grid.
  45109. var tooltipOptions = [{verticalAlign: 'middle'}, {align: 'center'}];
  45110. return {
  45111. position: currPosition,
  45112. rotation: transform.rotation,
  45113. cursorPoint: cursorPoint,
  45114. tooltipOption: tooltipOptions[dimIndex]
  45115. };
  45116. }
  45117. });
  45118. function getCartesian(grid, axis) {
  45119. var opt = {};
  45120. opt[axis.dim + 'AxisIndex'] = axis.index;
  45121. return grid.getCartesian(opt);
  45122. }
  45123. var pointerShapeBuilder = {
  45124. line: function (axis, pixelValue, otherExtent, elStyle) {
  45125. var targetShape = viewHelper.makeLineShape(
  45126. [pixelValue, otherExtent[0]],
  45127. [pixelValue, otherExtent[1]],
  45128. getAxisDimIndex(axis)
  45129. );
  45130. graphic.subPixelOptimizeLine({
  45131. shape: targetShape,
  45132. style: elStyle
  45133. });
  45134. return {
  45135. type: 'Line',
  45136. shape: targetShape
  45137. };
  45138. },
  45139. shadow: function (axis, pixelValue, otherExtent, elStyle) {
  45140. var bandWidth = axis.getBandWidth();
  45141. var span = otherExtent[1] - otherExtent[0];
  45142. return {
  45143. type: 'Rect',
  45144. shape: viewHelper.makeRectShape(
  45145. [pixelValue - bandWidth / 2, otherExtent[0]],
  45146. [bandWidth, span],
  45147. getAxisDimIndex(axis)
  45148. )
  45149. };
  45150. }
  45151. };
  45152. function getAxisDimIndex(axis) {
  45153. return axis.dim === 'x' ? 0 : 1;
  45154. }
  45155. AxisView.registerAxisPointerClass('CartesianAxisPointer', CartesianAxisPointer);
  45156. module.exports = CartesianAxisPointer;
  45157. /***/ },
  45158. /* 304 */
  45159. /***/ function(module, exports, __webpack_require__) {
  45160. 'use strict';
  45161. var zrUtil = __webpack_require__(4);
  45162. var clazzUtil = __webpack_require__(13);
  45163. var graphic = __webpack_require__(18);
  45164. var get = __webpack_require__(5).makeGetter();
  45165. var axisPointerModelHelper = __webpack_require__(137);
  45166. var eventTool = __webpack_require__(88);
  45167. var throttle = __webpack_require__(81);
  45168. var clone = zrUtil.clone;
  45169. var bind = zrUtil.bind;
  45170. /**
  45171. * Base axis pointer class in 2D.
  45172. * Implemenents {module:echarts/component/axis/IAxisPointer}.
  45173. */
  45174. function BaseAxisPointer () {
  45175. }
  45176. BaseAxisPointer.prototype = {
  45177. /**
  45178. * @private
  45179. */
  45180. _group: null,
  45181. /**
  45182. * @private
  45183. */
  45184. _lastGraphicKey: null,
  45185. /**
  45186. * @private
  45187. */
  45188. _handle: null,
  45189. /**
  45190. * @private
  45191. */
  45192. _dragging: false,
  45193. /**
  45194. * @private
  45195. */
  45196. _lastValue: null,
  45197. /**
  45198. * @private
  45199. */
  45200. _lastStatus: null,
  45201. /**
  45202. * @private
  45203. */
  45204. _payloadInfo: null,
  45205. /**
  45206. * In px, arbitrary value. Do not set too small,
  45207. * no animation is ok for most cases.
  45208. * @protected
  45209. */
  45210. animationThreshold: 15,
  45211. /**
  45212. * @implement
  45213. */
  45214. render: function (axisModel, axisPointerModel, api, forceRender) {
  45215. var value = axisPointerModel.get('value');
  45216. var status = axisPointerModel.get('status');
  45217. // Bind them to `this`, not in closure, otherwise they will not
  45218. // be replaced when user calling setOption in not merge mode.
  45219. this._axisModel = axisModel;
  45220. this._axisPointerModel = axisPointerModel;
  45221. this._api = api;
  45222. // Optimize: `render` will be called repeatly during mouse move.
  45223. // So it is power consuming if performing `render` each time,
  45224. // especially on mobile device.
  45225. if (!forceRender
  45226. && this._lastValue === value
  45227. && this._lastStatus === status
  45228. ) {
  45229. return;
  45230. }
  45231. this._lastValue = value;
  45232. this._lastStatus = status;
  45233. var group = this._group;
  45234. var handle = this._handle;
  45235. if (!status || status === 'hide') {
  45236. // Do not clear here, for animation better.
  45237. group && group.hide();
  45238. handle && handle.hide();
  45239. return;
  45240. }
  45241. group && group.show();
  45242. handle && handle.show();
  45243. // Otherwise status is 'show'
  45244. var elOption = {};
  45245. this.makeElOption(elOption, value, axisModel, axisPointerModel, api);
  45246. // Enable change axis pointer type.
  45247. var graphicKey = elOption.graphicKey;
  45248. if (graphicKey !== this._lastGraphicKey) {
  45249. this.clear(api);
  45250. }
  45251. this._lastGraphicKey = graphicKey;
  45252. var moveAnimation = this._moveAnimation =
  45253. this.determineAnimation(axisModel, axisPointerModel);
  45254. if (!group) {
  45255. group = this._group = new graphic.Group();
  45256. this.createPointerEl(group, elOption, axisModel, axisPointerModel);
  45257. this.createLabelEl(group, elOption, axisModel, axisPointerModel);
  45258. api.getZr().add(group);
  45259. }
  45260. else {
  45261. var doUpdateProps = zrUtil.curry(updateProps, axisPointerModel, moveAnimation);
  45262. this.updatePointerEl(group, elOption, doUpdateProps, axisPointerModel);
  45263. this.updateLabelEl(group, elOption, doUpdateProps, axisPointerModel);
  45264. }
  45265. updateMandatoryProps(group, axisPointerModel, true);
  45266. this._renderHandle(value);
  45267. },
  45268. /**
  45269. * @implement
  45270. */
  45271. remove: function (api) {
  45272. this.clear(api);
  45273. },
  45274. /**
  45275. * @implement
  45276. */
  45277. dispose: function (api) {
  45278. this.clear(api);
  45279. },
  45280. /**
  45281. * @protected
  45282. */
  45283. determineAnimation: function (axisModel, axisPointerModel) {
  45284. var animation = axisPointerModel.get('animation');
  45285. var axis = axisModel.axis;
  45286. var isCategoryAxis = axis.type === 'category';
  45287. var useSnap = axisPointerModel.get('snap');
  45288. // Value axis without snap always do not snap.
  45289. if (!useSnap && !isCategoryAxis) {
  45290. return false;
  45291. }
  45292. if (animation === 'auto' || animation == null) {
  45293. var animationThreshold = this.animationThreshold;
  45294. if (isCategoryAxis && axis.getBandWidth() > animationThreshold) {
  45295. return true;
  45296. }
  45297. // It is important to auto animation when snap used. Consider if there is
  45298. // a dataZoom, animation will be disabled when too many points exist, while
  45299. // it will be enabled for better visual effect when little points exist.
  45300. if (useSnap) {
  45301. var seriesDataCount = axisPointerModelHelper.getAxisInfo(axisModel).seriesDataCount;
  45302. var axisExtent = axis.getExtent();
  45303. // Approximate band width
  45304. return Math.abs(axisExtent[0] - axisExtent[1]) / seriesDataCount > animationThreshold;
  45305. }
  45306. return false;
  45307. }
  45308. return animation === true;
  45309. },
  45310. /**
  45311. * add {pointer, label, graphicKey} to elOption
  45312. * @protected
  45313. */
  45314. makeElOption: function (elOption, value, axisModel, axisPointerModel, api) {
  45315. // Shoule be implemenented by sub-class.
  45316. },
  45317. /**
  45318. * @protected
  45319. */
  45320. createPointerEl: function (group, elOption, axisModel, axisPointerModel) {
  45321. var pointerOption = elOption.pointer;
  45322. if (pointerOption) {
  45323. var pointerEl = get(group).pointerEl = new graphic[pointerOption.type](
  45324. clone(elOption.pointer)
  45325. );
  45326. group.add(pointerEl);
  45327. }
  45328. },
  45329. /**
  45330. * @protected
  45331. */
  45332. createLabelEl: function (group, elOption, axisModel, axisPointerModel) {
  45333. if (elOption.label) {
  45334. var labelEl = get(group).labelEl = new graphic.Rect(
  45335. clone(elOption.label)
  45336. );
  45337. group.add(labelEl);
  45338. updateLabelShowHide(labelEl, axisPointerModel);
  45339. }
  45340. },
  45341. /**
  45342. * @protected
  45343. */
  45344. updatePointerEl: function (group, elOption, updateProps) {
  45345. var pointerEl = get(group).pointerEl;
  45346. if (pointerEl) {
  45347. pointerEl.setStyle(elOption.pointer.style);
  45348. updateProps(pointerEl, {shape: elOption.pointer.shape});
  45349. }
  45350. },
  45351. /**
  45352. * @protected
  45353. */
  45354. updateLabelEl: function (group, elOption, updateProps, axisPointerModel) {
  45355. var labelEl = get(group).labelEl;
  45356. if (labelEl) {
  45357. labelEl.setStyle(elOption.label.style);
  45358. updateProps(labelEl, {
  45359. // Consider text length change in vertical axis, animation should
  45360. // be used on shape, otherwise the effect will be weird.
  45361. shape: elOption.label.shape,
  45362. position: elOption.label.position
  45363. });
  45364. updateLabelShowHide(labelEl, axisPointerModel);
  45365. }
  45366. },
  45367. /**
  45368. * @private
  45369. */
  45370. _renderHandle: function (value) {
  45371. if (this._dragging || !this.updateHandleTransform) {
  45372. return;
  45373. }
  45374. var axisPointerModel = this._axisPointerModel;
  45375. var zr = this._api.getZr();
  45376. var handle = this._handle;
  45377. var handleModel = axisPointerModel.getModel('handle');
  45378. var status = axisPointerModel.get('status');
  45379. if (!handleModel.get('show') || !status || status === 'hide') {
  45380. handle && zr.remove(handle);
  45381. this._handle = null;
  45382. return;
  45383. }
  45384. var isInit;
  45385. if (!this._handle) {
  45386. isInit = true;
  45387. handle = this._handle = createIcon(handleModel, {
  45388. onmousemove: function (e) {
  45389. // Fot mobile devicem, prevent screen slider on the button.
  45390. eventTool.stop(e.event);
  45391. },
  45392. onmousedown: bind(this._onHandleDragMove, this, 0, 0),
  45393. drift: bind(this._onHandleDragMove, this),
  45394. ondragend: bind(this._onHandleDragEnd, this)
  45395. });
  45396. zr.add(handle);
  45397. }
  45398. updateMandatoryProps(handle, axisPointerModel, false);
  45399. // update style
  45400. var includeStyles = [
  45401. 'color', 'borderColor', 'borderWidth', 'opacity',
  45402. 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY'
  45403. ];
  45404. handle.setStyle(handleModel.getItemStyle(null, includeStyles));
  45405. // update position
  45406. var handleSize = handleModel.get('size');
  45407. if (!zrUtil.isArray(handleSize)) {
  45408. handleSize = [handleSize, handleSize];
  45409. }
  45410. handle.attr('scale', [handleSize[0] / 2, handleSize[1] / 2]);
  45411. throttle.createOrUpdate(
  45412. this,
  45413. '_doDispatchAxisPointer',
  45414. handleModel.get('throttle') || 0,
  45415. 'fixRate'
  45416. );
  45417. this._moveHandleToValue(value, isInit);
  45418. },
  45419. /**
  45420. * @private
  45421. */
  45422. _moveHandleToValue: function (value, isInit) {
  45423. updateProps(
  45424. this._axisPointerModel,
  45425. !isInit && this._moveAnimation,
  45426. this._handle,
  45427. getHandleTransProps(this.getHandleTransform(
  45428. value, this._axisModel, this._axisPointerModel
  45429. ))
  45430. );
  45431. },
  45432. /**
  45433. * @private
  45434. */
  45435. _onHandleDragMove: function (dx, dy) {
  45436. var handle = this._handle;
  45437. if (!handle) {
  45438. return;
  45439. }
  45440. this._dragging = true;
  45441. // Persistent for throttle.
  45442. var trans = this.updateHandleTransform(
  45443. getHandleTransProps(handle),
  45444. [dx, dy],
  45445. this._axisModel,
  45446. this._axisPointerModel
  45447. );
  45448. this._payloadInfo = trans;
  45449. handle.stopAnimation();
  45450. handle.attr(getHandleTransProps(trans));
  45451. get(handle).lastProp = null;
  45452. this._doDispatchAxisPointer();
  45453. },
  45454. /**
  45455. * Throttled method.
  45456. * @private
  45457. */
  45458. _doDispatchAxisPointer: function () {
  45459. var handle = this._handle;
  45460. if (!handle) {
  45461. return;
  45462. }
  45463. var payloadInfo = this._payloadInfo;
  45464. var axisModel = this._axisModel;
  45465. this._api.dispatchAction({
  45466. type: 'updateAxisPointer',
  45467. x: payloadInfo.cursorPoint[0],
  45468. y: payloadInfo.cursorPoint[1],
  45469. tooltipOption: payloadInfo.tooltipOption,
  45470. axesInfo: [{
  45471. axisDim: axisModel.axis.dim,
  45472. axisIndex: axisModel.componentIndex
  45473. }]
  45474. });
  45475. },
  45476. /**
  45477. * @private
  45478. */
  45479. _onHandleDragEnd: function (moveAnimation) {
  45480. this._dragging = false;
  45481. var handle = this._handle;
  45482. if (!handle) {
  45483. return;
  45484. }
  45485. var value = this._axisPointerModel.get('value');
  45486. // Consider snap or categroy axis, handle may be not consistent with
  45487. // axisPointer. So move handle to align the exact value position when
  45488. // drag ended.
  45489. this._moveHandleToValue(value);
  45490. // For the effect: tooltip will be shown when finger holding on handle
  45491. // button, and will be hidden after finger left handle button.
  45492. this._api.dispatchAction({
  45493. type: 'hideTip'
  45494. });
  45495. },
  45496. /**
  45497. * Should be implemenented by sub-class if support `handle`.
  45498. * @protected
  45499. * @param {number} value
  45500. * @param {module:echarts/model/Model} axisModel
  45501. * @param {module:echarts/model/Model} axisPointerModel
  45502. * @return {Object} {position: [x, y], rotation: 0}
  45503. */
  45504. getHandleTransform: null,
  45505. /**
  45506. * * Should be implemenented by sub-class if support `handle`.
  45507. * @protected
  45508. * @param {Object} transform {position, rotation}
  45509. * @param {Array.<number>} delta [dx, dy]
  45510. * @param {module:echarts/model/Model} axisModel
  45511. * @param {module:echarts/model/Model} axisPointerModel
  45512. * @return {Object} {position: [x, y], rotation: 0, cursorPoint: [x, y]}
  45513. */
  45514. updateHandleTransform: null,
  45515. /**
  45516. * @private
  45517. */
  45518. clear: function (api) {
  45519. this._lastValue = null;
  45520. this._lastStatus = null;
  45521. var zr = api.getZr();
  45522. var group = this._group;
  45523. var handle = this._handle;
  45524. if (zr && group) {
  45525. this._lastGraphicKey = null;
  45526. group && zr.remove(group);
  45527. handle && zr.remove(handle);
  45528. this._group = null;
  45529. this._handle = null;
  45530. this._payloadInfo = null;
  45531. }
  45532. },
  45533. /**
  45534. * @protected
  45535. */
  45536. doClear: function () {
  45537. // Implemented by sub-class if necessary.
  45538. },
  45539. /**
  45540. * @protected
  45541. * @param {Array.<number>} xy
  45542. * @param {Array.<number>} wh
  45543. * @param {number} [xDimIndex=0] or 1
  45544. */
  45545. buildLabel: function (xy, wh, xDimIndex) {
  45546. xDimIndex = xDimIndex || 0;
  45547. return {
  45548. x: xy[xDimIndex],
  45549. y: xy[1 - xDimIndex],
  45550. width: wh[xDimIndex],
  45551. height: wh[1 - xDimIndex]
  45552. };
  45553. }
  45554. };
  45555. BaseAxisPointer.prototype.constructor = BaseAxisPointer;
  45556. function updateProps(animationModel, moveAnimation, el, props) {
  45557. // Animation optimize.
  45558. if (!propsEqual(get(el).lastProp, props)) {
  45559. get(el).lastProp = props;
  45560. moveAnimation
  45561. ? graphic.updateProps(el, props, animationModel)
  45562. : (el.stopAnimation(), el.attr(props));
  45563. }
  45564. }
  45565. function propsEqual(lastProps, newProps) {
  45566. if (zrUtil.isObject(lastProps) && zrUtil.isObject(newProps)) {
  45567. var equals = true;
  45568. zrUtil.each(newProps, function (item, key) {
  45569. equals &= propsEqual(lastProps[key], item);
  45570. });
  45571. return !!equals;
  45572. }
  45573. else {
  45574. return lastProps === newProps;
  45575. }
  45576. }
  45577. function updateLabelShowHide(labelEl, axisPointerModel) {
  45578. labelEl[axisPointerModel.get('label.show') ? 'show' : 'hide']();
  45579. }
  45580. function getHandleTransProps(trans) {
  45581. return {
  45582. position: trans.position.slice(),
  45583. rotation: trans.rotation || 0
  45584. };
  45585. }
  45586. function createIcon(handleModel, handlers) {
  45587. var iconStr = handleModel.get('icon');
  45588. var style = {
  45589. x: -1, y: -1, width: 2, height: 2
  45590. };
  45591. var opt = zrUtil.extend({
  45592. style: {
  45593. strokeNoScale: true
  45594. },
  45595. rectHover: true,
  45596. cursor: 'move',
  45597. draggable: true
  45598. }, handlers);
  45599. return iconStr.indexOf('image://') === 0
  45600. ? (
  45601. style.image = iconStr.slice(8),
  45602. opt.style = style,
  45603. new graphic.Image(opt)
  45604. )
  45605. : graphic.makePath(
  45606. iconStr.replace('path://', ''),
  45607. opt,
  45608. style,
  45609. 'center'
  45610. );
  45611. }
  45612. function updateMandatoryProps(group, axisPointerModel, silent) {
  45613. var z = axisPointerModel.get('z');
  45614. var zlevel = axisPointerModel.get('zlevel');
  45615. group && group.traverse(function (el) {
  45616. if (el.type !== 'group') {
  45617. z != null && (el.z = z);
  45618. zlevel != null && (el.zlevel = zlevel);
  45619. el.silent = silent;
  45620. }
  45621. });
  45622. }
  45623. clazzUtil.enableClassExtend(BaseAxisPointer);
  45624. module.exports = BaseAxisPointer;
  45625. /***/ },
  45626. /* 305 */
  45627. /***/ function(module, exports, __webpack_require__) {
  45628. 'use strict';
  45629. var zrUtil = __webpack_require__(4);
  45630. var graphic = __webpack_require__(18);
  45631. var textContain = __webpack_require__(8);
  45632. var formatUtil = __webpack_require__(6);
  45633. var matrix = __webpack_require__(11);
  45634. var axisHelper = __webpack_require__(101);
  45635. var AxisBuilder = __webpack_require__(135);
  45636. var helper = {};
  45637. /**
  45638. * @param {module:echarts/model/Model} axisPointerModel
  45639. */
  45640. helper.buildElStyle = function (axisPointerModel) {
  45641. var axisPointerType = axisPointerModel.get('type');
  45642. var styleModel = axisPointerModel.getModel(axisPointerType + 'Style');
  45643. var style;
  45644. if (axisPointerType === 'line') {
  45645. style = styleModel.getLineStyle();
  45646. style.fill = null;
  45647. }
  45648. else if (axisPointerType === 'shadow') {
  45649. style = styleModel.getAreaStyle();
  45650. style.stroke = null;
  45651. }
  45652. return style;
  45653. };
  45654. /**
  45655. * @param {Function} labelPos {align, verticalAlign, position}
  45656. */
  45657. helper.buildLabelElOption = function (
  45658. elOption, axisModel, axisPointerModel, api, labelPos
  45659. ) {
  45660. var value = axisPointerModel.get('value');
  45661. var text = helper.getValueLabel(
  45662. value, axisModel.axis, axisModel.ecModel,
  45663. axisPointerModel.get('seriesDataIndices'),
  45664. {
  45665. precision: axisPointerModel.get('label.precision'),
  45666. formatter: axisPointerModel.get('label.formatter')
  45667. }
  45668. );
  45669. var labelModel = axisPointerModel.getModel('label');
  45670. var textStyleModel = labelModel.getModel('textStyle');
  45671. var paddings = formatUtil.normalizeCssArray(labelModel.get('padding') || 0);
  45672. var font = textStyleModel.getFont();
  45673. var textRect = textContain.getBoundingRect(
  45674. text, font, labelPos.textAlign, labelPos.textBaseline
  45675. );
  45676. var position = labelPos.position;
  45677. var width = textRect.width + paddings[1] + paddings[3];
  45678. var height = textRect.height + paddings[0] + paddings[2];
  45679. // Adjust by align.
  45680. var align = labelPos.align;
  45681. align === 'right' && (position[0] -= width);
  45682. align === 'center' && (position[0] -= width / 2);
  45683. var verticalAlign = labelPos.verticalAlign;
  45684. verticalAlign === 'bottom' && (position[1] -= height);
  45685. verticalAlign === 'middle' && (position[1] -= height / 2);
  45686. // Not overflow ec container
  45687. confineInContainer(position, width, height, api);
  45688. var bgColor = labelModel.get('backgroundColor');
  45689. if (!bgColor || bgColor === 'auto') {
  45690. bgColor = axisModel.get('axisLine.lineStyle.color');
  45691. }
  45692. elOption.label = {
  45693. shape: {x: 0, y: 0, width: width, height: height, r: labelModel.get('borderRadius')},
  45694. position: position.slice(),
  45695. style: {
  45696. text: text,
  45697. textFont: font,
  45698. textFill: textStyleModel.getTextColor(),
  45699. textPosition: 'inside',
  45700. fill: bgColor,
  45701. stroke: labelModel.get('borderColor') || 'transparent',
  45702. lineWidth: labelModel.get('borderWidth') || 0,
  45703. shadowBlur: labelModel.get('shadowBlur'),
  45704. shadowColor: labelModel.get('shadowColor'),
  45705. shadowOffsetX: labelModel.get('shadowOffsetX'),
  45706. shadowOffsetY: labelModel.get('shadowOffsetY')
  45707. },
  45708. // Lable should be over axisPointer.
  45709. z2: 10
  45710. };
  45711. };
  45712. // Do not overflow ec container
  45713. function confineInContainer(position, width, height, api) {
  45714. var viewWidth = api.getWidth();
  45715. var viewHeight = api.getHeight();
  45716. position[0] = Math.min(position[0] + width, viewWidth) - width;
  45717. position[1] = Math.min(position[1] + height, viewHeight) - height;
  45718. position[0] = Math.max(position[0], 0);
  45719. position[1] = Math.max(position[1], 0);
  45720. }
  45721. /**
  45722. * @param {number} value
  45723. * @param {module:echarts/coord/Axis} axis
  45724. * @param {module:echarts/model/Global} ecModel
  45725. * @param {Object} opt
  45726. * @param {Array.<Object>} seriesDataIndices
  45727. * @param {number|string} opt.precision 'auto' or a number
  45728. * @param {string|Function} opt.formatter label formatter
  45729. */
  45730. helper.getValueLabel = function (value, axis, ecModel, seriesDataIndices, opt) {
  45731. var text = axis.scale.getLabel(
  45732. // If `precision` is set, width can be fixed (like '12.00500'), which
  45733. // helps to debounce when when moving label.
  45734. value, {precision: opt.precision}
  45735. );
  45736. var formatter = opt.formatter;
  45737. if (formatter) {
  45738. var params = {
  45739. value: axisHelper.getAxisRawValue(axis, value),
  45740. seriesData: []
  45741. };
  45742. zrUtil.each(seriesDataIndices, function (idxItem) {
  45743. var series = ecModel.getSeriesByIndex(idxItem.seriesIndex);
  45744. var dataIndex = idxItem.dataIndexInside;
  45745. var dataParams = series && series.getDataParams(dataIndex);
  45746. dataParams && params.seriesData.push(dataParams);
  45747. });
  45748. if (zrUtil.isString(formatter)) {
  45749. text = formatter.replace('{value}', text);
  45750. }
  45751. else if (zrUtil.isFunction(formatter)) {
  45752. text = formatter(params);
  45753. }
  45754. }
  45755. return text;
  45756. };
  45757. /**
  45758. * @param {module:echarts/coord/Axis} axis
  45759. * @param {number} value
  45760. * @param {Object} layoutInfo {
  45761. * rotation, position, labelOffset, labelDirection, labelMargin
  45762. * }
  45763. */
  45764. helper.getTransformedPosition = function (axis, value, layoutInfo) {
  45765. var transform = matrix.create();
  45766. matrix.rotate(transform, transform, layoutInfo.rotation);
  45767. matrix.translate(transform, transform, layoutInfo.position);
  45768. return graphic.applyTransform([
  45769. axis.dataToCoord(value),
  45770. (layoutInfo.labelOffset || 0)
  45771. + (layoutInfo.labelDirection || 1) * (layoutInfo.labelMargin || 0)
  45772. ], transform);
  45773. };
  45774. helper.buildCartesianSingleLabelElOption = function (
  45775. value, elOption, layoutInfo, axisModel, axisPointerModel, api
  45776. ) {
  45777. var textLayout = AxisBuilder.innerTextLayout(
  45778. layoutInfo.rotation, 0, layoutInfo.labelDirection
  45779. );
  45780. layoutInfo.labelMargin = axisPointerModel.get('label.margin');
  45781. helper.buildLabelElOption(elOption, axisModel, axisPointerModel, api, {
  45782. position: helper.getTransformedPosition(axisModel.axis, value, layoutInfo),
  45783. align: textLayout.textAlign,
  45784. verticalAlign: textLayout.textVerticalAlign
  45785. });
  45786. };
  45787. /**
  45788. * @param {Array.<number>} p1
  45789. * @param {Array.<number>} p2
  45790. * @param {number} [xDimIndex=0] or 1
  45791. */
  45792. helper.makeLineShape = function (p1, p2, xDimIndex) {
  45793. xDimIndex = xDimIndex || 0;
  45794. return {
  45795. x1: p1[xDimIndex],
  45796. y1: p1[1 - xDimIndex],
  45797. x2: p2[xDimIndex],
  45798. y2: p2[1 - xDimIndex]
  45799. };
  45800. };
  45801. /**
  45802. * @param {Array.<number>} xy
  45803. * @param {Array.<number>} wh
  45804. * @param {number} [xDimIndex=0] or 1
  45805. */
  45806. helper.makeRectShape = function (xy, wh, xDimIndex) {
  45807. xDimIndex = xDimIndex || 0;
  45808. return {
  45809. x: xy[xDimIndex],
  45810. y: xy[1 - xDimIndex],
  45811. width: wh[xDimIndex],
  45812. height: wh[1 - xDimIndex]
  45813. };
  45814. };
  45815. helper.makeSectorShape = function (cx, cy, r0, r, startAngle, endAngle) {
  45816. return {
  45817. cx: cx,
  45818. cy: cy,
  45819. r0: r0,
  45820. r: r,
  45821. startAngle: startAngle,
  45822. endAngle: endAngle,
  45823. clockwise: true
  45824. };
  45825. };
  45826. module.exports = helper;
  45827. /***/ },
  45828. /* 306 */
  45829. /***/ function(module, exports, __webpack_require__) {
  45830. 'use strict';
  45831. var graphic = __webpack_require__(18);
  45832. var BaseAxisPointer = __webpack_require__(304);
  45833. var viewHelper = __webpack_require__(305);
  45834. var singleAxisHelper = __webpack_require__(295);
  45835. var AxisView = __webpack_require__(136);
  45836. var XY = ['x', 'y'];
  45837. var WH = ['width', 'height'];
  45838. var SingleAxisPointer = BaseAxisPointer.extend({
  45839. /**
  45840. * @override
  45841. */
  45842. makeElOption: function (elOption, value, axisModel, axisPointerModel, api) {
  45843. var axis = axisModel.axis;
  45844. var coordSys = axis.coordinateSystem;
  45845. var otherExtent = getGlobalExtent(coordSys, 1 - getPointDimIndex(axis));
  45846. var pixelValue = coordSys.dataToPoint(value)[0];
  45847. var axisPointerType = axisPointerModel.get('type');
  45848. if (axisPointerType && axisPointerType !== 'none') {
  45849. var elStyle = viewHelper.buildElStyle(axisPointerModel);
  45850. var pointerOption = pointerShapeBuilder[axisPointerType](
  45851. axis, pixelValue, otherExtent, elStyle
  45852. );
  45853. pointerOption.style = elStyle;
  45854. elOption.graphicKey = pointerOption.type;
  45855. elOption.pointer = pointerOption;
  45856. }
  45857. var layoutInfo = singleAxisHelper.layout(axisModel);
  45858. viewHelper.buildCartesianSingleLabelElOption(
  45859. value, elOption, layoutInfo, axisModel, axisPointerModel, api
  45860. );
  45861. },
  45862. /**
  45863. * @override
  45864. */
  45865. getHandleTransform: function (value, axisModel, axisPointerModel) {
  45866. var layoutInfo = singleAxisHelper.layout(axisModel, {labelInside: false});
  45867. layoutInfo.labelMargin = axisPointerModel.get('handle.margin');
  45868. return {
  45869. position: viewHelper.getTransformedPosition(axisModel.axis, value, layoutInfo),
  45870. rotation: layoutInfo.rotation + (layoutInfo.labelDirection < 0 ? Math.PI : 0)
  45871. };
  45872. },
  45873. /**
  45874. * @override
  45875. */
  45876. updateHandleTransform: function (transform, delta, axisModel, axisPointerModel) {
  45877. var axis = axisModel.axis;
  45878. var coordSys = axis.coordinateSystem;
  45879. var dimIndex = getPointDimIndex(axis);
  45880. var axisExtent = getGlobalExtent(coordSys, dimIndex);
  45881. var currPosition = transform.position;
  45882. currPosition[dimIndex] += delta[dimIndex];
  45883. currPosition[dimIndex] = Math.min(axisExtent[1], currPosition[dimIndex]);
  45884. currPosition[dimIndex] = Math.max(axisExtent[0], currPosition[dimIndex]);
  45885. var otherExtent = getGlobalExtent(coordSys, 1 - dimIndex);
  45886. var cursorOtherValue = (otherExtent[1] + otherExtent[0]) / 2;
  45887. var cursorPoint = [cursorOtherValue, cursorOtherValue];
  45888. cursorPoint[dimIndex] = currPosition[dimIndex];
  45889. return {
  45890. position: currPosition,
  45891. rotation: transform.rotation,
  45892. cursorPoint: cursorPoint,
  45893. tooltipOption: {
  45894. verticalAlign: 'middle'
  45895. }
  45896. };
  45897. }
  45898. });
  45899. var pointerShapeBuilder = {
  45900. line: function (axis, pixelValue, otherExtent, elStyle) {
  45901. var targetShape = viewHelper.makeLineShape(
  45902. [pixelValue, otherExtent[0]],
  45903. [pixelValue, otherExtent[1]],
  45904. getPointDimIndex(axis)
  45905. );
  45906. graphic.subPixelOptimizeLine({
  45907. shape: targetShape,
  45908. style: elStyle
  45909. });
  45910. return {
  45911. type: 'Line',
  45912. shape: targetShape
  45913. };
  45914. },
  45915. shadow: function (axis, pixelValue, otherExtent, elStyle) {
  45916. var bandWidth = axis.getBandWidth();
  45917. var span = otherExtent[1] - otherExtent[0];
  45918. return {
  45919. type: 'Rect',
  45920. shape: viewHelper.makeRectShape(
  45921. [pixelValue - bandWidth / 2, otherExtent[0]],
  45922. [bandWidth, span],
  45923. getPointDimIndex(axis)
  45924. )
  45925. };
  45926. }
  45927. };
  45928. function getPointDimIndex(axis) {
  45929. return axis.isHorizontal() ? 0 : 1;
  45930. }
  45931. function getGlobalExtent(coordSys, dimIndex) {
  45932. var rect = coordSys.getRect();
  45933. return [rect[XY[dimIndex]], rect[XY[dimIndex]] + rect[WH[dimIndex]]];
  45934. }
  45935. AxisView.registerAxisPointerClass('SingleAxisPointer', SingleAxisPointer);
  45936. module.exports = SingleAxisPointer;
  45937. /***/ },
  45938. /* 307 */
  45939. /***/ function(module, exports, __webpack_require__) {
  45940. 'use strict';
  45941. /**
  45942. * @file Define the themeRiver view's series model
  45943. * @author Deqing Li(annong035@gmail.com)
  45944. */
  45945. var completeDimensions = __webpack_require__(110);
  45946. var SeriesModel = __webpack_require__(78);
  45947. var List = __webpack_require__(98);
  45948. var zrUtil = __webpack_require__(4);
  45949. var formatUtil = __webpack_require__(6);
  45950. var encodeHTML = formatUtil.encodeHTML;
  45951. var nest = __webpack_require__(254);
  45952. var DATA_NAME_INDEX = 2;
  45953. var ThemeRiverSeries = SeriesModel.extend({
  45954. type: 'series.themeRiver',
  45955. dependencies: ['singleAxis'],
  45956. /**
  45957. * @readOnly
  45958. * @type {module:zrender/core/util#HashMap}
  45959. */
  45960. nameMap: null,
  45961. /**
  45962. * @override
  45963. */
  45964. init: function (option) {
  45965. ThemeRiverSeries.superApply(this, 'init', arguments);
  45966. // Put this function here is for the sake of consistency of code
  45967. // Enable legend selection for each data item
  45968. // Use a function instead of direct access because data reference may changed
  45969. this.legendDataProvider = function () {
  45970. return this.getRawData();
  45971. };
  45972. },
  45973. /**
  45974. * If there is no value of a certain point in the time for some event,set it value to 0.
  45975. *
  45976. * @param {Array} data initial data in the option
  45977. * @return {Array}
  45978. */
  45979. fixData: function (data) {
  45980. var rawDataLength = data.length;
  45981. // grouped data by name
  45982. var dataByName = nest()
  45983. .key(function (dataItem) {
  45984. return dataItem[2];
  45985. })
  45986. .entries(data);
  45987. // data group in each layer
  45988. var layData = zrUtil.map(dataByName, function (d) {
  45989. return {
  45990. name: d.key,
  45991. dataList: d.values
  45992. };
  45993. });
  45994. var layerNum = layData.length;
  45995. var largestLayer = -1;
  45996. var index = -1;
  45997. for (var i = 0; i < layerNum; ++i) {
  45998. var len = layData[i].dataList.length;
  45999. if (len > largestLayer) {
  46000. largestLayer = len;
  46001. index = i;
  46002. }
  46003. }
  46004. for (var k = 0; k < layerNum; ++k) {
  46005. if (k === index) {
  46006. continue;
  46007. }
  46008. var name = layData[k].name;
  46009. for (var j = 0; j < largestLayer; ++j) {
  46010. var timeValue = layData[index].dataList[j][0];
  46011. var length = layData[k].dataList.length;
  46012. var keyIndex = -1;
  46013. for (var l = 0; l < length; ++l) {
  46014. var value = layData[k].dataList[l][0];
  46015. if (value === timeValue) {
  46016. keyIndex = l;
  46017. break;
  46018. }
  46019. }
  46020. if (keyIndex === -1) {
  46021. data[rawDataLength] = [];
  46022. data[rawDataLength][0] = timeValue;
  46023. data[rawDataLength][1] = 0;
  46024. data[rawDataLength][2] = name;
  46025. rawDataLength++;
  46026. }
  46027. }
  46028. }
  46029. return data;
  46030. },
  46031. /**
  46032. * @override
  46033. * @param {Object} option the initial option that user gived
  46034. * @param {module:echarts/model/Model} ecModel the model object for themeRiver option
  46035. * @return {module:echarts/data/List}
  46036. */
  46037. getInitialData: function (option, ecModel) {
  46038. var dimensions = [];
  46039. var singleAxisModel = ecModel.queryComponents({
  46040. mainType: 'singleAxis',
  46041. index: this.get('singleAxisIndex'),
  46042. id: this.get('singleAxisId')
  46043. })[0];
  46044. var axisType = singleAxisModel.get('type');
  46045. dimensions = [
  46046. {
  46047. name: 'time',
  46048. // FIXME common?
  46049. type: axisType === 'category'
  46050. ? 'ordinal'
  46051. : axisType === 'time'
  46052. ? 'time'
  46053. : 'float'
  46054. },
  46055. {
  46056. name: 'value',
  46057. type: 'float'
  46058. },
  46059. {
  46060. name: 'name',
  46061. type: 'ordinal'
  46062. }
  46063. ];
  46064. // filter the data item with the value of label is undefined
  46065. var filterData = zrUtil.filter(option.data, function (dataItem) {
  46066. return dataItem[2] !== undefined;
  46067. });
  46068. var data = this.fixData(filterData || []);
  46069. var nameList = [];
  46070. var nameMap = this.nameMap = zrUtil.createHashMap();
  46071. var count = 0;
  46072. for (var i = 0; i < data.length; ++i) {
  46073. nameList.push(data[i][DATA_NAME_INDEX]);
  46074. if (!nameMap.get(data[i][DATA_NAME_INDEX])) {
  46075. nameMap.set(data[i][DATA_NAME_INDEX], count);
  46076. count++;
  46077. }
  46078. }
  46079. dimensions = completeDimensions(dimensions, data);
  46080. var list = new List(dimensions, this);
  46081. list.initData(data, nameList);
  46082. return list;
  46083. },
  46084. /**
  46085. * Used by single coordinate
  46086. *
  46087. * @param {string} axisDim the dimension for single coordinate
  46088. * @return {Array.<string> } specified dimensions on the axis.
  46089. */
  46090. coordDimToDataDim: function (axisDim) {
  46091. return ['time'];
  46092. },
  46093. /**
  46094. * The raw data is divided into multiple layers and each layer
  46095. * has same name.
  46096. *
  46097. * @return {Array.<Array.<number>>}
  46098. */
  46099. getLayerSeries: function () {
  46100. var data = this.getData();
  46101. var lenCount = data.count();
  46102. var indexArr = [];
  46103. for (var i = 0; i < lenCount; ++i) {
  46104. indexArr[i] = i;
  46105. }
  46106. // data group by name
  46107. var dataByName = nest()
  46108. .key(function (index) {
  46109. return data.get('name', index);
  46110. })
  46111. .entries(indexArr);
  46112. var layerSeries = zrUtil.map(dataByName, function (d) {
  46113. return {
  46114. name: d.key,
  46115. indices: d.values
  46116. };
  46117. });
  46118. for (var j = 0; j < layerSeries.length; ++j) {
  46119. layerSeries[j].indices.sort(comparer);
  46120. }
  46121. function comparer(index1, index2) {
  46122. return data.get('time', index1) - data.get('time', index2);
  46123. }
  46124. return layerSeries;
  46125. },
  46126. /**
  46127. * Get data indices for show tooltip content
  46128. *
  46129. * @param {Array.<string>|string} dim single coordinate dimension
  46130. * @param {number} value axis value
  46131. * @param {module:echarts/coord/single/SingleAxis} baseAxis single Axis used
  46132. * the themeRiver.
  46133. * @return {Object} {dataIndices, nestestValue}
  46134. */
  46135. getAxisTooltipData: function (dim, value, baseAxis) {
  46136. if (!zrUtil.isArray(dim)) {
  46137. dim = dim ? [dim] : [];
  46138. }
  46139. var data = this.getData();
  46140. var layerSeries = this.getLayerSeries();
  46141. var indices = [];
  46142. var layerNum = layerSeries.length;
  46143. var nestestValue;
  46144. for (var i = 0; i < layerNum; ++i) {
  46145. var minDist = Number.MAX_VALUE;
  46146. var nearestIdx = -1;
  46147. var pointNum = layerSeries[i].indices.length;
  46148. for (var j = 0; j < pointNum; ++j) {
  46149. var theValue = data.get(dim[0], layerSeries[i].indices[j]);
  46150. var dist = Math.abs(theValue - value);
  46151. if (dist <= minDist) {
  46152. nestestValue = theValue;
  46153. minDist = dist;
  46154. nearestIdx = layerSeries[i].indices[j];
  46155. }
  46156. }
  46157. indices.push(nearestIdx);
  46158. }
  46159. return {dataIndices: indices, nestestValue: nestestValue};
  46160. },
  46161. /**
  46162. * @override
  46163. * @param {number} dataIndex index of data
  46164. */
  46165. formatTooltip: function (dataIndex) {
  46166. var data = this.getData();
  46167. var htmlName = data.get('name', dataIndex);
  46168. var htmlValue = data.get('value', dataIndex);
  46169. if (isNaN(htmlValue) || htmlValue == null) {
  46170. htmlValue = '-';
  46171. }
  46172. return encodeHTML(htmlName + ' : ' + htmlValue);
  46173. },
  46174. defaultOption: {
  46175. zlevel: 0,
  46176. z: 2,
  46177. coordinateSystem: 'singleAxis',
  46178. // gap in axis's orthogonal orientation
  46179. boundaryGap: ['10%', '10%'],
  46180. // legendHoverLink: true,
  46181. singleAxisIndex: 0,
  46182. animationEasing: 'linear',
  46183. label: {
  46184. normal: {
  46185. margin: 4,
  46186. textAlign: 'right',
  46187. show: true,
  46188. position: 'left',
  46189. textStyle: {
  46190. color: '#000',
  46191. fontSize: 11
  46192. }
  46193. },
  46194. emphasis: {
  46195. show: true
  46196. }
  46197. }
  46198. }
  46199. });
  46200. module.exports = ThemeRiverSeries;
  46201. /***/ },
  46202. /* 308 */
  46203. /***/ function(module, exports, __webpack_require__) {
  46204. /* WEBPACK VAR INJECTION */(function(process) {/**
  46205. * @file The file used to draw themeRiver view
  46206. * @author Deqing Li(annong035@gmail.com)
  46207. */
  46208. var poly = __webpack_require__(120);
  46209. var graphic = __webpack_require__(18);
  46210. var zrUtil = __webpack_require__(4);
  46211. var DataDiffer = __webpack_require__(99);
  46212. module.exports = __webpack_require__(1).extendChartView({
  46213. type: 'themeRiver',
  46214. init: function () {
  46215. this._layers = [];
  46216. },
  46217. render: function (seriesModel, ecModel, api) {
  46218. var data = seriesModel.getData();
  46219. var rawData = seriesModel.getRawData();
  46220. if (!data.count()) {
  46221. return;
  46222. }
  46223. var group = this.group;
  46224. var layerSeries = seriesModel.getLayerSeries();
  46225. var layoutInfo = data.getLayout('layoutInfo');
  46226. var rect = layoutInfo.rect;
  46227. var boundaryGap = layoutInfo.boundaryGap;
  46228. group.attr('position', [0, rect.y + boundaryGap[0]]);
  46229. function keyGetter(item) {
  46230. return item.name;
  46231. }
  46232. var dataDiffer = new DataDiffer(
  46233. this._layersSeries || [], layerSeries,
  46234. keyGetter, keyGetter
  46235. );
  46236. var newLayersGroups = {};
  46237. dataDiffer.add(zrUtil.bind(zrUtil.curry(process, 'add'), this))
  46238. .update(zrUtil.bind(zrUtil.curry(process, 'update'), this))
  46239. .remove(zrUtil.bind(zrUtil.curry(process, 'remove'), this))
  46240. .execute();
  46241. function process(status, idx, oldIdx) {
  46242. var oldLayersGroups = this._layers;
  46243. if (status === 'remove') {
  46244. group.remove(oldLayersGroups[idx]);
  46245. return;
  46246. }
  46247. var points0 = [];
  46248. var points1 = [];
  46249. var color;
  46250. var indices = layerSeries[idx].indices;
  46251. for (var j = 0; j < indices.length; j++) {
  46252. var layout = data.getItemLayout(indices[j]);
  46253. var x = layout.x;
  46254. var y0 = layout.y0;
  46255. var y = layout.y;
  46256. points0.push([x, y0]);
  46257. points1.push([x, y0 + y]);
  46258. color = rawData.getItemVisual(indices[j], 'color');
  46259. }
  46260. var polygon;
  46261. var text;
  46262. var textLayout = data.getItemLayout(indices[0]);
  46263. var itemModel = data.getItemModel(indices[j - 1]);
  46264. var labelModel = itemModel.getModel('label.normal');
  46265. var margin = labelModel.get('margin');
  46266. if (status === 'add') {
  46267. var layerGroup = newLayersGroups[idx] = new graphic.Group();
  46268. polygon = new poly.Polygon({
  46269. shape: {
  46270. points: points0,
  46271. stackedOnPoints: points1,
  46272. smooth: 0.4,
  46273. stackedOnSmooth: 0.4,
  46274. smoothConstraint: false
  46275. },
  46276. z2: 0
  46277. });
  46278. text = new graphic.Text({
  46279. style: {
  46280. x: textLayout.x - margin,
  46281. y: textLayout.y0 + textLayout.y / 2
  46282. }
  46283. });
  46284. layerGroup.add(polygon);
  46285. layerGroup.add(text);
  46286. group.add(layerGroup);
  46287. polygon.setClipPath(createGridClipShape(polygon.getBoundingRect(), seriesModel, function () {
  46288. polygon.removeClipPath();
  46289. }));
  46290. }
  46291. else {
  46292. var layerGroup = oldLayersGroups[oldIdx];
  46293. polygon = layerGroup.childAt(0);
  46294. text = layerGroup.childAt(1);
  46295. group.add(layerGroup);
  46296. newLayersGroups[idx] = layerGroup;
  46297. graphic.updateProps(polygon, {
  46298. shape: {
  46299. points: points0,
  46300. stackedOnPoints: points1
  46301. }
  46302. }, seriesModel);
  46303. graphic.updateProps(text, {
  46304. style: {
  46305. x: textLayout.x - margin,
  46306. y: textLayout.y0 + textLayout.y / 2
  46307. }
  46308. }, seriesModel);
  46309. }
  46310. var hoverItemStyleModel = itemModel.getModel('itemStyle.emphasis');
  46311. var itemStyleModel = itemModel.getModel('itemStyle.normal');
  46312. var textStyleModel = labelModel.getModel('textStyle');
  46313. text.setStyle({
  46314. text: labelModel.get('show')
  46315. ? seriesModel.getFormattedLabel(indices[j - 1], 'normal')
  46316. || data.getName(indices[j - 1])
  46317. : '',
  46318. textFont: textStyleModel.getFont(),
  46319. textAlign: labelModel.get('textAlign'),
  46320. textVerticalAlign: 'middle'
  46321. });
  46322. polygon.setStyle(zrUtil.extend({
  46323. fill: color
  46324. }, itemStyleModel.getItemStyle(['color'])));
  46325. graphic.setHoverStyle(polygon, hoverItemStyleModel.getItemStyle());
  46326. }
  46327. this._layersSeries = layerSeries;
  46328. this._layers = newLayersGroups;
  46329. },
  46330. dispose: function () {}
  46331. });
  46332. // add animation to the view
  46333. function createGridClipShape(rect, seriesModel, cb) {
  46334. var rectEl = new graphic.Rect({
  46335. shape: {
  46336. x: rect.x - 10,
  46337. y: rect.y - 10,
  46338. width: 0,
  46339. height: rect.height + 20
  46340. }
  46341. });
  46342. graphic.initProps(rectEl, {
  46343. shape: {
  46344. width: rect.width + 20,
  46345. height: rect.height + 20
  46346. }
  46347. }, seriesModel, cb);
  46348. return rectEl;
  46349. }
  46350. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(309)))
  46351. /***/ },
  46352. /* 309 */
  46353. /***/ function(module, exports) {
  46354. // shim for using process in browser
  46355. var process = module.exports = {};
  46356. // cached from whatever global is present so that test runners that stub it
  46357. // don't break things. But we need to wrap it in a try catch in case it is
  46358. // wrapped in strict mode code which doesn't define any globals. It's inside a
  46359. // function because try/catches deoptimize in certain engines.
  46360. var cachedSetTimeout;
  46361. var cachedClearTimeout;
  46362. function defaultSetTimout() {
  46363. throw new Error('setTimeout has not been defined');
  46364. }
  46365. function defaultClearTimeout () {
  46366. throw new Error('clearTimeout has not been defined');
  46367. }
  46368. (function () {
  46369. try {
  46370. if (typeof setTimeout === 'function') {
  46371. cachedSetTimeout = setTimeout;
  46372. } else {
  46373. cachedSetTimeout = defaultSetTimout;
  46374. }
  46375. } catch (e) {
  46376. cachedSetTimeout = defaultSetTimout;
  46377. }
  46378. try {
  46379. if (typeof clearTimeout === 'function') {
  46380. cachedClearTimeout = clearTimeout;
  46381. } else {
  46382. cachedClearTimeout = defaultClearTimeout;
  46383. }
  46384. } catch (e) {
  46385. cachedClearTimeout = defaultClearTimeout;
  46386. }
  46387. } ())
  46388. function runTimeout(fun) {
  46389. if (cachedSetTimeout === setTimeout) {
  46390. //normal enviroments in sane situations
  46391. return setTimeout(fun, 0);
  46392. }
  46393. // if setTimeout wasn't available but was latter defined
  46394. if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
  46395. cachedSetTimeout = setTimeout;
  46396. return setTimeout(fun, 0);
  46397. }
  46398. try {
  46399. // when when somebody has screwed with setTimeout but no I.E. maddness
  46400. return cachedSetTimeout(fun, 0);
  46401. } catch(e){
  46402. try {
  46403. // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
  46404. return cachedSetTimeout.call(null, fun, 0);
  46405. } catch(e){
  46406. // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
  46407. return cachedSetTimeout.call(this, fun, 0);
  46408. }
  46409. }
  46410. }
  46411. function runClearTimeout(marker) {
  46412. if (cachedClearTimeout === clearTimeout) {
  46413. //normal enviroments in sane situations
  46414. return clearTimeout(marker);
  46415. }
  46416. // if clearTimeout wasn't available but was latter defined
  46417. if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
  46418. cachedClearTimeout = clearTimeout;
  46419. return clearTimeout(marker);
  46420. }
  46421. try {
  46422. // when when somebody has screwed with setTimeout but no I.E. maddness
  46423. return cachedClearTimeout(marker);
  46424. } catch (e){
  46425. try {
  46426. // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
  46427. return cachedClearTimeout.call(null, marker);
  46428. } catch (e){
  46429. // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
  46430. // Some versions of I.E. have different rules for clearTimeout vs setTimeout
  46431. return cachedClearTimeout.call(this, marker);
  46432. }
  46433. }
  46434. }
  46435. var queue = [];
  46436. var draining = false;
  46437. var currentQueue;
  46438. var queueIndex = -1;
  46439. function cleanUpNextTick() {
  46440. if (!draining || !currentQueue) {
  46441. return;
  46442. }
  46443. draining = false;
  46444. if (currentQueue.length) {
  46445. queue = currentQueue.concat(queue);
  46446. } else {
  46447. queueIndex = -1;
  46448. }
  46449. if (queue.length) {
  46450. drainQueue();
  46451. }
  46452. }
  46453. function drainQueue() {
  46454. if (draining) {
  46455. return;
  46456. }
  46457. var timeout = runTimeout(cleanUpNextTick);
  46458. draining = true;
  46459. var len = queue.length;
  46460. while(len) {
  46461. currentQueue = queue;
  46462. queue = [];
  46463. while (++queueIndex < len) {
  46464. if (currentQueue) {
  46465. currentQueue[queueIndex].run();
  46466. }
  46467. }
  46468. queueIndex = -1;
  46469. len = queue.length;
  46470. }
  46471. currentQueue = null;
  46472. draining = false;
  46473. runClearTimeout(timeout);
  46474. }
  46475. process.nextTick = function (fun) {
  46476. var args = new Array(arguments.length - 1);
  46477. if (arguments.length > 1) {
  46478. for (var i = 1; i < arguments.length; i++) {
  46479. args[i - 1] = arguments[i];
  46480. }
  46481. }
  46482. queue.push(new Item(fun, args));
  46483. if (queue.length === 1 && !draining) {
  46484. runTimeout(drainQueue);
  46485. }
  46486. };
  46487. // v8 likes predictible objects
  46488. function Item(fun, array) {
  46489. this.fun = fun;
  46490. this.array = array;
  46491. }
  46492. Item.prototype.run = function () {
  46493. this.fun.apply(null, this.array);
  46494. };
  46495. process.title = 'browser';
  46496. process.browser = true;
  46497. process.env = {};
  46498. process.argv = [];
  46499. process.version = ''; // empty string to avoid regexp issues
  46500. process.versions = {};
  46501. function noop() {}
  46502. process.on = noop;
  46503. process.addListener = noop;
  46504. process.once = noop;
  46505. process.off = noop;
  46506. process.removeListener = noop;
  46507. process.removeAllListeners = noop;
  46508. process.emit = noop;
  46509. process.binding = function (name) {
  46510. throw new Error('process.binding is not supported');
  46511. };
  46512. process.cwd = function () { return '/' };
  46513. process.chdir = function (dir) {
  46514. throw new Error('process.chdir is not supported');
  46515. };
  46516. process.umask = function() { return 0; };
  46517. /***/ },
  46518. /* 310 */
  46519. /***/ function(module, exports, __webpack_require__) {
  46520. /**
  46521. * @file Using layout algorithm transform the raw data to layout information.
  46522. * @author Deqing Li(annong035@gmail.com)
  46523. */
  46524. var zrUtil = __webpack_require__(4);
  46525. var numberUtil = __webpack_require__(7);
  46526. module.exports = function (ecModel, api) {
  46527. ecModel.eachSeriesByType('themeRiver', function (seriesModel) {
  46528. var data = seriesModel.getData();
  46529. var single = seriesModel.coordinateSystem;
  46530. var layoutInfo = {};
  46531. // use the axis boundingRect for view
  46532. var rect = single.getRect();
  46533. layoutInfo.rect = rect;
  46534. var boundaryGap = seriesModel.get('boundaryGap');
  46535. var axis = single.getAxis();
  46536. layoutInfo.boundaryGap = boundaryGap;
  46537. if (axis.orient === 'horizontal') {
  46538. boundaryGap[0] = numberUtil.parsePercent(boundaryGap[0], rect.height);
  46539. boundaryGap[1] = numberUtil.parsePercent(boundaryGap[1], rect.height);
  46540. var height = rect.height - boundaryGap[0] - boundaryGap[1];
  46541. themeRiverLayout(data, seriesModel, height);
  46542. }
  46543. else {
  46544. boundaryGap[0] = numberUtil.parsePercent(boundaryGap[0], rect.width);
  46545. boundaryGap[1] = numberUtil.parsePercent(boundaryGap[1], rect.width);
  46546. var width = rect.width - boundaryGap[0] - boundaryGap[1];
  46547. themeRiverLayout(data, seriesModel, width);
  46548. }
  46549. data.setLayout('layoutInfo', layoutInfo);
  46550. });
  46551. };
  46552. /**
  46553. * The layout information about themeriver
  46554. *
  46555. * @param {module:echarts/data/List} data data in the series
  46556. * @param {module:echarts/model/Series} seriesModel the model object of themeRiver series
  46557. * @param {number} height value used to compute every series height
  46558. */
  46559. function themeRiverLayout(data, seriesModel, height) {
  46560. if (!data.count()) {
  46561. return;
  46562. }
  46563. var coordSys = seriesModel.coordinateSystem;
  46564. // the data in each layer are organized into a series.
  46565. var layerSeries = seriesModel.getLayerSeries();
  46566. // the points in each layer.
  46567. var layerPoints = zrUtil.map(layerSeries, function (singleLayer) {
  46568. return zrUtil.map(singleLayer.indices, function (idx) {
  46569. var pt = coordSys.dataToPoint(data.get('time', idx));
  46570. pt[1] = data.get('value', idx);
  46571. return pt;
  46572. });
  46573. });
  46574. var base = computeBaseline(layerPoints);
  46575. var baseLine = base.y0;
  46576. var ky = height / base.max;
  46577. // set layout information for each item.
  46578. var n = layerSeries.length;
  46579. var m = layerSeries[0].indices.length;
  46580. var baseY0;
  46581. for (var j = 0; j < m; ++j) {
  46582. baseY0 = baseLine[j] * ky;
  46583. data.setItemLayout(layerSeries[0].indices[j], {
  46584. layerIndex: 0,
  46585. x: layerPoints[0][j][0],
  46586. y0: baseY0,
  46587. y: layerPoints[0][j][1] * ky
  46588. });
  46589. for (var i = 1; i < n; ++i) {
  46590. baseY0 += layerPoints[i - 1][j][1] * ky;
  46591. data.setItemLayout(layerSeries[i].indices[j], {
  46592. layerIndex: i,
  46593. x: layerPoints[i][j][0],
  46594. y0: baseY0,
  46595. y: layerPoints[i][j][1] * ky
  46596. });
  46597. }
  46598. }
  46599. }
  46600. /**
  46601. * Compute the baseLine of the rawdata
  46602. * Inspired by Lee Byron's paper Stacked Graphs - Geometry & Aesthetics
  46603. *
  46604. * @param {Array.<Array>} data the points in each layer
  46605. * @return {Array}
  46606. */
  46607. function computeBaseline(data) {
  46608. var layerNum = data.length;
  46609. var pointNum = data[0].length;
  46610. var sums = [];
  46611. var y0 = [];
  46612. var max = 0;
  46613. var temp;
  46614. var base = {};
  46615. for (var i = 0; i < pointNum; ++i) {
  46616. for (var j = 0, temp = 0; j < layerNum; ++j) {
  46617. temp += data[j][i][1];
  46618. }
  46619. if (temp > max) {
  46620. max = temp;
  46621. }
  46622. sums.push(temp);
  46623. }
  46624. for (var k = 0; k < pointNum; ++k) {
  46625. y0[k] = (max - sums[k]) / 2;
  46626. }
  46627. max = 0;
  46628. for (var l = 0; l < pointNum; ++l) {
  46629. var sum = sums[l] + y0[l];
  46630. if (sum > max) {
  46631. max = sum;
  46632. }
  46633. }
  46634. base.y0 = y0;
  46635. base.max = max;
  46636. return base;
  46637. }
  46638. /***/ },
  46639. /* 311 */
  46640. /***/ function(module, exports) {
  46641. /**
  46642. * @file Visual encoding for themeRiver view
  46643. * @author Deqing Li(annong035@gmail.com)
  46644. */
  46645. module.exports = function (ecModel) {
  46646. ecModel.eachSeriesByType('themeRiver', function (seriesModel) {
  46647. var data = seriesModel.getData();
  46648. var rawData = seriesModel.getRawData();
  46649. var colorList = seriesModel.get('color');
  46650. data.each(function (index) {
  46651. var name = data.getName(index);
  46652. var color = colorList[(seriesModel.nameMap.get(name) - 1) % colorList.length];
  46653. rawData.setItemVisual(index, 'color', color);
  46654. });
  46655. });
  46656. };
  46657. /***/ },
  46658. /* 312 */
  46659. /***/ function(module, exports, __webpack_require__) {
  46660. var echarts = __webpack_require__(1);
  46661. var zrUtil = __webpack_require__(4);
  46662. var graphicUtil = __webpack_require__(18);
  46663. var labelHelper = __webpack_require__(118);
  46664. var createListFromArray = __webpack_require__(109);
  46665. var barGrid = __webpack_require__(145);
  46666. var ITEM_STYLE_NORMAL_PATH = ['itemStyle', 'normal'];
  46667. var ITEM_STYLE_EMPHASIS_PATH = ['itemStyle', 'emphasis'];
  46668. var LABEL_NORMAL = ['label', 'normal'];
  46669. var LABEL_EMPHASIS = ['label', 'emphasis'];
  46670. /**
  46671. * To reduce total package size of each coordinate systems, the modules `prepareCustom`
  46672. * of each coordinate systems are not required by each coordinate systems directly, but
  46673. * required by the module `custom`.
  46674. *
  46675. * prepareInfoForCustomSeries {Function}: optional
  46676. * @return {Object} {coordSys: {...}, api: {
  46677. * coord: function (data, clamp) {}, // return point in global.
  46678. * size: function (dataSize, dataItem) {} // return size of each axis in coordSys.
  46679. * }}
  46680. */
  46681. var prepareCustoms = {
  46682. cartesian2d: __webpack_require__(313),
  46683. geo: __webpack_require__(314),
  46684. singleAxis: __webpack_require__(315),
  46685. polar: __webpack_require__(316),
  46686. calendar: __webpack_require__(317)
  46687. };
  46688. // ------
  46689. // Model
  46690. // ------
  46691. echarts.extendSeriesModel({
  46692. type: 'series.custom',
  46693. dependencies: ['grid', 'polar', 'geo', 'singleAxis', 'calendar'],
  46694. defaultOption: {
  46695. coordinateSystem: 'cartesian2d',
  46696. zlevel: 0,
  46697. z: 2,
  46698. legendHoverLink: true
  46699. // Cartesian coordinate system
  46700. // xAxisIndex: 0,
  46701. // yAxisIndex: 0,
  46702. // Polar coordinate system
  46703. // polarIndex: 0,
  46704. // Geo coordinate system
  46705. // geoIndex: 0,
  46706. // label: {}
  46707. // itemStyle: {}
  46708. },
  46709. getInitialData: function (option, ecModel) {
  46710. return createListFromArray(option.data, this, ecModel);
  46711. }
  46712. });
  46713. // -----
  46714. // View
  46715. // -----
  46716. echarts.extendChartView({
  46717. type: 'custom',
  46718. /**
  46719. * @private
  46720. * @type {module:echarts/data/List}
  46721. */
  46722. _data: null,
  46723. /**
  46724. * @override
  46725. */
  46726. render: function (customSeries, ecModel, api) {
  46727. var oldData = this._data;
  46728. var data = customSeries.getData();
  46729. var group = this.group;
  46730. var renderItem = makeRenderItem(customSeries, data, ecModel, api);
  46731. data.diff(oldData)
  46732. .add(function (newIdx) {
  46733. data.hasValue(newIdx) && createOrUpdate(
  46734. null, newIdx, renderItem(newIdx), customSeries, group, data
  46735. );
  46736. })
  46737. .update(function (newIdx, oldIdx) {
  46738. var el = oldData.getItemGraphicEl(oldIdx);
  46739. data.hasValue(newIdx)
  46740. ? createOrUpdate(
  46741. el, newIdx, renderItem(newIdx), customSeries, group, data
  46742. )
  46743. : (el && group.remove(el));
  46744. })
  46745. .remove(function (oldIdx) {
  46746. var el = oldData.getItemGraphicEl(oldIdx);
  46747. el && group.remove(el);
  46748. })
  46749. .execute();
  46750. this._data = data;
  46751. }
  46752. });
  46753. function createEl(elOption) {
  46754. var graphicType = elOption.type;
  46755. var el;
  46756. if (graphicType === 'path') {
  46757. var shape = elOption.shape;
  46758. el = graphicUtil.makePath(
  46759. shape.pathData,
  46760. null,
  46761. {
  46762. x: shape.x || 0,
  46763. y: shape.y || 0,
  46764. width: shape.width || 0,
  46765. height: shape.height || 0
  46766. },
  46767. 'center'
  46768. );
  46769. el.__customPathData = elOption.pathData;
  46770. }
  46771. else if (graphicType === 'image') {
  46772. el = new graphicUtil.Image({
  46773. });
  46774. el.__customImagePath = elOption.style.image;
  46775. }
  46776. else if (graphicType === 'text') {
  46777. el = new graphicUtil.Text({
  46778. });
  46779. el.__customText = elOption.style.text;
  46780. }
  46781. else {
  46782. var Clz = graphicUtil[graphicType.charAt(0).toUpperCase() + graphicType.slice(1)];
  46783. if (true) {
  46784. zrUtil.assert(Clz, 'graphic type "' + graphicType + '" can not be found.');
  46785. }
  46786. el = new Clz();
  46787. }
  46788. el.__customGraphicType = graphicType;
  46789. return el;
  46790. }
  46791. function updateEl(el, dataIndex, elOption, animatableModel, data, isInit) {
  46792. var targetProps = {};
  46793. var elOptionStyle = elOption.style || {};
  46794. elOption.shape && (targetProps.shape = zrUtil.clone(elOption.shape));
  46795. elOption.position && (targetProps.position = elOption.position.slice());
  46796. elOption.scale && (targetProps.scale = elOption.scale.slice());
  46797. elOption.origin && (targetProps.origin = elOption.origin.slice());
  46798. elOption.rotation && (targetProps.rotation = elOption.rotation);
  46799. if (el.type === 'image' && elOption.style) {
  46800. var targetStyle = targetProps.style = {};
  46801. zrUtil.each(['x', 'y', 'width', 'height'], function (prop) {
  46802. prepareStyleTransition(prop, targetStyle, elOptionStyle, el.style, isInit);
  46803. });
  46804. }
  46805. if (el.type === 'text' && elOption.style) {
  46806. var targetStyle = targetProps.style = {};
  46807. zrUtil.each(['x', 'y'], function (prop) {
  46808. prepareStyleTransition(prop, targetStyle, elOptionStyle, el.style, isInit);
  46809. });
  46810. }
  46811. if (el.type !== 'group') {
  46812. el.useStyle(elOptionStyle);
  46813. // Init animation.
  46814. if (isInit) {
  46815. el.style.opacity = 0;
  46816. var targetOpacity = elOptionStyle.opacity;
  46817. targetOpacity == null && (targetOpacity = 1);
  46818. graphicUtil.initProps(el, {style: {opacity: targetOpacity}}, animatableModel, dataIndex);
  46819. }
  46820. }
  46821. if (isInit) {
  46822. el.attr(targetProps);
  46823. }
  46824. else {
  46825. graphicUtil.updateProps(el, targetProps, animatableModel, dataIndex);
  46826. }
  46827. // z2 must not be null/undefined, otherwise sort error may occur.
  46828. el.attr({z2: elOption.z2 || 0, silent: elOption.silent});
  46829. el.styleEmphasis !== false && graphicUtil.setHoverStyle(el, el.styleEmphasis);
  46830. }
  46831. function prepareStyleTransition(prop, targetStyle, elOptionStyle, oldElStyle, isInit) {
  46832. if (elOptionStyle[prop] != null && !isInit) {
  46833. targetStyle[prop] = elOptionStyle[prop];
  46834. elOptionStyle[prop] = oldElStyle[prop];
  46835. }
  46836. }
  46837. function makeRenderItem(customSeries, data, ecModel, api) {
  46838. var renderItem = customSeries.get('renderItem');
  46839. var coordSys = customSeries.coordinateSystem;
  46840. if (true) {
  46841. zrUtil.assert(renderItem, 'series.render is required.');
  46842. zrUtil.assert(prepareCustoms[coordSys.type], 'This coordSys does not support custom series.');
  46843. }
  46844. var prepareResult = prepareCustoms[coordSys.type](coordSys);
  46845. var userAPI = zrUtil.defaults({
  46846. getWidth: api.getWidth,
  46847. getHeight: api.getHeight,
  46848. getZr: api.getZr,
  46849. getDevicePixelRatio: api.getDevicePixelRatio,
  46850. value: value,
  46851. style: style,
  46852. styleEmphasis: styleEmphasis,
  46853. visual: visual,
  46854. barLayout: barLayout,
  46855. currentSeriesIndices: currentSeriesIndices,
  46856. font: font
  46857. }, prepareResult.api);
  46858. var userParams = {
  46859. context: {},
  46860. seriesId: customSeries.id,
  46861. seriesName: customSeries.name,
  46862. seriesIndex: customSeries.seriesIndex,
  46863. coordSys: prepareResult.coordSys,
  46864. dataInsideLength: data.count(),
  46865. encode: wrapEncodeDef(customSeries.getData())
  46866. };
  46867. // Do not support call `api` asynchronously without dataIndexInside input.
  46868. var currDataIndexInside;
  46869. var currDirty = true;
  46870. var currItemModel;
  46871. var currLabelNormalModel;
  46872. var currLabelEmphasisModel;
  46873. var currLabelValueDim;
  46874. var currVisualColor;
  46875. return function (dataIndexInside) {
  46876. currDataIndexInside = dataIndexInside;
  46877. currDirty = true;
  46878. return renderItem && renderItem(
  46879. zrUtil.defaults({
  46880. dataIndexInside: dataIndexInside,
  46881. dataIndex: data.getRawIndex(dataIndexInside)
  46882. }, userParams),
  46883. userAPI
  46884. ) || {};
  46885. };
  46886. // Do not update cache until api called.
  46887. function updateCache(dataIndexInside) {
  46888. dataIndexInside == null && (dataIndexInside = currDataIndexInside);
  46889. if (currDirty) {
  46890. currItemModel = data.getItemModel(dataIndexInside);
  46891. currLabelNormalModel = currItemModel.getModel(LABEL_NORMAL);
  46892. currLabelEmphasisModel = currItemModel.getModel(LABEL_EMPHASIS);
  46893. currLabelValueDim = labelHelper.findLabelValueDim(data);
  46894. currVisualColor = data.getItemVisual(dataIndexInside, 'color');
  46895. currDirty = false;
  46896. }
  46897. }
  46898. /**
  46899. * @public
  46900. * @param {nubmer|string} dim
  46901. * @param {number} [dataIndexInside=currDataIndexInside]
  46902. * @return {number|string} value
  46903. */
  46904. function value(dim, dataIndexInside) {
  46905. dataIndexInside == null && (dataIndexInside = currDataIndexInside);
  46906. return data.get(data.getDimension(dim || 0), dataIndexInside);
  46907. }
  46908. /**
  46909. * By default, `visual` is applied to style (to support visualMap).
  46910. * `visual.color` is applied at `fill`. If user want apply visual.color on `stroke`,
  46911. * it can be implemented as:
  46912. * `api.style({stroke: api.visual('color'), fill: null})`;
  46913. * @public
  46914. * @param {Object} [extra]
  46915. * @param {number} [dataIndexInside=currDataIndexInside]
  46916. */
  46917. function style(extra, dataIndexInside) {
  46918. dataIndexInside == null && (dataIndexInside = currDataIndexInside);
  46919. updateCache(dataIndexInside);
  46920. var itemStyle = currItemModel.getModel(ITEM_STYLE_NORMAL_PATH).getItemStyle();
  46921. currVisualColor != null && (itemStyle.fill = currVisualColor);
  46922. var opacity = data.getItemVisual(dataIndexInside, 'opacity');
  46923. opacity != null && (itemStyle.opacity = opacity);
  46924. labelHelper.setTextToStyle(
  46925. data, dataIndexInside, currLabelValueDim, itemStyle,
  46926. customSeries, currLabelNormalModel, currVisualColor
  46927. );
  46928. extra && zrUtil.extend(itemStyle, extra);
  46929. return itemStyle;
  46930. }
  46931. /**
  46932. * @public
  46933. * @param {Object} [extra]
  46934. * @param {number} [dataIndexInside=currDataIndexInside]
  46935. */
  46936. function styleEmphasis(extra, dataIndexInside) {
  46937. dataIndexInside == null && (dataIndexInside = currDataIndexInside);
  46938. updateCache(dataIndexInside);
  46939. var itemStyle = currItemModel.getModel(ITEM_STYLE_EMPHASIS_PATH).getItemStyle();
  46940. labelHelper.setTextToStyle(
  46941. data, dataIndexInside, currLabelValueDim, itemStyle,
  46942. customSeries, currLabelEmphasisModel, currVisualColor
  46943. );
  46944. extra && zrUtil.extend(itemStyle, extra);
  46945. return itemStyle;
  46946. }
  46947. /**
  46948. * @public
  46949. * @param {string} visualType
  46950. * @param {number} [dataIndexInside=currDataIndexInside]
  46951. */
  46952. function visual(visualType, dataIndexInside) {
  46953. dataIndexInside == null && (dataIndexInside = currDataIndexInside);
  46954. return data.getItemVisual(dataIndexInside, visualType);
  46955. }
  46956. /**
  46957. * @public
  46958. * @param {number} opt.count Positive interger.
  46959. * @param {number} [opt.barWidth]
  46960. * @param {number} [opt.barMaxWidth]
  46961. * @param {number} [opt.barGap]
  46962. * @param {number} [opt.barCategoryGap]
  46963. * @return {Object} {width, offset, offsetCenter} is not support, return undefined.
  46964. */
  46965. function barLayout(opt) {
  46966. if (coordSys.getBaseAxis) {
  46967. var baseAxis = coordSys.getBaseAxis();
  46968. return barGrid.getLayoutOnAxis(zrUtil.defaults({axis: baseAxis}, opt), api);
  46969. }
  46970. }
  46971. /**
  46972. * @public
  46973. * @return {Array.<number>}
  46974. */
  46975. function currentSeriesIndices() {
  46976. return ecModel.getCurrentSeriesIndices();
  46977. }
  46978. /**
  46979. * @public
  46980. * @param {Object} opt
  46981. * @param {string} [opt.fontStyle]
  46982. * @param {number} [opt.fontWeight]
  46983. * @param {number} [opt.fontSize]
  46984. * @param {string} [opt.fontFamily]
  46985. * @return {string} font string
  46986. */
  46987. function font(opt) {
  46988. return graphicUtil.getFont(opt, ecModel);
  46989. }
  46990. }
  46991. function wrapEncodeDef(data) {
  46992. var encodeDef = {};
  46993. zrUtil.each(data.dimensions, function (dimName, dataDimIndex) {
  46994. var dimInfo = data.getDimensionInfo(dimName);
  46995. if (!dimInfo.isExtraCoord) {
  46996. var coordDim = dimInfo.coordDim;
  46997. var dataDims = encodeDef[coordDim] = encodeDef[coordDim] || [];
  46998. dataDims[dimInfo.coordDimIndex] = dataDimIndex;
  46999. }
  47000. });
  47001. return encodeDef;
  47002. }
  47003. function createOrUpdate(el, dataIndex, elOption, animatableModel, group, data) {
  47004. el = doCreateOrUpdate(el, dataIndex, elOption, animatableModel, group, data);
  47005. el && data.setItemGraphicEl(dataIndex, el);
  47006. }
  47007. function doCreateOrUpdate(el, dataIndex, elOption, animatableModel, group, data) {
  47008. var elOptionType = elOption.type;
  47009. if (el
  47010. && elOptionType !== el.__customGraphicType
  47011. && (elOptionType !== 'path' || elOption.pathData !== el.__customPathData)
  47012. && (elOptionType !== 'image' || elOption.style.image !== el.__customImagePath)
  47013. && (elOptionType !== 'text' || elOption.style.text !== el.__customText)
  47014. ) {
  47015. group.remove(el);
  47016. el = null;
  47017. }
  47018. // `elOption.type` is undefined when `renderItem` returns nothing.
  47019. if (elOptionType == null) {
  47020. return;
  47021. }
  47022. var isInit = !el;
  47023. !el && (el = createEl(elOption));
  47024. updateEl(el, dataIndex, elOption, animatableModel, data, isInit);
  47025. elOptionType === 'group' && zrUtil.each(elOption.children, function (childOption, index) {
  47026. doCreateOrUpdate(el.childAt(index), dataIndex, childOption, animatableModel, el, data);
  47027. });
  47028. group.add(el);
  47029. return el;
  47030. }
  47031. /***/ },
  47032. /* 313 */
  47033. /***/ function(module, exports, __webpack_require__) {
  47034. var zrUtil = __webpack_require__(4);
  47035. function dataToCoordSize(dataSize, dataItem) {
  47036. // dataItem is necessary in log axis.
  47037. dataItem = dataItem || [0, 0];
  47038. return zrUtil.map(['x', 'y'], function (dim, dimIdx) {
  47039. var axis = this.getAxis(dim);
  47040. var val = dataItem[dimIdx];
  47041. var halfSize = dataSize[dimIdx] / 2;
  47042. return axis.type === 'category'
  47043. ? axis.getBandWidth()
  47044. : Math.abs(axis.dataToCoord(val - halfSize) - axis.dataToCoord(val + halfSize));
  47045. }, this);
  47046. }
  47047. function prepareCustom(coordSys) {
  47048. var rect = coordSys.grid.getRect();
  47049. return {
  47050. coordSys: {
  47051. // The name exposed to user is always 'cartesian2d' but not 'grid'.
  47052. type: 'cartesian2d',
  47053. x: rect.x,
  47054. y: rect.y,
  47055. width: rect.width,
  47056. height: rect.height
  47057. },
  47058. api: {
  47059. coord: zrUtil.bind(coordSys.dataToPoint, coordSys),
  47060. size: zrUtil.bind(dataToCoordSize, coordSys)
  47061. }
  47062. };
  47063. }
  47064. module.exports = prepareCustom;
  47065. /***/ },
  47066. /* 314 */
  47067. /***/ function(module, exports, __webpack_require__) {
  47068. var zrUtil = __webpack_require__(4);
  47069. function dataToCoordSize(dataSize, dataItem) {
  47070. dataItem = dataItem || [0, 0];
  47071. return zrUtil.map([0, 1], function (dimIdx) {
  47072. var val = dataItem[dimIdx];
  47073. var halfSize = dataSize[dimIdx] / 2;
  47074. var p1 = [];
  47075. var p2 = [];
  47076. p1[dimIdx] = val - halfSize;
  47077. p2[dimIdx] = val + halfSize;
  47078. p1[1 - dimIdx] = p2[1 - dimIdx] = dataItem[1 - dimIdx];
  47079. return Math.abs(this.dataToPoint(p1)[dimIdx] - this.dataToPoint(p2)[dimIdx]);
  47080. }, this);
  47081. }
  47082. function prepareCustom(coordSys) {
  47083. var rect = coordSys.getBoundingRect();
  47084. return {
  47085. coordSys: {
  47086. type: 'geo',
  47087. x: rect.x,
  47088. y: rect.y,
  47089. width: rect.width,
  47090. height: rect.height
  47091. },
  47092. api: {
  47093. coord: zrUtil.bind(coordSys.dataToPoint, coordSys),
  47094. size: zrUtil.bind(dataToCoordSize, coordSys)
  47095. }
  47096. };
  47097. }
  47098. module.exports = prepareCustom;
  47099. /***/ },
  47100. /* 315 */
  47101. /***/ function(module, exports, __webpack_require__) {
  47102. var zrUtil = __webpack_require__(4);
  47103. function dataToCoordSize(dataSize, dataItem) {
  47104. // dataItem is necessary in log axis.
  47105. var axis = this.getAxis();
  47106. var val = dataItem instanceof Array ? dataItem[0] : dataItem;
  47107. var halfSize = (dataSize instanceof Array ? dataSize[0] : dataSize) / 2;
  47108. return axis.type === 'category'
  47109. ? axis.getBandWidth()
  47110. : Math.abs(axis.dataToCoord(val - halfSize) - axis.dataToCoord(val + halfSize));
  47111. }
  47112. function prepareCustom(coordSys) {
  47113. var rect = coordSys.getRect();
  47114. return {
  47115. coordSys: {
  47116. type: 'singleAxis',
  47117. x: rect.x,
  47118. y: rect.y,
  47119. width: rect.width,
  47120. height: rect.height
  47121. },
  47122. api: {
  47123. coord: zrUtil.bind(coordSys.dataToPoint, coordSys),
  47124. size: zrUtil.bind(dataToCoordSize, coordSys)
  47125. }
  47126. };
  47127. }
  47128. module.exports = prepareCustom;
  47129. /***/ },
  47130. /* 316 */
  47131. /***/ function(module, exports, __webpack_require__) {
  47132. var zrUtil = __webpack_require__(4);
  47133. function dataToCoordSize(dataSize, dataItem) {
  47134. // dataItem is necessary in log axis.
  47135. return zrUtil.map(['Radius', 'Angle'], function (dim, dimIdx) {
  47136. var axis = this['get' + dim + 'Axis']();
  47137. var val = dataItem[dimIdx];
  47138. var halfSize = dataSize[dimIdx] / 2;
  47139. var method = 'dataTo' + dim;
  47140. var result = axis.type === 'category'
  47141. ? axis.getBandWidth()
  47142. : Math.abs(axis[method](val - halfSize) - axis[method](val + halfSize));
  47143. if (dim === 'Angle') {
  47144. result = result * Math.PI / 180;
  47145. }
  47146. return result;
  47147. }, this);
  47148. }
  47149. function prepareCustom(coordSys) {
  47150. var radiusAxis = coordSys.getRadiusAxis();
  47151. var angleAxis = coordSys.getAngleAxis();
  47152. var radius = radiusAxis.getExtent();
  47153. radius[0] > radius[1] && radius.reverse();
  47154. return {
  47155. coordSys: {
  47156. type: 'polar',
  47157. cx: coordSys.cx,
  47158. cy: coordSys.cy,
  47159. r: radius[1],
  47160. r0: radius[0]
  47161. },
  47162. api: {
  47163. coord: zrUtil.bind(function (data) {
  47164. var radius = radiusAxis.dataToRadius(data[0]);
  47165. var angle = angleAxis.dataToAngle(data[1]);
  47166. var coord = coordSys.coordToPoint([radius, angle]);
  47167. coord.push(radius, angle * Math.PI / 180);
  47168. return coord;
  47169. }),
  47170. size: zrUtil.bind(dataToCoordSize, coordSys)
  47171. }
  47172. };
  47173. }
  47174. module.exports = prepareCustom;
  47175. /***/ },
  47176. /* 317 */
  47177. /***/ function(module, exports, __webpack_require__) {
  47178. var zrUtil = __webpack_require__(4);
  47179. function prepareCustom(coordSys) {
  47180. var rect = coordSys.getRect();
  47181. var rangeInfo = coordSys.getRangeInfo();
  47182. return {
  47183. coordSys: {
  47184. type: 'calendar',
  47185. x: rect.x,
  47186. y: rect.y,
  47187. width: rect.width,
  47188. height: rect.height,
  47189. cellWidth: coordSys.getCellWidth(),
  47190. cellHeight: coordSys.getCellHeight(),
  47191. rangeInfo: {
  47192. start: rangeInfo.start,
  47193. end: rangeInfo.end,
  47194. weeks: rangeInfo.weeks,
  47195. dayCount: rangeInfo.allDay
  47196. }
  47197. },
  47198. api: {
  47199. coord: zrUtil.bind(coordSys.dataToPoint, coordSys)
  47200. }
  47201. };
  47202. }
  47203. module.exports = prepareCustom;
  47204. /***/ },
  47205. /* 318 */
  47206. /***/ function(module, exports, __webpack_require__) {
  47207. var echarts = __webpack_require__(1);
  47208. var zrUtil = __webpack_require__(4);
  47209. var modelUtil = __webpack_require__(5);
  47210. var graphicUtil = __webpack_require__(18);
  47211. var layoutUtil = __webpack_require__(71);
  47212. // -------------
  47213. // Preprocessor
  47214. // -------------
  47215. echarts.registerPreprocessor(function (option) {
  47216. var graphicOption = option.graphic;
  47217. // Convert
  47218. // {graphic: [{left: 10, type: 'circle'}, ...]}
  47219. // or
  47220. // {graphic: {left: 10, type: 'circle'}}
  47221. // to
  47222. // {graphic: [{elements: [{left: 10, type: 'circle'}, ...]}]}
  47223. if (zrUtil.isArray(graphicOption)) {
  47224. if (!graphicOption[0] || !graphicOption[0].elements) {
  47225. option.graphic = [{elements: graphicOption}];
  47226. }
  47227. else {
  47228. // Only one graphic instance can be instantiated. (We dont
  47229. // want that too many views are created in echarts._viewMap)
  47230. option.graphic = [option.graphic[0]];
  47231. }
  47232. }
  47233. else if (graphicOption && !graphicOption.elements) {
  47234. option.graphic = [{elements: [graphicOption]}];
  47235. }
  47236. });
  47237. // ------
  47238. // Model
  47239. // ------
  47240. var GraphicModel = echarts.extendComponentModel({
  47241. type: 'graphic',
  47242. defaultOption: {
  47243. // Extra properties for each elements:
  47244. //
  47245. // left/right/top/bottom: (like 12, '22%', 'center', default undefined)
  47246. // If left/rigth is set, shape.x/shape.cx/position will not be used.
  47247. // If top/bottom is set, shape.y/shape.cy/position will not be used.
  47248. // This mechanism is useful when you want to position a group/element
  47249. // against the right side or the center of this container.
  47250. //
  47251. // width/height: (can only be pixel value, default 0)
  47252. // Only be used to specify contianer(group) size, if needed. And
  47253. // can not be percentage value (like '33%'). See the reason in the
  47254. // layout algorithm below.
  47255. //
  47256. // bounding: (enum: 'all' (default) | 'raw')
  47257. // Specify how to calculate boundingRect when locating.
  47258. // 'all': Get uioned and transformed boundingRect
  47259. // from both itself and its descendants.
  47260. // This mode simplies confining a group of elements in the bounding
  47261. // of their ancester container (e.g., using 'right: 0').
  47262. // 'raw': Only use the boundingRect of itself and before transformed.
  47263. // This mode is similar to css behavior, which is useful when you
  47264. // want an element to be able to overflow its container. (Consider
  47265. // a rotated circle needs to be located in a corner.)
  47266. // Note: elements is always behind its ancestors in this elements array.
  47267. elements: [],
  47268. parentId: null
  47269. },
  47270. /**
  47271. * Save el options for the sake of the performance (only update modified graphics).
  47272. * The order is the same as those in option. (ancesters -> descendants)
  47273. *
  47274. * @private
  47275. * @type {Array.<Object>}
  47276. */
  47277. _elOptionsToUpdate: null,
  47278. /**
  47279. * @override
  47280. */
  47281. mergeOption: function (option) {
  47282. // Prevent default merge to elements
  47283. var elements = this.option.elements;
  47284. this.option.elements = null;
  47285. GraphicModel.superApply(this, 'mergeOption', arguments);
  47286. this.option.elements = elements;
  47287. },
  47288. /**
  47289. * @override
  47290. */
  47291. optionUpdated: function (newOption, isInit) {
  47292. var thisOption = this.option;
  47293. var newList = (isInit ? thisOption : newOption).elements;
  47294. var existList = thisOption.elements = isInit ? [] : thisOption.elements;
  47295. var flattenedList = [];
  47296. this._flatten(newList, flattenedList);
  47297. var mappingResult = modelUtil.mappingToExists(existList, flattenedList);
  47298. modelUtil.makeIdAndName(mappingResult);
  47299. // Clear elOptionsToUpdate
  47300. var elOptionsToUpdate = this._elOptionsToUpdate = [];
  47301. zrUtil.each(mappingResult, function (resultItem, index) {
  47302. var newElOption = resultItem.option;
  47303. if (true) {
  47304. zrUtil.assert(
  47305. zrUtil.isObject(newElOption) || resultItem.exist,
  47306. 'Empty graphic option definition'
  47307. );
  47308. }
  47309. if (!newElOption) {
  47310. return;
  47311. }
  47312. elOptionsToUpdate.push(newElOption);
  47313. setKeyInfoToNewElOption(resultItem, newElOption);
  47314. mergeNewElOptionToExist(existList, index, newElOption);
  47315. setLayoutInfoToExist(existList[index], newElOption);
  47316. }, this);
  47317. // Clean
  47318. for (var i = existList.length - 1; i >= 0; i--) {
  47319. if (existList[i] == null) {
  47320. existList.splice(i, 1);
  47321. }
  47322. else {
  47323. // $action should be volatile, otherwise option gotten from
  47324. // `getOption` will contain unexpected $action.
  47325. delete existList[i].$action;
  47326. }
  47327. }
  47328. },
  47329. /**
  47330. * Convert
  47331. * [{
  47332. * type: 'group',
  47333. * id: 'xx',
  47334. * children: [{type: 'circle'}, {type: 'polygon'}]
  47335. * }]
  47336. * to
  47337. * [
  47338. * {type: 'group', id: 'xx'},
  47339. * {type: 'circle', parentId: 'xx'},
  47340. * {type: 'polygon', parentId: 'xx'}
  47341. * ]
  47342. *
  47343. * @private
  47344. * @param {Array.<Object>} optionList option list
  47345. * @param {Array.<Object>} result result of flatten
  47346. * @param {Object} parentOption parent option
  47347. */
  47348. _flatten: function (optionList, result, parentOption) {
  47349. zrUtil.each(optionList, function (option) {
  47350. if (!option) {
  47351. return;
  47352. }
  47353. if (parentOption) {
  47354. option.parentOption = parentOption;
  47355. }
  47356. result.push(option);
  47357. var children = option.children;
  47358. if (option.type === 'group' && children) {
  47359. this._flatten(children, result, option);
  47360. }
  47361. // Deleting for JSON output, and for not affecting group creation.
  47362. delete option.children;
  47363. }, this);
  47364. },
  47365. // FIXME
  47366. // Pass to view using payload? setOption has a payload?
  47367. useElOptionsToUpdate: function () {
  47368. var els = this._elOptionsToUpdate;
  47369. // Clear to avoid render duplicately when zooming.
  47370. this._elOptionsToUpdate = null;
  47371. return els;
  47372. }
  47373. });
  47374. // -----
  47375. // View
  47376. // -----
  47377. echarts.extendComponentView({
  47378. type: 'graphic',
  47379. /**
  47380. * @override
  47381. */
  47382. init: function (ecModel, api) {
  47383. /**
  47384. * @private
  47385. * @type {module:zrender/core/util.HashMap}
  47386. */
  47387. this._elMap = zrUtil.createHashMap();
  47388. /**
  47389. * @private
  47390. * @type {module:echarts/graphic/GraphicModel}
  47391. */
  47392. this._lastGraphicModel;
  47393. },
  47394. /**
  47395. * @override
  47396. */
  47397. render: function (graphicModel, ecModel, api) {
  47398. // Having leveraged between use cases and algorithm complexity, a very
  47399. // simple layout mechanism is used:
  47400. // The size(width/height) can be determined by itself or its parent (not
  47401. // implemented yet), but can not by its children. (Top-down travel)
  47402. // The location(x/y) can be determined by the bounding rect of itself
  47403. // (can including its descendants or not) and the size of its parent.
  47404. // (Bottom-up travel)
  47405. // When `chart.clear()` or `chart.setOption({...}, true)` with the same id,
  47406. // view will be reused.
  47407. if (graphicModel !== this._lastGraphicModel) {
  47408. this._clear();
  47409. }
  47410. this._lastGraphicModel = graphicModel;
  47411. this._updateElements(graphicModel, api);
  47412. this._relocate(graphicModel, api);
  47413. },
  47414. /**
  47415. * Update graphic elements.
  47416. *
  47417. * @private
  47418. * @param {Object} graphicModel graphic model
  47419. * @param {module:echarts/ExtensionAPI} api extension API
  47420. */
  47421. _updateElements: function (graphicModel, api) {
  47422. var elOptionsToUpdate = graphicModel.useElOptionsToUpdate();
  47423. if (!elOptionsToUpdate) {
  47424. return;
  47425. }
  47426. var elMap = this._elMap;
  47427. var rootGroup = this.group;
  47428. // Top-down tranverse to assign graphic settings to each elements.
  47429. zrUtil.each(elOptionsToUpdate, function (elOption) {
  47430. var $action = elOption.$action;
  47431. var id = elOption.id;
  47432. var existEl = elMap.get(id);
  47433. var parentId = elOption.parentId;
  47434. var targetElParent = parentId != null ? elMap.get(parentId) : rootGroup;
  47435. // In top/bottom mode, textVertical should not be used. And textBaseline
  47436. // should not be 'alphabetic', which cause inaccurately locating.
  47437. if (elOption.hv && elOption.hv[1] && elOption.type === 'text') {
  47438. elOption.style = zrUtil.defaults({textBaseline: 'middle'}, elOption.style);
  47439. elOption.style.textVerticalAlign = null;
  47440. }
  47441. // Remove unnecessary props to avoid potential problems.
  47442. var elOptionCleaned = getCleanedElOption(elOption);
  47443. // For simple, do not support parent change, otherwise reorder is needed.
  47444. if (true) {
  47445. existEl && zrUtil.assert(
  47446. targetElParent === existEl.parent,
  47447. 'Changing parent is not supported.'
  47448. );
  47449. }
  47450. if (!$action || $action === 'merge') {
  47451. existEl
  47452. ? existEl.attr(elOptionCleaned)
  47453. : createEl(id, targetElParent, elOptionCleaned, elMap);
  47454. }
  47455. else if ($action === 'replace') {
  47456. removeEl(existEl, elMap);
  47457. createEl(id, targetElParent, elOptionCleaned, elMap);
  47458. }
  47459. else if ($action === 'remove') {
  47460. removeEl(existEl, elMap);
  47461. }
  47462. var el = elMap.get(id);
  47463. if (el) {
  47464. el.__ecGraphicWidth = elOption.width;
  47465. el.__ecGraphicHeight = elOption.height;
  47466. }
  47467. });
  47468. },
  47469. /**
  47470. * Locate graphic elements.
  47471. *
  47472. * @private
  47473. * @param {Object} graphicModel graphic model
  47474. * @param {module:echarts/ExtensionAPI} api extension API
  47475. */
  47476. _relocate: function (graphicModel, api) {
  47477. var elOptions = graphicModel.option.elements;
  47478. var rootGroup = this.group;
  47479. var elMap = this._elMap;
  47480. // Bottom-up tranvese all elements (consider ec resize) to locate elements.
  47481. for (var i = elOptions.length - 1; i >= 0; i--) {
  47482. var elOption = elOptions[i];
  47483. var el = elMap.get(elOption.id);
  47484. if (!el) {
  47485. continue;
  47486. }
  47487. var parentEl = el.parent;
  47488. var containerInfo = parentEl === rootGroup
  47489. ? {
  47490. width: api.getWidth(),
  47491. height: api.getHeight()
  47492. }
  47493. : { // Like 'position:absolut' in css, default 0.
  47494. width: parentEl.__ecGraphicWidth || 0,
  47495. height: parentEl.__ecGraphicHeight || 0
  47496. };
  47497. layoutUtil.positionElement(
  47498. el, elOption, containerInfo, null,
  47499. {hv: elOption.hv, boundingMode: elOption.bounding}
  47500. );
  47501. }
  47502. },
  47503. /**
  47504. * Clear all elements.
  47505. *
  47506. * @private
  47507. */
  47508. _clear: function () {
  47509. var elMap = this._elMap;
  47510. elMap.each(function (el) {
  47511. removeEl(el, elMap);
  47512. });
  47513. this._elMap = zrUtil.createHashMap();
  47514. },
  47515. /**
  47516. * @override
  47517. */
  47518. dispose: function () {
  47519. this._clear();
  47520. }
  47521. });
  47522. function createEl(id, targetElParent, elOption, elMap) {
  47523. var graphicType = elOption.type;
  47524. if (true) {
  47525. zrUtil.assert(graphicType, 'graphic type MUST be set');
  47526. }
  47527. var Clz = graphicUtil[graphicType.charAt(0).toUpperCase() + graphicType.slice(1)];
  47528. if (true) {
  47529. zrUtil.assert(Clz, 'graphic type can not be found');
  47530. }
  47531. var el = new Clz(elOption);
  47532. targetElParent.add(el);
  47533. elMap.set(id, el);
  47534. el.__ecGraphicId = id;
  47535. }
  47536. function removeEl(existEl, elMap) {
  47537. var existElParent = existEl && existEl.parent;
  47538. if (existElParent) {
  47539. existEl.type === 'group' && existEl.traverse(function (el) {
  47540. removeEl(el, elMap);
  47541. });
  47542. elMap.removeKey(existEl.__ecGraphicId);
  47543. existElParent.remove(existEl);
  47544. }
  47545. }
  47546. // Remove unnecessary props to avoid potential problems.
  47547. function getCleanedElOption(elOption) {
  47548. elOption = zrUtil.extend({}, elOption);
  47549. zrUtil.each(
  47550. ['id', 'parentId', '$action', 'hv', 'bounding'].concat(layoutUtil.LOCATION_PARAMS),
  47551. function (name) {
  47552. delete elOption[name];
  47553. }
  47554. );
  47555. return elOption;
  47556. }
  47557. function isSetLoc(obj, props) {
  47558. var isSet;
  47559. zrUtil.each(props, function (prop) {
  47560. obj[prop] != null && obj[prop] !== 'auto' && (isSet = true);
  47561. });
  47562. return isSet;
  47563. }
  47564. function setKeyInfoToNewElOption(resultItem, newElOption) {
  47565. var existElOption = resultItem.exist;
  47566. // Set id and type after id assigned.
  47567. newElOption.id = resultItem.keyInfo.id;
  47568. !newElOption.type && existElOption && (newElOption.type = existElOption.type);
  47569. // Set parent id if not specified
  47570. if (newElOption.parentId == null) {
  47571. var newElParentOption = newElOption.parentOption;
  47572. if (newElParentOption) {
  47573. newElOption.parentId = newElParentOption.id;
  47574. }
  47575. else if (existElOption) {
  47576. newElOption.parentId = existElOption.parentId;
  47577. }
  47578. }
  47579. // Clear
  47580. newElOption.parentOption = null;
  47581. }
  47582. function mergeNewElOptionToExist(existList, index, newElOption) {
  47583. // Update existing options, for `getOption` feature.
  47584. var newElOptCopy = zrUtil.extend({}, newElOption);
  47585. var existElOption = existList[index];
  47586. var $action = newElOption.$action || 'merge';
  47587. if ($action === 'merge') {
  47588. if (existElOption) {
  47589. if (true) {
  47590. var newType = newElOption.type;
  47591. zrUtil.assert(
  47592. !newType || existElOption.type === newType,
  47593. 'Please set $action: "replace" to change `type`'
  47594. );
  47595. }
  47596. // We can ensure that newElOptCopy and existElOption are not
  47597. // the same object, so `merge` will not change newElOptCopy.
  47598. zrUtil.merge(existElOption, newElOptCopy, true);
  47599. // Rigid body, use ignoreSize.
  47600. layoutUtil.mergeLayoutParam(existElOption, newElOptCopy, {ignoreSize: true});
  47601. // Will be used in render.
  47602. layoutUtil.copyLayoutParams(newElOption, existElOption);
  47603. }
  47604. else {
  47605. existList[index] = newElOptCopy;
  47606. }
  47607. }
  47608. else if ($action === 'replace') {
  47609. existList[index] = newElOptCopy;
  47610. }
  47611. else if ($action === 'remove') {
  47612. // null will be cleaned later.
  47613. existElOption && (existList[index] = null);
  47614. }
  47615. }
  47616. function setLayoutInfoToExist(existItem, newElOption) {
  47617. if (!existItem) {
  47618. return;
  47619. }
  47620. existItem.hv = newElOption.hv = [
  47621. // Rigid body, dont care `width`.
  47622. isSetLoc(newElOption, ['left', 'right']),
  47623. // Rigid body, dont care `height`.
  47624. isSetLoc(newElOption, ['top', 'bottom'])
  47625. ];
  47626. // Give default group size. Otherwise layout error may occur.
  47627. if (existItem.type === 'group') {
  47628. existItem.width == null && (existItem.width = newElOption.width = 0);
  47629. existItem.height == null && (existItem.height = newElOption.height = 0);
  47630. }
  47631. }
  47632. /***/ },
  47633. /* 319 */
  47634. /***/ function(module, exports, __webpack_require__) {
  47635. __webpack_require__(124);
  47636. __webpack_require__(303);
  47637. __webpack_require__(297);
  47638. /***/ },
  47639. /* 320 */
  47640. /***/ function(module, exports, __webpack_require__) {
  47641. /**
  47642. * Legend component entry file8
  47643. */
  47644. __webpack_require__(321);
  47645. __webpack_require__(322);
  47646. __webpack_require__(323);
  47647. var echarts = __webpack_require__(1);
  47648. // Series Filter
  47649. echarts.registerProcessor(__webpack_require__(325));
  47650. /***/ },
  47651. /* 321 */
  47652. /***/ function(module, exports, __webpack_require__) {
  47653. 'use strict';
  47654. var zrUtil = __webpack_require__(4);
  47655. var Model = __webpack_require__(12);
  47656. var LegendModel = __webpack_require__(1).extendComponentModel({
  47657. type: 'legend',
  47658. dependencies: ['series'],
  47659. layoutMode: {
  47660. type: 'box',
  47661. ignoreSize: true
  47662. },
  47663. init: function (option, parentModel, ecModel) {
  47664. this.mergeDefaultAndTheme(option, ecModel);
  47665. option.selected = option.selected || {};
  47666. },
  47667. mergeOption: function (option) {
  47668. LegendModel.superCall(this, 'mergeOption', option);
  47669. },
  47670. optionUpdated: function () {
  47671. this._updateData(this.ecModel);
  47672. var legendData = this._data;
  47673. // If selectedMode is single, try to select one
  47674. if (legendData[0] && this.get('selectedMode') === 'single') {
  47675. var hasSelected = false;
  47676. // If has any selected in option.selected
  47677. for (var i = 0; i < legendData.length; i++) {
  47678. var name = legendData[i].get('name');
  47679. if (this.isSelected(name)) {
  47680. // Force to unselect others
  47681. this.select(name);
  47682. hasSelected = true;
  47683. break;
  47684. }
  47685. }
  47686. // Try select the first if selectedMode is single
  47687. !hasSelected && this.select(legendData[0].get('name'));
  47688. }
  47689. },
  47690. _updateData: function (ecModel) {
  47691. var legendData = zrUtil.map(this.get('data') || [], function (dataItem) {
  47692. // Can be string or number
  47693. if (typeof dataItem === 'string' || typeof dataItem === 'number') {
  47694. dataItem = {
  47695. name: dataItem
  47696. };
  47697. }
  47698. return new Model(dataItem, this, this.ecModel);
  47699. }, this);
  47700. this._data = legendData;
  47701. var availableNames = zrUtil.map(ecModel.getSeries(), function (series) {
  47702. return series.name;
  47703. });
  47704. ecModel.eachSeries(function (seriesModel) {
  47705. if (seriesModel.legendDataProvider) {
  47706. var data = seriesModel.legendDataProvider();
  47707. availableNames = availableNames.concat(data.mapArray(data.getName));
  47708. }
  47709. });
  47710. /**
  47711. * @type {Array.<string>}
  47712. * @private
  47713. */
  47714. this._availableNames = availableNames;
  47715. },
  47716. /**
  47717. * @return {Array.<module:echarts/model/Model>}
  47718. */
  47719. getData: function () {
  47720. return this._data;
  47721. },
  47722. /**
  47723. * @param {string} name
  47724. */
  47725. select: function (name) {
  47726. var selected = this.option.selected;
  47727. var selectedMode = this.get('selectedMode');
  47728. if (selectedMode === 'single') {
  47729. var data = this._data;
  47730. zrUtil.each(data, function (dataItem) {
  47731. selected[dataItem.get('name')] = false;
  47732. });
  47733. }
  47734. selected[name] = true;
  47735. },
  47736. /**
  47737. * @param {string} name
  47738. */
  47739. unSelect: function (name) {
  47740. if (this.get('selectedMode') !== 'single') {
  47741. this.option.selected[name] = false;
  47742. }
  47743. },
  47744. /**
  47745. * @param {string} name
  47746. */
  47747. toggleSelected: function (name) {
  47748. var selected = this.option.selected;
  47749. // Default is true
  47750. if (!selected.hasOwnProperty(name)) {
  47751. selected[name] = true;
  47752. }
  47753. this[selected[name] ? 'unSelect' : 'select'](name);
  47754. },
  47755. /**
  47756. * @param {string} name
  47757. */
  47758. isSelected: function (name) {
  47759. var selected = this.option.selected;
  47760. return !(selected.hasOwnProperty(name) && !selected[name])
  47761. && zrUtil.indexOf(this._availableNames, name) >= 0;
  47762. },
  47763. defaultOption: {
  47764. // 一级层叠
  47765. zlevel: 0,
  47766. // 二级层叠
  47767. z: 4,
  47768. show: true,
  47769. // 布局方式,默认为水平布局,可选为:
  47770. // 'horizontal' | 'vertical'
  47771. orient: 'horizontal',
  47772. left: 'center',
  47773. // right: 'center',
  47774. top: 'top',
  47775. // bottom: 'top',
  47776. // 水平对齐
  47777. // 'auto' | 'left' | 'right'
  47778. // 默认为 'auto', 根据 x 的位置判断是左对齐还是右对齐
  47779. align: 'auto',
  47780. backgroundColor: 'rgba(0,0,0,0)',
  47781. // 图例边框颜色
  47782. borderColor: '#ccc',
  47783. // 图例边框线宽,单位px,默认为0(无边框)
  47784. borderWidth: 0,
  47785. // 图例内边距,单位px,默认各方向内边距为5,
  47786. // 接受数组分别设定上右下左边距,同css
  47787. padding: 5,
  47788. // 各个item之间的间隔,单位px,默认为10,
  47789. // 横向布局时为水平间隔,纵向布局时为纵向间隔
  47790. itemGap: 10,
  47791. // 图例图形宽度
  47792. itemWidth: 25,
  47793. // 图例图形高度
  47794. itemHeight: 14,
  47795. // 图例关闭时候的颜色
  47796. inactiveColor: '#ccc',
  47797. textStyle: {
  47798. // 图例文字颜色
  47799. color: '#333'
  47800. },
  47801. // formatter: '',
  47802. // 选择模式,默认开启图例开关
  47803. selectedMode: true,
  47804. // 配置默认选中状态,可配合LEGEND.SELECTED事件做动态数据载入
  47805. // selected: null,
  47806. // 图例内容(详见legend.data,数组中每一项代表一个item
  47807. // data: [],
  47808. // Tooltip 相关配置
  47809. tooltip: {
  47810. show: false
  47811. }
  47812. }
  47813. });
  47814. module.exports = LegendModel;
  47815. /***/ },
  47816. /* 322 */
  47817. /***/ function(module, exports, __webpack_require__) {
  47818. /**
  47819. * @file Legend action
  47820. */
  47821. var echarts = __webpack_require__(1);
  47822. var zrUtil = __webpack_require__(4);
  47823. function legendSelectActionHandler(methodName, payload, ecModel) {
  47824. var selectedMap = {};
  47825. var isToggleSelect = methodName === 'toggleSelected';
  47826. var isSelected;
  47827. // Update all legend components
  47828. ecModel.eachComponent('legend', function (legendModel) {
  47829. if (isToggleSelect && isSelected != null) {
  47830. // Force other legend has same selected status
  47831. // Or the first is toggled to true and other are toggled to false
  47832. // In the case one legend has some item unSelected in option. And if other legend
  47833. // doesn't has the item, they will assume it is selected.
  47834. legendModel[isSelected ? 'select' : 'unSelect'](payload.name);
  47835. }
  47836. else {
  47837. legendModel[methodName](payload.name);
  47838. isSelected = legendModel.isSelected(payload.name);
  47839. }
  47840. var legendData = legendModel.getData();
  47841. zrUtil.each(legendData, function (model) {
  47842. var name = model.get('name');
  47843. // Wrap element
  47844. if (name === '\n' || name === '') {
  47845. return;
  47846. }
  47847. var isItemSelected = legendModel.isSelected(name);
  47848. if (selectedMap.hasOwnProperty(name)) {
  47849. // Unselected if any legend is unselected
  47850. selectedMap[name] = selectedMap[name] && isItemSelected;
  47851. }
  47852. else {
  47853. selectedMap[name] = isItemSelected;
  47854. }
  47855. });
  47856. });
  47857. // Return the event explicitly
  47858. return {
  47859. name: payload.name,
  47860. selected: selectedMap
  47861. };
  47862. }
  47863. /**
  47864. * @event legendToggleSelect
  47865. * @type {Object}
  47866. * @property {string} type 'legendToggleSelect'
  47867. * @property {string} [from]
  47868. * @property {string} name Series name or data item name
  47869. */
  47870. echarts.registerAction(
  47871. 'legendToggleSelect', 'legendselectchanged',
  47872. zrUtil.curry(legendSelectActionHandler, 'toggleSelected')
  47873. );
  47874. /**
  47875. * @event legendSelect
  47876. * @type {Object}
  47877. * @property {string} type 'legendSelect'
  47878. * @property {string} name Series name or data item name
  47879. */
  47880. echarts.registerAction(
  47881. 'legendSelect', 'legendselected',
  47882. zrUtil.curry(legendSelectActionHandler, 'select')
  47883. );
  47884. /**
  47885. * @event legendUnSelect
  47886. * @type {Object}
  47887. * @property {string} type 'legendUnSelect'
  47888. * @property {string} name Series name or data item name
  47889. */
  47890. echarts.registerAction(
  47891. 'legendUnSelect', 'legendunselected',
  47892. zrUtil.curry(legendSelectActionHandler, 'unSelect')
  47893. );
  47894. /***/ },
  47895. /* 323 */
  47896. /***/ function(module, exports, __webpack_require__) {
  47897. var zrUtil = __webpack_require__(4);
  47898. var symbolCreator = __webpack_require__(111);
  47899. var graphic = __webpack_require__(18);
  47900. var listComponentHelper = __webpack_require__(324);
  47901. var curry = zrUtil.curry;
  47902. function dispatchSelectAction(name, api) {
  47903. api.dispatchAction({
  47904. type: 'legendToggleSelect',
  47905. name: name
  47906. });
  47907. }
  47908. function dispatchHighlightAction(seriesModel, dataName, api) {
  47909. // If element hover will move to a hoverLayer.
  47910. var el = api.getZr().storage.getDisplayList()[0];
  47911. if (!(el && el.useHoverLayer)) {
  47912. seriesModel.get('legendHoverLink') && api.dispatchAction({
  47913. type: 'highlight',
  47914. seriesName: seriesModel.name,
  47915. name: dataName
  47916. });
  47917. }
  47918. }
  47919. function dispatchDownplayAction(seriesModel, dataName, api) {
  47920. // If element hover will move to a hoverLayer.
  47921. var el = api.getZr().storage.getDisplayList()[0];
  47922. if (!(el && el.useHoverLayer)) {
  47923. seriesModel.get('legendHoverLink') && api.dispatchAction({
  47924. type: 'downplay',
  47925. seriesName: seriesModel.name,
  47926. name: dataName
  47927. });
  47928. }
  47929. }
  47930. module.exports = __webpack_require__(1).extendComponentView({
  47931. type: 'legend',
  47932. init: function () {
  47933. this._symbolTypeStore = {};
  47934. },
  47935. render: function (legendModel, ecModel, api) {
  47936. var group = this.group;
  47937. group.removeAll();
  47938. if (!legendModel.get('show')) {
  47939. return;
  47940. }
  47941. var selectMode = legendModel.get('selectedMode');
  47942. var itemAlign = legendModel.get('align');
  47943. if (itemAlign === 'auto') {
  47944. itemAlign = (legendModel.get('left') === 'right'
  47945. && legendModel.get('orient') === 'vertical')
  47946. ? 'right' : 'left';
  47947. }
  47948. var legendDrawedMap = zrUtil.createHashMap();
  47949. zrUtil.each(legendModel.getData(), function (itemModel) {
  47950. var name = itemModel.get('name');
  47951. // Use empty string or \n as a newline string
  47952. if (name === '' || name === '\n') {
  47953. group.add(new graphic.Group({
  47954. newline: true
  47955. }));
  47956. return;
  47957. }
  47958. var seriesModel = ecModel.getSeriesByName(name)[0];
  47959. if (legendDrawedMap.get(name)) {
  47960. // Have been drawed
  47961. return;
  47962. }
  47963. // Series legend
  47964. if (seriesModel) {
  47965. var data = seriesModel.getData();
  47966. var color = data.getVisual('color');
  47967. // If color is a callback function
  47968. if (typeof color === 'function') {
  47969. // Use the first data
  47970. color = color(seriesModel.getDataParams(0));
  47971. }
  47972. // Using rect symbol defaultly
  47973. var legendSymbolType = data.getVisual('legendSymbol') || 'roundRect';
  47974. var symbolType = data.getVisual('symbol');
  47975. var itemGroup = this._createItem(
  47976. name, itemModel, legendModel,
  47977. legendSymbolType, symbolType,
  47978. itemAlign, color,
  47979. selectMode
  47980. );
  47981. itemGroup.on('click', curry(dispatchSelectAction, name, api))
  47982. .on('mouseover', curry(dispatchHighlightAction, seriesModel, null, api))
  47983. .on('mouseout', curry(dispatchDownplayAction, seriesModel, null, api));
  47984. legendDrawedMap.set(name, true);
  47985. }
  47986. else {
  47987. // Data legend of pie, funnel
  47988. ecModel.eachRawSeries(function (seriesModel) {
  47989. // In case multiple series has same data name
  47990. if (legendDrawedMap.get(name)) {
  47991. return;
  47992. }
  47993. if (seriesModel.legendDataProvider) {
  47994. var data = seriesModel.legendDataProvider();
  47995. var idx = data.indexOfName(name);
  47996. if (idx < 0) {
  47997. return;
  47998. }
  47999. var color = data.getItemVisual(idx, 'color');
  48000. var legendSymbolType = 'roundRect';
  48001. var itemGroup = this._createItem(
  48002. name, itemModel, legendModel,
  48003. legendSymbolType, null,
  48004. itemAlign, color,
  48005. selectMode
  48006. );
  48007. itemGroup.on('click', curry(dispatchSelectAction, name, api))
  48008. // FIXME Should not specify the series name
  48009. .on('mouseover', curry(dispatchHighlightAction, seriesModel, name, api))
  48010. .on('mouseout', curry(dispatchDownplayAction, seriesModel, name, api));
  48011. legendDrawedMap.set(name, true);
  48012. }
  48013. }, this);
  48014. }
  48015. if (true) {
  48016. if (!legendDrawedMap.get(name)) {
  48017. console.warn(name + ' series not exists. Legend data should be same with series name or data name.');
  48018. }
  48019. }
  48020. }, this);
  48021. listComponentHelper.layout(group, legendModel, api);
  48022. // Render background after group is layout
  48023. // FIXME
  48024. listComponentHelper.addBackground(group, legendModel);
  48025. },
  48026. _createItem: function (
  48027. name, itemModel, legendModel,
  48028. legendSymbolType, symbolType,
  48029. itemAlign, color, selectMode
  48030. ) {
  48031. var itemWidth = legendModel.get('itemWidth');
  48032. var itemHeight = legendModel.get('itemHeight');
  48033. var inactiveColor = legendModel.get('inactiveColor');
  48034. var isSelected = legendModel.isSelected(name);
  48035. var itemGroup = new graphic.Group();
  48036. var textStyleModel = itemModel.getModel('textStyle');
  48037. var itemIcon = itemModel.get('icon');
  48038. var tooltipModel = itemModel.getModel('tooltip');
  48039. var legendGlobalTooltipModel = tooltipModel.parentModel;
  48040. // Use user given icon first
  48041. legendSymbolType = itemIcon || legendSymbolType;
  48042. itemGroup.add(symbolCreator.createSymbol(
  48043. legendSymbolType, 0, 0, itemWidth, itemHeight, isSelected ? color : inactiveColor
  48044. ));
  48045. // Compose symbols
  48046. // PENDING
  48047. if (!itemIcon && symbolType
  48048. // At least show one symbol, can't be all none
  48049. && ((symbolType !== legendSymbolType) || symbolType == 'none')
  48050. ) {
  48051. var size = itemHeight * 0.8;
  48052. if (symbolType === 'none') {
  48053. symbolType = 'circle';
  48054. }
  48055. // Put symbol in the center
  48056. itemGroup.add(symbolCreator.createSymbol(
  48057. symbolType, (itemWidth - size) / 2, (itemHeight - size) / 2, size, size,
  48058. isSelected ? color : inactiveColor
  48059. ));
  48060. }
  48061. // Text
  48062. var textX = itemAlign === 'left' ? itemWidth + 5 : -5;
  48063. var textAlign = itemAlign;
  48064. var formatter = legendModel.get('formatter');
  48065. var content = name;
  48066. if (typeof formatter === 'string' && formatter) {
  48067. content = formatter.replace('{name}', name != null ? name : '');
  48068. }
  48069. else if (typeof formatter === 'function') {
  48070. content = formatter(name);
  48071. }
  48072. var text = new graphic.Text({
  48073. style: {
  48074. text: content,
  48075. x: textX,
  48076. y: itemHeight / 2,
  48077. fill: isSelected ? textStyleModel.getTextColor() : inactiveColor,
  48078. textFont: textStyleModel.getFont(),
  48079. textAlign: textAlign,
  48080. textVerticalAlign: 'middle'
  48081. }
  48082. });
  48083. itemGroup.add(text);
  48084. // Add a invisible rect to increase the area of mouse hover
  48085. var hitRect = new graphic.Rect({
  48086. shape: itemGroup.getBoundingRect(),
  48087. invisible: true,
  48088. tooltip: tooltipModel.get('show') ? zrUtil.extend({
  48089. content: name,
  48090. // Defaul formatter
  48091. formatter: legendGlobalTooltipModel.get('formatter', true) || function () {
  48092. return name;
  48093. },
  48094. formatterParams: {
  48095. componentType: 'legend',
  48096. legendIndex: legendModel.componentIndex,
  48097. name: name,
  48098. $vars: ['name']
  48099. }
  48100. }, tooltipModel.option) : null
  48101. });
  48102. itemGroup.add(hitRect);
  48103. itemGroup.eachChild(function (child) {
  48104. child.silent = true;
  48105. });
  48106. hitRect.silent = !selectMode;
  48107. this.group.add(itemGroup);
  48108. graphic.setHoverStyle(itemGroup);
  48109. return itemGroup;
  48110. }
  48111. });
  48112. /***/ },
  48113. /* 324 */
  48114. /***/ function(module, exports, __webpack_require__) {
  48115. // List layout
  48116. var layout = __webpack_require__(71);
  48117. var formatUtil = __webpack_require__(6);
  48118. var graphic = __webpack_require__(18);
  48119. function positionGroup(group, model, api) {
  48120. layout.positionElement(
  48121. group, model.getBoxLayoutParams(),
  48122. {
  48123. width: api.getWidth(),
  48124. height: api.getHeight()
  48125. },
  48126. model.get('padding')
  48127. );
  48128. }
  48129. module.exports = {
  48130. /**
  48131. * Layout list like component.
  48132. * It will box layout each items in group of component and then position the whole group in the viewport
  48133. * @param {module:zrender/group/Group} group
  48134. * @param {module:echarts/model/Component} componentModel
  48135. * @param {module:echarts/ExtensionAPI}
  48136. */
  48137. layout: function (group, componentModel, api) {
  48138. var rect = layout.getLayoutRect(componentModel.getBoxLayoutParams(), {
  48139. width: api.getWidth(),
  48140. height: api.getHeight()
  48141. }, componentModel.get('padding'));
  48142. layout.box(
  48143. componentModel.get('orient'),
  48144. group,
  48145. componentModel.get('itemGap'),
  48146. rect.width,
  48147. rect.height
  48148. );
  48149. positionGroup(group, componentModel, api);
  48150. },
  48151. addBackground: function (group, componentModel) {
  48152. var padding = formatUtil.normalizeCssArray(
  48153. componentModel.get('padding')
  48154. );
  48155. var boundingRect = group.getBoundingRect();
  48156. var style = componentModel.getItemStyle(['color', 'opacity']);
  48157. style.fill = componentModel.get('backgroundColor');
  48158. var rect = new graphic.Rect({
  48159. shape: {
  48160. x: boundingRect.x - padding[3],
  48161. y: boundingRect.y - padding[0],
  48162. width: boundingRect.width + padding[1] + padding[3],
  48163. height: boundingRect.height + padding[0] + padding[2]
  48164. },
  48165. style: style,
  48166. silent: true,
  48167. z2: -1
  48168. });
  48169. graphic.subPixelOptimizeRect(rect);
  48170. group.add(rect);
  48171. }
  48172. };
  48173. /***/ },
  48174. /* 325 */
  48175. /***/ function(module, exports) {
  48176. module.exports = function (ecModel) {
  48177. var legendModels = ecModel.findComponents({
  48178. mainType: 'legend'
  48179. });
  48180. if (legendModels && legendModels.length) {
  48181. ecModel.filterSeries(function (series) {
  48182. // If in any legend component the status is not selected.
  48183. // Because in legend series is assumed selected when it is not in the legend data.
  48184. for (var i = 0; i < legendModels.length; i++) {
  48185. if (!legendModels[i].isSelected(series.name)) {
  48186. return false;
  48187. }
  48188. }
  48189. return true;
  48190. });
  48191. }
  48192. };
  48193. /***/ },
  48194. /* 326 */
  48195. /***/ function(module, exports, __webpack_require__) {
  48196. // FIXME Better way to pack data in graphic element
  48197. __webpack_require__(297);
  48198. __webpack_require__(327);
  48199. __webpack_require__(328);
  48200. // Show tip action
  48201. /**
  48202. * @action
  48203. * @property {string} type
  48204. * @property {number} seriesIndex
  48205. * @property {number} dataIndex
  48206. * @property {number} [x]
  48207. * @property {number} [y]
  48208. */
  48209. __webpack_require__(1).registerAction(
  48210. {
  48211. type: 'showTip',
  48212. event: 'showTip',
  48213. update: 'tooltip:manuallyShowTip'
  48214. },
  48215. // noop
  48216. function () {}
  48217. );
  48218. // Hide tip action
  48219. __webpack_require__(1).registerAction(
  48220. {
  48221. type: 'hideTip',
  48222. event: 'hideTip',
  48223. update: 'tooltip:manuallyHideTip'
  48224. },
  48225. // noop
  48226. function () {}
  48227. );
  48228. /***/ },
  48229. /* 327 */
  48230. /***/ function(module, exports, __webpack_require__) {
  48231. __webpack_require__(1).extendComponentModel({
  48232. type: 'tooltip',
  48233. dependencies: ['axisPointer'],
  48234. defaultOption: {
  48235. zlevel: 0,
  48236. z: 8,
  48237. show: true,
  48238. // tooltip主体内容
  48239. showContent: true,
  48240. // 'trigger' only works on coordinate system.
  48241. // 'item' | 'axis' | 'none'
  48242. trigger: 'item',
  48243. // 'click' | 'mousemove' | 'none'
  48244. triggerOn: 'mousemove|click',
  48245. alwaysShowContent: false,
  48246. displayMode: 'single', // 'single' | 'multipleByCoordSys'
  48247. // 位置 {Array} | {Function}
  48248. // position: null
  48249. // Consider triggered from axisPointer handle, verticalAlign should be 'middle'
  48250. // align: null,
  48251. // verticalAlign: null,
  48252. // 是否约束 content 在 viewRect 中。默认 false 是为了兼容以前版本。
  48253. confine: false,
  48254. // 内容格式器:{string}(Template) ¦ {Function}
  48255. // formatter: null
  48256. showDelay: 0,
  48257. // 隐藏延迟,单位ms
  48258. hideDelay: 100,
  48259. // 动画变换时间,单位s
  48260. transitionDuration: 0.4,
  48261. enterable: false,
  48262. // 提示背景颜色,默认为透明度为0.7的黑色
  48263. backgroundColor: 'rgba(50,50,50,0.7)',
  48264. // 提示边框颜色
  48265. borderColor: '#333',
  48266. // 提示边框圆角,单位px,默认为4
  48267. borderRadius: 4,
  48268. // 提示边框线宽,单位px,默认为0(无边框)
  48269. borderWidth: 0,
  48270. // 提示内边距,单位px,默认各方向内边距为5,
  48271. // 接受数组分别设定上右下左边距,同css
  48272. padding: 5,
  48273. // Extra css text
  48274. extraCssText: '',
  48275. // 坐标轴指示器,坐标轴触发有效
  48276. axisPointer: {
  48277. // 默认为直线
  48278. // 可选为:'line' | 'shadow' | 'cross'
  48279. type: 'line',
  48280. // type 为 line 的时候有效,指定 tooltip line 所在的轴,可选
  48281. // 可选 'x' | 'y' | 'angle' | 'radius' | 'auto'
  48282. // 默认 'auto',会选择类型为 cateogry 的轴,对于双数值轴,笛卡尔坐标系会默认选择 x 轴
  48283. // 极坐标系会默认选择 angle 轴
  48284. axis: 'auto',
  48285. animation: 'auto',
  48286. animationDurationUpdate: 200,
  48287. animationEasingUpdate: 'exponentialOut',
  48288. crossStyle: {
  48289. color: '#999',
  48290. width: 1,
  48291. type: 'dashed',
  48292. // TODO formatter
  48293. textStyle: {}
  48294. }
  48295. // lineStyle and shadowStyle should not be specified here,
  48296. // otherwise it will always override those styles on option.axisPointer.
  48297. },
  48298. textStyle: {
  48299. color: '#fff',
  48300. fontSize: 14
  48301. }
  48302. }
  48303. });
  48304. /***/ },
  48305. /* 328 */
  48306. /***/ function(module, exports, __webpack_require__) {
  48307. var TooltipContent = __webpack_require__(329);
  48308. var zrUtil = __webpack_require__(4);
  48309. var formatUtil = __webpack_require__(6);
  48310. var numberUtil = __webpack_require__(7);
  48311. var graphic = __webpack_require__(18);
  48312. var findPointFromSeries = __webpack_require__(299);
  48313. var layoutUtil = __webpack_require__(71);
  48314. var env = __webpack_require__(2);
  48315. var Model = __webpack_require__(12);
  48316. var globalListener = __webpack_require__(302);
  48317. var axisHelper = __webpack_require__(101);
  48318. var axisPointerViewHelper = __webpack_require__(305);
  48319. var bind = zrUtil.bind;
  48320. var each = zrUtil.each;
  48321. var parsePercent = numberUtil.parsePercent;
  48322. var proxyRect = new graphic.Rect({
  48323. shape: {x: -1, y: -1, width: 2, height: 2}
  48324. });
  48325. __webpack_require__(1).extendComponentView({
  48326. type: 'tooltip',
  48327. init: function (ecModel, api) {
  48328. if (env.node) {
  48329. return;
  48330. }
  48331. var tooltipContent = new TooltipContent(api.getDom(), api);
  48332. this._tooltipContent = tooltipContent;
  48333. },
  48334. render: function (tooltipModel, ecModel, api) {
  48335. if (env.node) {
  48336. return;
  48337. }
  48338. // Reset
  48339. this.group.removeAll();
  48340. /**
  48341. * @private
  48342. * @type {module:echarts/component/tooltip/TooltipModel}
  48343. */
  48344. this._tooltipModel = tooltipModel;
  48345. /**
  48346. * @private
  48347. * @type {module:echarts/model/Global}
  48348. */
  48349. this._ecModel = ecModel;
  48350. /**
  48351. * @private
  48352. * @type {module:echarts/ExtensionAPI}
  48353. */
  48354. this._api = api;
  48355. /**
  48356. * Should be cleaned when render.
  48357. * @private
  48358. * @type {Array.<Array.<Object>>}
  48359. */
  48360. this._lastDataByCoordSys = null;
  48361. /**
  48362. * @private
  48363. * @type {boolean}
  48364. */
  48365. this._alwaysShowContent = tooltipModel.get('alwaysShowContent');
  48366. var tooltipContent = this._tooltipContent;
  48367. tooltipContent.update();
  48368. tooltipContent.setEnterable(tooltipModel.get('enterable'));
  48369. this._initGlobalListener();
  48370. this._keepShow();
  48371. },
  48372. _initGlobalListener: function () {
  48373. var tooltipModel = this._tooltipModel;
  48374. var triggerOn = tooltipModel.get('triggerOn');
  48375. globalListener.register(
  48376. 'itemTooltip',
  48377. this._api,
  48378. bind(function (currTrigger, e, dispatchAction) {
  48379. // If 'none', it is not controlled by mouse totally.
  48380. if (triggerOn !== 'none') {
  48381. if (triggerOn.indexOf(currTrigger) >= 0) {
  48382. this._tryShow(e, dispatchAction);
  48383. }
  48384. else if (currTrigger === 'leave') {
  48385. this._hide(dispatchAction);
  48386. }
  48387. }
  48388. }, this)
  48389. );
  48390. },
  48391. _keepShow: function () {
  48392. var tooltipModel = this._tooltipModel;
  48393. var ecModel = this._ecModel;
  48394. var api = this._api;
  48395. // Try to keep the tooltip show when refreshing
  48396. if (this._lastX != null
  48397. && this._lastY != null
  48398. // When user is willing to control tooltip totally using API,
  48399. // self.manuallyShowTip({x, y}) might cause tooltip hide,
  48400. // which is not expected.
  48401. && tooltipModel.get('triggerOn') !== 'none'
  48402. ) {
  48403. var self = this;
  48404. clearTimeout(this._refreshUpdateTimeout);
  48405. this._refreshUpdateTimeout = setTimeout(function () {
  48406. // Show tip next tick after other charts are rendered
  48407. // In case highlight action has wrong result
  48408. // FIXME
  48409. self.manuallyShowTip(tooltipModel, ecModel, api, {
  48410. x: self._lastX,
  48411. y: self._lastY
  48412. });
  48413. });
  48414. }
  48415. },
  48416. /**
  48417. * Show tip manually by
  48418. * dispatchAction({
  48419. * type: 'showTip',
  48420. * x: 10,
  48421. * y: 10
  48422. * });
  48423. * Or
  48424. * dispatchAction({
  48425. * type: 'showTip',
  48426. * seriesIndex: 0,
  48427. * dataIndex or dataIndexInside or name
  48428. * });
  48429. *
  48430. * TODO Batch
  48431. */
  48432. manuallyShowTip: function (tooltipModel, ecModel, api, payload) {
  48433. if (payload.from === this.uid || env.node) {
  48434. return;
  48435. }
  48436. var dispatchAction = makeDispatchAction(payload, api);
  48437. // Reset ticket
  48438. this._ticket = '';
  48439. // When triggered from axisPointer.
  48440. var dataByCoordSys = payload.dataByCoordSys;
  48441. if (payload.tooltip && payload.x != null && payload.y != null) {
  48442. var el = proxyRect;
  48443. el.position = [payload.x, payload.y];
  48444. el.update();
  48445. el.tooltip = payload.tooltip;
  48446. // Manually show tooltip while view is not using zrender elements.
  48447. this._tryShow({
  48448. offsetX: payload.x,
  48449. offsetY: payload.y,
  48450. target: el
  48451. }, dispatchAction);
  48452. }
  48453. else if (dataByCoordSys) {
  48454. this._tryShow({
  48455. offsetX: payload.x,
  48456. offsetY: payload.y,
  48457. position: payload.position,
  48458. event: {},
  48459. dataByCoordSys: payload.dataByCoordSys,
  48460. tooltipOption: payload.tooltipOption
  48461. }, dispatchAction);
  48462. }
  48463. else if (payload.seriesIndex != null) {
  48464. if (this._manuallyAxisShowTip(tooltipModel, ecModel, api, payload)) {
  48465. return;
  48466. }
  48467. var pointInfo = findPointFromSeries(payload, ecModel);
  48468. var cx = pointInfo.point[0];
  48469. var cy = pointInfo.point[1];
  48470. if (cx != null && cy != null) {
  48471. this._tryShow({
  48472. offsetX: cx,
  48473. offsetY: cy,
  48474. position: payload.position,
  48475. target: pointInfo.el,
  48476. event: {}
  48477. }, dispatchAction);
  48478. }
  48479. }
  48480. else if (payload.x != null && payload.y != null) {
  48481. // FIXME
  48482. // should wrap dispatchAction like `axisPointer/globalListener` ?
  48483. api.dispatchAction({
  48484. type: 'updateAxisPointer',
  48485. x: payload.x,
  48486. y: payload.y
  48487. });
  48488. this._tryShow({
  48489. offsetX: payload.x,
  48490. offsetY: payload.y,
  48491. position: payload.position,
  48492. target: api.getZr().findHover(payload.x, payload.y).target,
  48493. event: {}
  48494. }, dispatchAction);
  48495. }
  48496. },
  48497. manuallyHideTip: function (tooltipModel, ecModel, api, payload) {
  48498. var tooltipContent = this._tooltipContent;
  48499. if (!this._alwaysShowContent) {
  48500. tooltipContent.hideLater(this._tooltipModel.get('hideDelay'));
  48501. }
  48502. this._lastX = this._lastY = null;
  48503. if (payload.from !== this.uid) {
  48504. this._hide(makeDispatchAction(payload, api));
  48505. }
  48506. },
  48507. // Be compatible with previous design, that is, when tooltip.type is 'axis' and
  48508. // dispatchAction 'showTip' with seriesIndex and dataIndex will trigger axis pointer
  48509. // and tooltip.
  48510. _manuallyAxisShowTip: function (tooltipModel, ecModel, api, payload) {
  48511. var seriesIndex = payload.seriesIndex;
  48512. var dataIndex = payload.dataIndex;
  48513. var coordSysAxesInfo = ecModel.getComponent('axisPointer').coordSysAxesInfo;
  48514. if (seriesIndex == null || dataIndex == null || coordSysAxesInfo == null) {
  48515. return;
  48516. }
  48517. var seriesModel = ecModel.getSeriesByIndex(seriesIndex);
  48518. if (!seriesModel) {
  48519. return;
  48520. }
  48521. var data = seriesModel.getData();
  48522. var tooltipModel = buildTooltipModel([
  48523. data.getItemModel(dataIndex),
  48524. seriesModel,
  48525. (seriesModel.coordinateSystem || {}).model,
  48526. tooltipModel
  48527. ]);
  48528. if (tooltipModel.get('trigger') !== 'axis') {
  48529. return;
  48530. }
  48531. api.dispatchAction({
  48532. type: 'updateAxisPointer',
  48533. seriesIndex: seriesIndex,
  48534. dataIndex: dataIndex
  48535. });
  48536. return true;
  48537. },
  48538. _tryShow: function (e, dispatchAction) {
  48539. var el = e.target;
  48540. var tooltipModel = this._tooltipModel;
  48541. if (!tooltipModel) {
  48542. return;
  48543. }
  48544. // Save mouse x, mouse y. So we can try to keep showing the tip if chart is refreshed
  48545. this._lastX = e.offsetX;
  48546. this._lastY = e.offsetY;
  48547. var dataByCoordSys = e.dataByCoordSys;
  48548. if (dataByCoordSys && dataByCoordSys.length) {
  48549. this._showAxisTooltip(dataByCoordSys, e);
  48550. }
  48551. // Always show item tooltip if mouse is on the element with dataIndex
  48552. else if (el && el.dataIndex != null) {
  48553. this._lastDataByCoordSys = null;
  48554. this._showSeriesItemTooltip(e, el, dispatchAction);
  48555. }
  48556. // Tooltip provided directly. Like legend.
  48557. else if (el && el.tooltip) {
  48558. this._lastDataByCoordSys = null;
  48559. this._showComponentItemTooltip(e, el, dispatchAction);
  48560. }
  48561. else {
  48562. this._lastDataByCoordSys = null;
  48563. this._hide(dispatchAction);
  48564. }
  48565. },
  48566. _showOrMove: function (tooltipModel, cb) {
  48567. // showDelay is used in this case: tooltip.enterable is set
  48568. // as true. User intent to move mouse into tooltip and click
  48569. // something. `showDelay` makes it easyer to enter the content
  48570. // but tooltip do not move immediately.
  48571. var delay = tooltipModel.get('showDelay');
  48572. cb = zrUtil.bind(cb, this);
  48573. clearTimeout(this._showTimout);
  48574. delay > 0
  48575. ? (this._showTimout = setTimeout(cb, delay))
  48576. : cb();
  48577. },
  48578. _showAxisTooltip: function (dataByCoordSys, e) {
  48579. var ecModel = this._ecModel;
  48580. var globalTooltipModel = this._tooltipModel;
  48581. var point = [e.offsetX, e.offsetY];
  48582. var singleDefaultHTML = [];
  48583. var singleParamsList = [];
  48584. var singleTooltipModel = buildTooltipModel([
  48585. e.tooltipOption,
  48586. globalTooltipModel
  48587. ]);
  48588. each(dataByCoordSys, function (itemCoordSys) {
  48589. // var coordParamList = [];
  48590. // var coordDefaultHTML = [];
  48591. // var coordTooltipModel = buildTooltipModel([
  48592. // e.tooltipOption,
  48593. // itemCoordSys.tooltipOption,
  48594. // ecModel.getComponent(itemCoordSys.coordSysMainType, itemCoordSys.coordSysIndex),
  48595. // globalTooltipModel
  48596. // ]);
  48597. // var displayMode = coordTooltipModel.get('displayMode');
  48598. // var paramsList = displayMode === 'single' ? singleParamsList : [];
  48599. each(itemCoordSys.dataByAxis, function (item) {
  48600. var axisModel = ecModel.getComponent(item.axisDim + 'Axis', item.axisIndex);
  48601. var axisValue = item.value;
  48602. var seriesDefaultHTML = [];
  48603. if (!axisModel || axisValue == null) {
  48604. return;
  48605. }
  48606. var valueLabel = axisPointerViewHelper.getValueLabel(
  48607. axisValue, axisModel.axis, ecModel,
  48608. item.seriesDataIndices,
  48609. item.valueLabelOpt
  48610. );
  48611. zrUtil.each(item.seriesDataIndices, function (idxItem) {
  48612. var series = ecModel.getSeriesByIndex(idxItem.seriesIndex);
  48613. var dataIndex = idxItem.dataIndexInside;
  48614. var dataParams = series && series.getDataParams(dataIndex);
  48615. dataParams.axisDim = item.axisDim;
  48616. dataParams.axisIndex = item.axisIndex;
  48617. dataParams.axisType = item.axisType;
  48618. dataParams.axisId = item.axisId;
  48619. dataParams.axisValue = axisHelper.getAxisRawValue(axisModel.axis, axisValue);
  48620. dataParams.axisValueLabel = valueLabel;
  48621. if (dataParams) {
  48622. singleParamsList.push(dataParams);
  48623. seriesDefaultHTML.push(series.formatTooltip(dataIndex, true));
  48624. }
  48625. });
  48626. // Default tooltip content
  48627. // FIXME
  48628. // (1) shold be the first data which has name?
  48629. // (2) themeRiver, firstDataIndex is array, and first line is unnecessary.
  48630. var firstLine = valueLabel;
  48631. singleDefaultHTML.push(
  48632. (firstLine ? formatUtil.encodeHTML(firstLine) + '<br />' : '')
  48633. + seriesDefaultHTML.join('<br />')
  48634. );
  48635. });
  48636. }, this);
  48637. // In most case, the second axis is shown upper than the first one.
  48638. singleDefaultHTML.reverse();
  48639. singleDefaultHTML = singleDefaultHTML.join('<br /><br />');
  48640. var positionExpr = e.position;
  48641. this._showOrMove(singleTooltipModel, function () {
  48642. if (this._updateContentNotChangedOnAxis(dataByCoordSys)) {
  48643. this._updatePosition(
  48644. singleTooltipModel,
  48645. positionExpr,
  48646. point[0], point[1],
  48647. this._tooltipContent,
  48648. singleParamsList
  48649. );
  48650. }
  48651. else {
  48652. this._showTooltipContent(
  48653. singleTooltipModel, singleDefaultHTML, singleParamsList, Math.random(),
  48654. point[0], point[1], positionExpr
  48655. );
  48656. }
  48657. });
  48658. // Do not trigger events here, because this branch only be entered
  48659. // from dispatchAction.
  48660. },
  48661. _showSeriesItemTooltip: function (e, el, dispatchAction) {
  48662. var ecModel = this._ecModel;
  48663. // Use dataModel in element if possible
  48664. // Used when mouseover on a element like markPoint or edge
  48665. // In which case, the data is not main data in series.
  48666. var seriesIndex = el.seriesIndex;
  48667. var seriesModel = ecModel.getSeriesByIndex(seriesIndex);
  48668. // For example, graph link.
  48669. var dataModel = el.dataModel || seriesModel;
  48670. var dataIndex = el.dataIndex;
  48671. var dataType = el.dataType;
  48672. var data = dataModel.getData();
  48673. var tooltipModel = buildTooltipModel([
  48674. data.getItemModel(dataIndex),
  48675. dataModel,
  48676. seriesModel && (seriesModel.coordinateSystem || {}).model,
  48677. this._tooltipModel
  48678. ]);
  48679. var tooltipTrigger = tooltipModel.get('trigger');
  48680. if (tooltipTrigger != null && tooltipTrigger !== 'item') {
  48681. return;
  48682. }
  48683. var params = dataModel.getDataParams(dataIndex, dataType);
  48684. var defaultHtml = dataModel.formatTooltip(dataIndex, false, dataType);
  48685. var asyncTicket = 'item_' + dataModel.name + '_' + dataIndex;
  48686. this._showOrMove(tooltipModel, function () {
  48687. this._showTooltipContent(
  48688. tooltipModel, defaultHtml, params, asyncTicket,
  48689. e.offsetX, e.offsetY, e.position, e.target
  48690. );
  48691. });
  48692. // FIXME
  48693. // duplicated showtip if manuallyShowTip is called from dispatchAction.
  48694. dispatchAction({
  48695. type: 'showTip',
  48696. dataIndexInside: dataIndex,
  48697. dataIndex: data.getRawIndex(dataIndex),
  48698. seriesIndex: seriesIndex,
  48699. from: this.uid
  48700. });
  48701. },
  48702. _showComponentItemTooltip: function (e, el, dispatchAction) {
  48703. var tooltipOpt = el.tooltip;
  48704. if (typeof tooltipOpt === 'string') {
  48705. var content = tooltipOpt;
  48706. tooltipOpt = {
  48707. content: content,
  48708. // Fixed formatter
  48709. formatter: content
  48710. };
  48711. }
  48712. var subTooltipModel = new Model(tooltipOpt, this._tooltipModel, this._ecModel);
  48713. var defaultHtml = subTooltipModel.get('content');
  48714. var asyncTicket = Math.random();
  48715. // Do not check whether `trigger` is 'none' here, because `trigger`
  48716. // only works on cooridinate system. In fact, we have not found case
  48717. // that requires setting `trigger` nothing on component yet.
  48718. this._showOrMove(subTooltipModel, function () {
  48719. this._showTooltipContent(
  48720. subTooltipModel, defaultHtml, subTooltipModel.get('formatterParams') || {},
  48721. asyncTicket, e.offsetX, e.offsetY, e.position, el
  48722. );
  48723. });
  48724. // If not dispatch showTip, tip may be hide triggered by axis.
  48725. dispatchAction({
  48726. type: 'showTip',
  48727. from: this.uid
  48728. });
  48729. },
  48730. _showTooltipContent: function (
  48731. tooltipModel, defaultHtml, params, asyncTicket, x, y, positionExpr, el
  48732. ) {
  48733. // Reset ticket
  48734. this._ticket = '';
  48735. if (!tooltipModel.get('showContent') || !tooltipModel.get('show')) {
  48736. return;
  48737. }
  48738. var tooltipContent = this._tooltipContent;
  48739. var formatter = tooltipModel.get('formatter');
  48740. positionExpr = positionExpr || tooltipModel.get('position');
  48741. var html = defaultHtml;
  48742. if (formatter && typeof formatter === 'string') {
  48743. html = formatUtil.formatTpl(formatter, params, true);
  48744. }
  48745. else if (typeof formatter === 'function') {
  48746. var callback = bind(function (cbTicket, html) {
  48747. if (cbTicket === this._ticket) {
  48748. tooltipContent.setContent(html);
  48749. this._updatePosition(
  48750. tooltipModel, positionExpr, x, y, tooltipContent, params, el
  48751. );
  48752. }
  48753. }, this);
  48754. this._ticket = asyncTicket;
  48755. html = formatter(params, asyncTicket, callback);
  48756. }
  48757. tooltipContent.setContent(html);
  48758. tooltipContent.show(tooltipModel);
  48759. this._updatePosition(
  48760. tooltipModel, positionExpr, x, y, tooltipContent, params, el
  48761. );
  48762. },
  48763. /**
  48764. * @param {string|Function|Array.<number>} positionExpr
  48765. * @param {number} x Mouse x
  48766. * @param {number} y Mouse y
  48767. * @param {boolean} confine Whether confine tooltip content in view rect.
  48768. * @param {Object|<Array.<Object>} params
  48769. * @param {module:zrender/Element} el target element
  48770. * @param {module:echarts/ExtensionAPI} api
  48771. * @return {Array.<number>}
  48772. */
  48773. _updatePosition: function (tooltipModel, positionExpr, x, y, content, params, el) {
  48774. var viewWidth = this._api.getWidth();
  48775. var viewHeight = this._api.getHeight();
  48776. positionExpr = positionExpr || tooltipModel.get('position');
  48777. var contentSize = content.getSize();
  48778. var align = tooltipModel.get('align');
  48779. var vAlign = tooltipModel.get('verticalAlign');
  48780. var rect = el && el.getBoundingRect().clone();
  48781. el && rect.applyTransform(el.transform);
  48782. if (typeof positionExpr === 'function') {
  48783. // Callback of position can be an array or a string specify the position
  48784. positionExpr = positionExpr([x, y], params, content.el, rect, {
  48785. viewSize: [viewWidth, viewHeight],
  48786. contentSize: contentSize.slice()
  48787. });
  48788. }
  48789. if (zrUtil.isArray(positionExpr)) {
  48790. x = parsePercent(positionExpr[0], viewWidth);
  48791. y = parsePercent(positionExpr[1], viewHeight);
  48792. }
  48793. else if (zrUtil.isObject(positionExpr)) {
  48794. positionExpr.width = contentSize[0];
  48795. positionExpr.height = contentSize[1];
  48796. var layoutRect = layoutUtil.getLayoutRect(
  48797. positionExpr, {width: viewWidth, height: viewHeight}
  48798. );
  48799. x = layoutRect.x;
  48800. y = layoutRect.y;
  48801. align = null;
  48802. // When positionExpr is left/top/right/bottom,
  48803. // align and verticalAlign will not work.
  48804. vAlign = null;
  48805. }
  48806. // Specify tooltip position by string 'top' 'bottom' 'left' 'right' around graphic element
  48807. else if (typeof positionExpr === 'string' && el) {
  48808. var pos = calcTooltipPosition(
  48809. positionExpr, rect, contentSize
  48810. );
  48811. x = pos[0];
  48812. y = pos[1];
  48813. }
  48814. else {
  48815. var pos = refixTooltipPosition(
  48816. x, y, content.el, viewWidth, viewHeight, align ? null : 20, vAlign ? null : 20
  48817. );
  48818. x = pos[0];
  48819. y = pos[1];
  48820. }
  48821. align && (x -= isCenterAlign(align) ? contentSize[0] / 2 : align === 'right' ? contentSize[0] : 0);
  48822. vAlign && (y -= isCenterAlign(vAlign) ? contentSize[1] / 2 : vAlign === 'bottom' ? contentSize[1] : 0);
  48823. if (tooltipModel.get('confine')) {
  48824. var pos = confineTooltipPosition(
  48825. x, y, content.el, viewWidth, viewHeight
  48826. );
  48827. x = pos[0];
  48828. y = pos[1];
  48829. }
  48830. content.moveTo(x, y);
  48831. },
  48832. // FIXME
  48833. // Should we remove this but leave this to user?
  48834. _updateContentNotChangedOnAxis: function (dataByCoordSys) {
  48835. var lastCoordSys = this._lastDataByCoordSys;
  48836. var contentNotChanged = !!lastCoordSys
  48837. && lastCoordSys.length === dataByCoordSys.length;
  48838. contentNotChanged && each(lastCoordSys, function (lastItemCoordSys, indexCoordSys) {
  48839. var lastDataByAxis = lastItemCoordSys.dataByAxis || {};
  48840. var thisItemCoordSys = dataByCoordSys[indexCoordSys] || {};
  48841. var thisDataByAxis = thisItemCoordSys.dataByAxis || [];
  48842. contentNotChanged &= lastDataByAxis.length === thisDataByAxis.length;
  48843. contentNotChanged && each(lastDataByAxis, function (lastItem, indexAxis) {
  48844. var thisItem = thisDataByAxis[indexAxis] || {};
  48845. var lastIndices = lastItem.seriesDataIndices || [];
  48846. var newIndices = thisItem.seriesDataIndices || [];
  48847. contentNotChanged &=
  48848. lastItem.value === thisItem.value
  48849. && lastItem.axisType === thisItem.axisType
  48850. && lastItem.axisId === thisItem.axisId
  48851. && lastIndices.length === newIndices.length;
  48852. contentNotChanged && each(lastIndices, function (lastIdxItem, j) {
  48853. var newIdxItem = newIndices[j];
  48854. contentNotChanged &=
  48855. lastIdxItem.seriesIndex === newIdxItem.seriesIndex
  48856. && lastIdxItem.dataIndex === newIdxItem.dataIndex;
  48857. });
  48858. });
  48859. });
  48860. this._lastDataByCoordSys = dataByCoordSys;
  48861. return !!contentNotChanged;
  48862. },
  48863. _hide: function (dispatchAction) {
  48864. // Do not directly hideLater here, because this behavior may be prevented
  48865. // in dispatchAction when showTip is dispatched.
  48866. // FIXME
  48867. // duplicated hideTip if manuallyHideTip is called from dispatchAction.
  48868. this._lastDataByCoordSys = null;
  48869. dispatchAction({
  48870. type: 'hideTip',
  48871. from: this.uid
  48872. });
  48873. },
  48874. dispose: function (ecModel, api) {
  48875. if (env.node) {
  48876. return;
  48877. }
  48878. this._tooltipContent.hide();
  48879. globalListener.unregister('itemTooltip', api);
  48880. }
  48881. });
  48882. /**
  48883. * @param {Array.<Object|module:echarts/model/Model>} modelCascade
  48884. * From top to bottom. (the last one should be globalTooltipModel);
  48885. */
  48886. function buildTooltipModel(modelCascade) {
  48887. var resultModel = modelCascade.pop();
  48888. while (modelCascade.length) {
  48889. var tooltipOpt = modelCascade.pop();
  48890. if (tooltipOpt) {
  48891. if (tooltipOpt instanceof Model) {
  48892. tooltipOpt = tooltipOpt.get('tooltip', true);
  48893. }
  48894. // In each data item tooltip can be simply write:
  48895. // {
  48896. // value: 10,
  48897. // tooltip: 'Something you need to know'
  48898. // }
  48899. if (typeof tooltipOpt === 'string') {
  48900. tooltipOpt = {formatter: tooltipOpt};
  48901. }
  48902. resultModel = new Model(tooltipOpt, resultModel, resultModel.ecModel);
  48903. }
  48904. }
  48905. return resultModel;
  48906. }
  48907. function makeDispatchAction(payload, api) {
  48908. return payload.dispatchAction || zrUtil.bind(api.dispatchAction, api);
  48909. }
  48910. function refixTooltipPosition(x, y, el, viewWidth, viewHeight, gapH, gapV) {
  48911. var width = el.clientWidth;
  48912. var height = el.clientHeight;
  48913. if (gapH != null) {
  48914. if (x + width + gapH > viewWidth) {
  48915. x -= width + gapH;
  48916. }
  48917. else {
  48918. x += gapH;
  48919. }
  48920. }
  48921. if (gapV != null) {
  48922. if (y + height + gapV > viewHeight) {
  48923. y -= height + gapV;
  48924. }
  48925. else {
  48926. y += gapV;
  48927. }
  48928. }
  48929. return [x, y];
  48930. }
  48931. function confineTooltipPosition(x, y, el, viewWidth, viewHeight) {
  48932. var width = el.clientWidth;
  48933. var height = el.clientHeight;
  48934. x = Math.min(x + width, viewWidth) - width;
  48935. y = Math.min(y + height, viewHeight) - height;
  48936. x = Math.max(x, 0);
  48937. y = Math.max(y, 0);
  48938. return [x, y];
  48939. }
  48940. function calcTooltipPosition(position, rect, contentSize) {
  48941. var domWidth = contentSize[0];
  48942. var domHeight = contentSize[1];
  48943. var gap = 5;
  48944. var x = 0;
  48945. var y = 0;
  48946. var rectWidth = rect.width;
  48947. var rectHeight = rect.height;
  48948. switch (position) {
  48949. case 'inside':
  48950. x = rect.x + rectWidth / 2 - domWidth / 2;
  48951. y = rect.y + rectHeight / 2 - domHeight / 2;
  48952. break;
  48953. case 'top':
  48954. x = rect.x + rectWidth / 2 - domWidth / 2;
  48955. y = rect.y - domHeight - gap;
  48956. break;
  48957. case 'bottom':
  48958. x = rect.x + rectWidth / 2 - domWidth / 2;
  48959. y = rect.y + rectHeight + gap;
  48960. break;
  48961. case 'left':
  48962. x = rect.x - domWidth - gap;
  48963. y = rect.y + rectHeight / 2 - domHeight / 2;
  48964. break;
  48965. case 'right':
  48966. x = rect.x + rectWidth + gap;
  48967. y = rect.y + rectHeight / 2 - domHeight / 2;
  48968. }
  48969. return [x, y];
  48970. }
  48971. function isCenterAlign(align) {
  48972. return align === 'center' || align === 'middle';
  48973. }
  48974. /***/ },
  48975. /* 329 */
  48976. /***/ function(module, exports, __webpack_require__) {
  48977. /**
  48978. * @module echarts/component/tooltip/TooltipContent
  48979. */
  48980. var zrUtil = __webpack_require__(4);
  48981. var zrColor = __webpack_require__(31);
  48982. var eventUtil = __webpack_require__(88);
  48983. var formatUtil = __webpack_require__(6);
  48984. var each = zrUtil.each;
  48985. var toCamelCase = formatUtil.toCamelCase;
  48986. var env = __webpack_require__(2);
  48987. var vendors = ['', '-webkit-', '-moz-', '-o-'];
  48988. var gCssText = 'position:absolute;display:block;border-style:solid;white-space:nowrap;z-index:9999999;';
  48989. /**
  48990. * @param {number} duration
  48991. * @return {string}
  48992. * @inner
  48993. */
  48994. function assembleTransition(duration) {
  48995. var transitionCurve = 'cubic-bezier(0.23, 1, 0.32, 1)';
  48996. var transitionText = 'left ' + duration + 's ' + transitionCurve + ','
  48997. + 'top ' + duration + 's ' + transitionCurve;
  48998. return zrUtil.map(vendors, function (vendorPrefix) {
  48999. return vendorPrefix + 'transition:' + transitionText;
  49000. }).join(';');
  49001. }
  49002. /**
  49003. * @param {Object} textStyle
  49004. * @return {string}
  49005. * @inner
  49006. */
  49007. function assembleFont(textStyleModel) {
  49008. var cssText = [];
  49009. var fontSize = textStyleModel.get('fontSize');
  49010. var color = textStyleModel.getTextColor();
  49011. color && cssText.push('color:' + color);
  49012. cssText.push('font:' + textStyleModel.getFont());
  49013. fontSize &&
  49014. cssText.push('line-height:' + Math.round(fontSize * 3 / 2) + 'px');
  49015. each(['decoration', 'align'], function (name) {
  49016. var val = textStyleModel.get(name);
  49017. val && cssText.push('text-' + name + ':' + val);
  49018. });
  49019. return cssText.join(';');
  49020. }
  49021. /**
  49022. * @param {Object} tooltipModel
  49023. * @return {string}
  49024. * @inner
  49025. */
  49026. function assembleCssText(tooltipModel) {
  49027. var cssText = [];
  49028. var transitionDuration = tooltipModel.get('transitionDuration');
  49029. var backgroundColor = tooltipModel.get('backgroundColor');
  49030. var textStyleModel = tooltipModel.getModel('textStyle');
  49031. var padding = tooltipModel.get('padding');
  49032. // Animation transition. Do not animate when transitionDuration is 0.
  49033. transitionDuration &&
  49034. cssText.push(assembleTransition(transitionDuration));
  49035. if (backgroundColor) {
  49036. if (env.canvasSupported) {
  49037. cssText.push('background-Color:' + backgroundColor);
  49038. }
  49039. else {
  49040. // for ie
  49041. cssText.push(
  49042. 'background-Color:#' + zrColor.toHex(backgroundColor)
  49043. );
  49044. cssText.push('filter:alpha(opacity=70)');
  49045. }
  49046. }
  49047. // Border style
  49048. each(['width', 'color', 'radius'], function (name) {
  49049. var borderName = 'border-' + name;
  49050. var camelCase = toCamelCase(borderName);
  49051. var val = tooltipModel.get(camelCase);
  49052. val != null &&
  49053. cssText.push(borderName + ':' + val + (name === 'color' ? '' : 'px'));
  49054. });
  49055. // Text style
  49056. cssText.push(assembleFont(textStyleModel));
  49057. // Padding
  49058. if (padding != null) {
  49059. cssText.push('padding:' + formatUtil.normalizeCssArray(padding).join('px ') + 'px');
  49060. }
  49061. return cssText.join(';') + ';';
  49062. }
  49063. /**
  49064. * @alias module:echarts/component/tooltip/TooltipContent
  49065. * @constructor
  49066. */
  49067. function TooltipContent(container, api) {
  49068. var el = document.createElement('div');
  49069. var zr = this._zr = api.getZr();
  49070. this.el = el;
  49071. this._x = api.getWidth() / 2;
  49072. this._y = api.getHeight() / 2;
  49073. container.appendChild(el);
  49074. this._container = container;
  49075. this._show = false;
  49076. /**
  49077. * @private
  49078. */
  49079. this._hideTimeout;
  49080. var self = this;
  49081. el.onmouseenter = function () {
  49082. // clear the timeout in hideLater and keep showing tooltip
  49083. if (self._enterable) {
  49084. clearTimeout(self._hideTimeout);
  49085. self._show = true;
  49086. }
  49087. self._inContent = true;
  49088. };
  49089. el.onmousemove = function (e) {
  49090. e = e || window.event;
  49091. if (!self._enterable) {
  49092. // Try trigger zrender event to avoid mouse
  49093. // in and out shape too frequently
  49094. var handler = zr.handler;
  49095. eventUtil.normalizeEvent(container, e, true);
  49096. handler.dispatch('mousemove', e);
  49097. }
  49098. };
  49099. el.onmouseleave = function () {
  49100. if (self._enterable) {
  49101. if (self._show) {
  49102. self.hideLater(self._hideDelay);
  49103. }
  49104. }
  49105. self._inContent = false;
  49106. };
  49107. }
  49108. TooltipContent.prototype = {
  49109. constructor: TooltipContent,
  49110. /**
  49111. * @private
  49112. * @type {boolean}
  49113. */
  49114. _enterable: true,
  49115. /**
  49116. * Update when tooltip is rendered
  49117. */
  49118. update: function () {
  49119. // FIXME
  49120. // Move this logic to ec main?
  49121. var container = this._container;
  49122. var stl = container.currentStyle
  49123. || document.defaultView.getComputedStyle(container);
  49124. var domStyle = container.style;
  49125. if (domStyle.position !== 'absolute' && stl.position !== 'absolute') {
  49126. domStyle.position = 'relative';
  49127. }
  49128. // Hide the tooltip
  49129. // PENDING
  49130. // this.hide();
  49131. },
  49132. show: function (tooltipModel) {
  49133. clearTimeout(this._hideTimeout);
  49134. var el = this.el;
  49135. el.style.cssText = gCssText + assembleCssText(tooltipModel)
  49136. // http://stackoverflow.com/questions/21125587/css3-transition-not-working-in-chrome-anymore
  49137. + ';left:' + this._x + 'px;top:' + this._y + 'px;'
  49138. + (tooltipModel.get('extraCssText') || '');
  49139. el.style.display = el.innerHTML ? 'block' : 'none';
  49140. this._show = true;
  49141. },
  49142. setContent: function (content) {
  49143. this.el.innerHTML = content == null ? '' : content;
  49144. },
  49145. setEnterable: function (enterable) {
  49146. this._enterable = enterable;
  49147. },
  49148. getSize: function () {
  49149. var el = this.el;
  49150. return [el.clientWidth, el.clientHeight];
  49151. },
  49152. moveTo: function (x, y) {
  49153. // xy should be based on canvas root. But tooltipContent is
  49154. // the sibling of canvas root. So padding of ec container
  49155. // should be considered here.
  49156. var zr = this._zr;
  49157. var viewportRoot;
  49158. if (zr && zr.painter && (viewportRoot = zr.painter.getViewportRoot())) {
  49159. x += viewportRoot.offsetLeft || 0;
  49160. y += viewportRoot.offsetTop || 0;
  49161. }
  49162. var style = this.el.style;
  49163. style.left = x + 'px';
  49164. style.top = y + 'px';
  49165. this._x = x;
  49166. this._y = y;
  49167. },
  49168. hide: function () {
  49169. this.el.style.display = 'none';
  49170. this._show = false;
  49171. },
  49172. hideLater: function (time) {
  49173. if (this._show && !(this._inContent && this._enterable)) {
  49174. if (time) {
  49175. this._hideDelay = time;
  49176. // Set show false to avoid invoke hideLater mutiple times
  49177. this._show = false;
  49178. this._hideTimeout = setTimeout(zrUtil.bind(this.hide, this), time);
  49179. }
  49180. else {
  49181. this.hide();
  49182. }
  49183. }
  49184. },
  49185. isShow: function () {
  49186. return this._show;
  49187. }
  49188. };
  49189. module.exports = TooltipContent;
  49190. /***/ },
  49191. /* 330 */
  49192. /***/ function(module, exports, __webpack_require__) {
  49193. 'use strict';
  49194. var zrUtil = __webpack_require__(4);
  49195. __webpack_require__(331);
  49196. __webpack_require__(337);
  49197. __webpack_require__(339);
  49198. __webpack_require__(297);
  49199. __webpack_require__(341);
  49200. // For reducing size of echarts.min, barLayoutPolar is required by polar.
  49201. __webpack_require__(1).registerLayout(zrUtil.curry(__webpack_require__(342), 'bar'));
  49202. // Polar view
  49203. __webpack_require__(1).extendComponentView({
  49204. type: 'polar'
  49205. });
  49206. /***/ },
  49207. /* 331 */
  49208. /***/ function(module, exports, __webpack_require__) {
  49209. // TODO Axis scale
  49210. var Polar = __webpack_require__(332);
  49211. var numberUtil = __webpack_require__(7);
  49212. var zrUtil = __webpack_require__(4);
  49213. var axisHelper = __webpack_require__(101);
  49214. var niceScaleExtent = axisHelper.niceScaleExtent;
  49215. // 依赖 PolarModel 做预处理
  49216. __webpack_require__(335);
  49217. /**
  49218. * Resize method bound to the polar
  49219. * @param {module:echarts/coord/polar/PolarModel} polarModel
  49220. * @param {module:echarts/ExtensionAPI} api
  49221. */
  49222. function resizePolar(polarModel, api) {
  49223. var center = polarModel.get('center');
  49224. var radius = polarModel.get('radius');
  49225. var width = api.getWidth();
  49226. var height = api.getHeight();
  49227. var parsePercent = numberUtil.parsePercent;
  49228. this.cx = parsePercent(center[0], width);
  49229. this.cy = parsePercent(center[1], height);
  49230. var radiusAxis = this.getRadiusAxis();
  49231. var size = Math.min(width, height) / 2;
  49232. // var idx = radiusAxis.inverse ? 1 : 0;
  49233. radiusAxis.setExtent(0, parsePercent(radius, size));
  49234. }
  49235. /**
  49236. * Update polar
  49237. */
  49238. function updatePolarScale(ecModel, api) {
  49239. var polar = this;
  49240. var angleAxis = polar.getAngleAxis();
  49241. var radiusAxis = polar.getRadiusAxis();
  49242. // Reset scale
  49243. angleAxis.scale.setExtent(Infinity, -Infinity);
  49244. radiusAxis.scale.setExtent(Infinity, -Infinity);
  49245. ecModel.eachSeries(function (seriesModel) {
  49246. if (seriesModel.coordinateSystem === polar) {
  49247. var data = seriesModel.getData();
  49248. radiusAxis.scale.unionExtentFromData(data, 'radius');
  49249. angleAxis.scale.unionExtentFromData(data, 'angle');
  49250. }
  49251. });
  49252. niceScaleExtent(angleAxis.scale, angleAxis.model);
  49253. niceScaleExtent(radiusAxis.scale, radiusAxis.model);
  49254. // Fix extent of category angle axis
  49255. if (angleAxis.type === 'category' && !angleAxis.onBand) {
  49256. var extent = angleAxis.getExtent();
  49257. var diff = 360 / angleAxis.scale.count();
  49258. angleAxis.inverse ? (extent[1] += diff) : (extent[1] -= diff);
  49259. angleAxis.setExtent(extent[0], extent[1]);
  49260. }
  49261. }
  49262. /**
  49263. * Set common axis properties
  49264. * @param {module:echarts/coord/polar/AngleAxis|module:echarts/coord/polar/RadiusAxis}
  49265. * @param {module:echarts/coord/polar/AxisModel}
  49266. * @inner
  49267. */
  49268. function setAxis(axis, axisModel) {
  49269. axis.type = axisModel.get('type');
  49270. axis.scale = axisHelper.createScaleByModel(axisModel);
  49271. axis.onBand = axisModel.get('boundaryGap') && axis.type === 'category';
  49272. // FIXME Radius axis not support inverse axis
  49273. if (axisModel.mainType === 'angleAxis') {
  49274. var startAngle = axisModel.get('startAngle');
  49275. axis.inverse = axisModel.get('inverse') ^ axisModel.get('clockwise');
  49276. axis.setExtent(startAngle, startAngle + (axis.inverse ? -360 : 360));
  49277. }
  49278. // Inject axis instance
  49279. axisModel.axis = axis;
  49280. axis.model = axisModel;
  49281. }
  49282. var polarCreator = {
  49283. dimensions: Polar.prototype.dimensions,
  49284. create: function (ecModel, api) {
  49285. var polarList = [];
  49286. ecModel.eachComponent('polar', function (polarModel, idx) {
  49287. var polar = new Polar(idx);
  49288. // Inject resize and update method
  49289. polar.resize = resizePolar;
  49290. polar.update = updatePolarScale;
  49291. var radiusAxis = polar.getRadiusAxis();
  49292. var angleAxis = polar.getAngleAxis();
  49293. var radiusAxisModel = polarModel.findAxisModel('radiusAxis');
  49294. var angleAxisModel = polarModel.findAxisModel('angleAxis');
  49295. setAxis(radiusAxis, radiusAxisModel);
  49296. setAxis(angleAxis, angleAxisModel);
  49297. polar.resize(polarModel, api);
  49298. polarList.push(polar);
  49299. polarModel.coordinateSystem = polar;
  49300. polar.model = polarModel;
  49301. });
  49302. // Inject coordinateSystem to series
  49303. ecModel.eachSeries(function (seriesModel) {
  49304. if (seriesModel.get('coordinateSystem') === 'polar') {
  49305. var polarModel = ecModel.queryComponents({
  49306. mainType: 'polar',
  49307. index: seriesModel.get('polarIndex'),
  49308. id: seriesModel.get('polarId')
  49309. })[0];
  49310. if (true) {
  49311. if (!polarModel) {
  49312. throw new Error(
  49313. 'Polar "' + zrUtil.retrieve(
  49314. seriesModel.get('polarIndex'),
  49315. seriesModel.get('polarId'),
  49316. 0
  49317. ) + '" not found'
  49318. );
  49319. }
  49320. }
  49321. seriesModel.coordinateSystem = polarModel.coordinateSystem;
  49322. }
  49323. });
  49324. return polarList;
  49325. }
  49326. };
  49327. __webpack_require__(76).register('polar', polarCreator);
  49328. /***/ },
  49329. /* 332 */
  49330. /***/ function(module, exports, __webpack_require__) {
  49331. 'use strict';
  49332. /**
  49333. * @module echarts/coord/polar/Polar
  49334. */
  49335. var RadiusAxis = __webpack_require__(333);
  49336. var AngleAxis = __webpack_require__(334);
  49337. /**
  49338. * @alias {module:echarts/coord/polar/Polar}
  49339. * @constructor
  49340. * @param {string} name
  49341. */
  49342. var Polar = function (name) {
  49343. /**
  49344. * @type {string}
  49345. */
  49346. this.name = name || '';
  49347. /**
  49348. * x of polar center
  49349. * @type {number}
  49350. */
  49351. this.cx = 0;
  49352. /**
  49353. * y of polar center
  49354. * @type {number}
  49355. */
  49356. this.cy = 0;
  49357. /**
  49358. * @type {module:echarts/coord/polar/RadiusAxis}
  49359. * @private
  49360. */
  49361. this._radiusAxis = new RadiusAxis();
  49362. /**
  49363. * @type {module:echarts/coord/polar/AngleAxis}
  49364. * @private
  49365. */
  49366. this._angleAxis = new AngleAxis();
  49367. this._radiusAxis.polar = this._angleAxis.polar = this;
  49368. };
  49369. Polar.prototype = {
  49370. type: 'polar',
  49371. axisPointerEnabled: true,
  49372. constructor: Polar,
  49373. /**
  49374. * @param {Array.<string>}
  49375. * @readOnly
  49376. */
  49377. dimensions: ['radius', 'angle'],
  49378. /**
  49379. * @type {module:echarts/coord/PolarModel}
  49380. */
  49381. model: null,
  49382. /**
  49383. * If contain coord
  49384. * @param {Array.<number>} point
  49385. * @return {boolean}
  49386. */
  49387. containPoint: function (point) {
  49388. var coord = this.pointToCoord(point);
  49389. return this._radiusAxis.contain(coord[0])
  49390. && this._angleAxis.contain(coord[1]);
  49391. },
  49392. /**
  49393. * If contain data
  49394. * @param {Array.<number>} data
  49395. * @return {boolean}
  49396. */
  49397. containData: function (data) {
  49398. return this._radiusAxis.containData(data[0])
  49399. && this._angleAxis.containData(data[1]);
  49400. },
  49401. /**
  49402. * @param {string} dim
  49403. * @return {module:echarts/coord/polar/AngleAxis|module:echarts/coord/polar/RadiusAxis}
  49404. */
  49405. getAxis: function (dim) {
  49406. return this['_' + dim + 'Axis'];
  49407. },
  49408. /**
  49409. * @return {Array.<module:echarts/coord/Axis>}
  49410. */
  49411. getAxes: function () {
  49412. return [this._radiusAxis, this._angleAxis];
  49413. },
  49414. /**
  49415. * Get axes by type of scale
  49416. * @param {string} scaleType
  49417. * @return {module:echarts/coord/polar/AngleAxis|module:echarts/coord/polar/RadiusAxis}
  49418. */
  49419. getAxesByScale: function (scaleType) {
  49420. var axes = [];
  49421. var angleAxis = this._angleAxis;
  49422. var radiusAxis = this._radiusAxis;
  49423. angleAxis.scale.type === scaleType && axes.push(angleAxis);
  49424. radiusAxis.scale.type === scaleType && axes.push(radiusAxis);
  49425. return axes;
  49426. },
  49427. /**
  49428. * @return {module:echarts/coord/polar/AngleAxis}
  49429. */
  49430. getAngleAxis: function () {
  49431. return this._angleAxis;
  49432. },
  49433. /**
  49434. * @return {module:echarts/coord/polar/RadiusAxis}
  49435. */
  49436. getRadiusAxis: function () {
  49437. return this._radiusAxis;
  49438. },
  49439. /**
  49440. * @param {module:echarts/coord/polar/Axis}
  49441. * @return {module:echarts/coord/polar/Axis}
  49442. */
  49443. getOtherAxis: function (axis) {
  49444. var angleAxis = this._angleAxis;
  49445. return axis === angleAxis ? this._radiusAxis : angleAxis;
  49446. },
  49447. /**
  49448. * Base axis will be used on stacking.
  49449. *
  49450. * @return {module:echarts/coord/polar/Axis}
  49451. */
  49452. getBaseAxis: function () {
  49453. return this.getAxesByScale('ordinal')[0]
  49454. || this.getAxesByScale('time')[0]
  49455. || this.getAngleAxis();
  49456. },
  49457. /**
  49458. * @param {string} [dim] 'radius' or 'angle' or 'auto' or null/undefined
  49459. * @return {Object} {baseAxes: [], otherAxes: []}
  49460. */
  49461. getTooltipAxes: function (dim) {
  49462. var baseAxis = (dim != null && dim !== 'auto')
  49463. ? this.getAxis(dim) : this.getBaseAxis();
  49464. return {
  49465. baseAxes: [baseAxis],
  49466. otherAxes: [this.getOtherAxis(baseAxis)]
  49467. };
  49468. },
  49469. /**
  49470. * Convert series data to a list of (x, y) points
  49471. * @param {module:echarts/data/List} data
  49472. * @return {Array}
  49473. * Return list of coordinates. For example:
  49474. * `[[10, 10], [20, 20], [30, 30]]`
  49475. */
  49476. dataToPoints: function (data) {
  49477. return data.mapArray(this.dimensions, function (radius, angle) {
  49478. return this.dataToPoint([radius, angle]);
  49479. }, true, this);
  49480. },
  49481. /**
  49482. * Convert a single data item to (x, y) point.
  49483. * Parameter data is an array which the first element is radius and the second is angle
  49484. * @param {Array.<number>} data
  49485. * @param {boolean} [clamp=false]
  49486. * @return {Array.<number>}
  49487. */
  49488. dataToPoint: function (data, clamp) {
  49489. return this.coordToPoint([
  49490. this._radiusAxis.dataToRadius(data[0], clamp),
  49491. this._angleAxis.dataToAngle(data[1], clamp)
  49492. ]);
  49493. },
  49494. /**
  49495. * Convert a (x, y) point to data
  49496. * @param {Array.<number>} point
  49497. * @param {boolean} [clamp=false]
  49498. * @return {Array.<number>}
  49499. */
  49500. pointToData: function (point, clamp) {
  49501. var coord = this.pointToCoord(point);
  49502. return [
  49503. this._radiusAxis.radiusToData(coord[0], clamp),
  49504. this._angleAxis.angleToData(coord[1], clamp)
  49505. ];
  49506. },
  49507. /**
  49508. * Convert a (x, y) point to (radius, angle) coord
  49509. * @param {Array.<number>} point
  49510. * @return {Array.<number>}
  49511. */
  49512. pointToCoord: function (point) {
  49513. var dx = point[0] - this.cx;
  49514. var dy = point[1] - this.cy;
  49515. var angleAxis = this.getAngleAxis();
  49516. var extent = angleAxis.getExtent();
  49517. var minAngle = Math.min(extent[0], extent[1]);
  49518. var maxAngle = Math.max(extent[0], extent[1]);
  49519. // Fix fixed extent in polarCreator
  49520. // FIXME
  49521. angleAxis.inverse
  49522. ? (minAngle = maxAngle - 360)
  49523. : (maxAngle = minAngle + 360);
  49524. var radius = Math.sqrt(dx * dx + dy * dy);
  49525. dx /= radius;
  49526. dy /= radius;
  49527. var radian = Math.atan2(-dy, dx) / Math.PI * 180;
  49528. // move to angleExtent
  49529. var dir = radian < minAngle ? 1 : -1;
  49530. while (radian < minAngle || radian > maxAngle) {
  49531. radian += dir * 360;
  49532. }
  49533. return [radius, radian];
  49534. },
  49535. /**
  49536. * Convert a (radius, angle) coord to (x, y) point
  49537. * @param {Array.<number>} coord
  49538. * @return {Array.<number>}
  49539. */
  49540. coordToPoint: function (coord) {
  49541. var radius = coord[0];
  49542. var radian = coord[1] / 180 * Math.PI;
  49543. var x = Math.cos(radian) * radius + this.cx;
  49544. // Inverse the y
  49545. var y = -Math.sin(radian) * radius + this.cy;
  49546. return [x, y];
  49547. }
  49548. };
  49549. module.exports = Polar;
  49550. /***/ },
  49551. /* 333 */
  49552. /***/ function(module, exports, __webpack_require__) {
  49553. 'use strict';
  49554. var zrUtil = __webpack_require__(4);
  49555. var Axis = __webpack_require__(100);
  49556. function RadiusAxis(scale, radiusExtent) {
  49557. Axis.call(this, 'radius', scale, radiusExtent);
  49558. /**
  49559. * Axis type
  49560. * - 'category'
  49561. * - 'value'
  49562. * - 'time'
  49563. * - 'log'
  49564. * @type {string}
  49565. */
  49566. this.type = 'category';
  49567. }
  49568. RadiusAxis.prototype = {
  49569. constructor: RadiusAxis,
  49570. /**
  49571. * @override
  49572. */
  49573. pointToData: function (point, clamp) {
  49574. return this.polar.pointToData(point, clamp)[this.dim === 'radius' ? 0 : 1];
  49575. },
  49576. dataToRadius: Axis.prototype.dataToCoord,
  49577. radiusToData: Axis.prototype.coordToData
  49578. };
  49579. zrUtil.inherits(RadiusAxis, Axis);
  49580. module.exports = RadiusAxis;
  49581. /***/ },
  49582. /* 334 */
  49583. /***/ function(module, exports, __webpack_require__) {
  49584. 'use strict';
  49585. var zrUtil = __webpack_require__(4);
  49586. var Axis = __webpack_require__(100);
  49587. function AngleAxis(scale, angleExtent) {
  49588. angleExtent = angleExtent || [0, 360];
  49589. Axis.call(this, 'angle', scale, angleExtent);
  49590. /**
  49591. * Axis type
  49592. * - 'category'
  49593. * - 'value'
  49594. * - 'time'
  49595. * - 'log'
  49596. * @type {string}
  49597. */
  49598. this.type = 'category';
  49599. }
  49600. AngleAxis.prototype = {
  49601. constructor: AngleAxis,
  49602. /**
  49603. * @override
  49604. */
  49605. pointToData: function (point, clamp) {
  49606. return this.polar.pointToData(point, clamp)[this.dim === 'radius' ? 0 : 1];
  49607. },
  49608. dataToAngle: Axis.prototype.dataToCoord,
  49609. angleToData: Axis.prototype.coordToData
  49610. };
  49611. zrUtil.inherits(AngleAxis, Axis);
  49612. module.exports = AngleAxis;
  49613. /***/ },
  49614. /* 335 */
  49615. /***/ function(module, exports, __webpack_require__) {
  49616. 'use strict';
  49617. __webpack_require__(336);
  49618. __webpack_require__(1).extendComponentModel({
  49619. type: 'polar',
  49620. dependencies: ['polarAxis', 'angleAxis'],
  49621. /**
  49622. * @type {module:echarts/coord/polar/Polar}
  49623. */
  49624. coordinateSystem: null,
  49625. /**
  49626. * @param {string} axisType
  49627. * @return {module:echarts/coord/polar/AxisModel}
  49628. */
  49629. findAxisModel: function (axisType) {
  49630. var foundAxisModel;
  49631. var ecModel = this.ecModel;
  49632. ecModel.eachComponent(axisType, function (axisModel) {
  49633. if (axisModel.getCoordSysModel() === this) {
  49634. foundAxisModel = axisModel;
  49635. }
  49636. }, this);
  49637. return foundAxisModel;
  49638. },
  49639. defaultOption: {
  49640. zlevel: 0,
  49641. z: 0,
  49642. center: ['50%', '50%'],
  49643. radius: '80%'
  49644. }
  49645. });
  49646. /***/ },
  49647. /* 336 */
  49648. /***/ function(module, exports, __webpack_require__) {
  49649. 'use strict';
  49650. var zrUtil = __webpack_require__(4);
  49651. var ComponentModel = __webpack_require__(69);
  49652. var axisModelCreator = __webpack_require__(131);
  49653. var PolarAxisModel = ComponentModel.extend({
  49654. type: 'polarAxis',
  49655. /**
  49656. * @type {module:echarts/coord/polar/AngleAxis|module:echarts/coord/polar/RadiusAxis}
  49657. */
  49658. axis: null,
  49659. /**
  49660. * @override
  49661. */
  49662. getCoordSysModel: function () {
  49663. return this.ecModel.queryComponents({
  49664. mainType: 'polar',
  49665. index: this.option.polarIndex,
  49666. id: this.option.polarId
  49667. })[0];
  49668. }
  49669. });
  49670. zrUtil.merge(PolarAxisModel.prototype, __webpack_require__(112));
  49671. var polarAxisDefaultExtendedOption = {
  49672. angle: {
  49673. // polarIndex: 0,
  49674. // polarId: '',
  49675. startAngle: 90,
  49676. clockwise: true,
  49677. splitNumber: 12,
  49678. axisLabel: {
  49679. rotate: false
  49680. }
  49681. },
  49682. radius: {
  49683. // polarIndex: 0,
  49684. // polarId: '',
  49685. splitNumber: 5
  49686. }
  49687. };
  49688. function getAxisType(axisDim, option) {
  49689. // Default axis with data is category axis
  49690. return option.type || (option.data ? 'category' : 'value');
  49691. }
  49692. axisModelCreator('angle', PolarAxisModel, getAxisType, polarAxisDefaultExtendedOption.angle);
  49693. axisModelCreator('radius', PolarAxisModel, getAxisType, polarAxisDefaultExtendedOption.radius);
  49694. /***/ },
  49695. /* 337 */
  49696. /***/ function(module, exports, __webpack_require__) {
  49697. 'use strict';
  49698. __webpack_require__(331);
  49699. __webpack_require__(338);
  49700. /***/ },
  49701. /* 338 */
  49702. /***/ function(module, exports, __webpack_require__) {
  49703. 'use strict';
  49704. var zrUtil = __webpack_require__(4);
  49705. var graphic = __webpack_require__(18);
  49706. var Model = __webpack_require__(12);
  49707. var elementList = ['axisLine', 'axisLabel', 'axisTick', 'splitLine', 'splitArea'];
  49708. function getAxisLineShape(polar, r0, r, angle) {
  49709. var start = polar.coordToPoint([r0, angle]);
  49710. var end = polar.coordToPoint([r, angle]);
  49711. return {
  49712. x1: start[0],
  49713. y1: start[1],
  49714. x2: end[0],
  49715. y2: end[1]
  49716. };
  49717. }
  49718. __webpack_require__(136).extend({
  49719. type: 'angleAxis',
  49720. axisPointerClass: 'PolarAxisPointer',
  49721. render: function (angleAxisModel, ecModel) {
  49722. this.group.removeAll();
  49723. if (!angleAxisModel.get('show')) {
  49724. return;
  49725. }
  49726. var angleAxis = angleAxisModel.axis;
  49727. var polar = angleAxis.polar;
  49728. var radiusExtent = polar.getRadiusAxis().getExtent();
  49729. var ticksAngles = angleAxis.getTicksCoords();
  49730. if (angleAxis.type !== 'category') {
  49731. // Remove the last tick which will overlap the first tick
  49732. ticksAngles.pop();
  49733. }
  49734. zrUtil.each(elementList, function (name) {
  49735. if (angleAxisModel.get(name +'.show')
  49736. && (!angleAxis.scale.isBlank() || name === 'axisLine')
  49737. ) {
  49738. this['_' + name](angleAxisModel, polar, ticksAngles, radiusExtent);
  49739. }
  49740. }, this);
  49741. },
  49742. /**
  49743. * @private
  49744. */
  49745. _axisLine: function (angleAxisModel, polar, ticksAngles, radiusExtent) {
  49746. var lineStyleModel = angleAxisModel.getModel('axisLine.lineStyle');
  49747. var circle = new graphic.Circle({
  49748. shape: {
  49749. cx: polar.cx,
  49750. cy: polar.cy,
  49751. r: radiusExtent[1]
  49752. },
  49753. style: lineStyleModel.getLineStyle(),
  49754. z2: 1,
  49755. silent: true
  49756. });
  49757. circle.style.fill = null;
  49758. this.group.add(circle);
  49759. },
  49760. /**
  49761. * @private
  49762. */
  49763. _axisTick: function (angleAxisModel, polar, ticksAngles, radiusExtent) {
  49764. var tickModel = angleAxisModel.getModel('axisTick');
  49765. var tickLen = (tickModel.get('inside') ? -1 : 1) * tickModel.get('length');
  49766. var lines = zrUtil.map(ticksAngles, function (tickAngle) {
  49767. return new graphic.Line({
  49768. shape: getAxisLineShape(polar, radiusExtent[1], radiusExtent[1] + tickLen, tickAngle)
  49769. });
  49770. });
  49771. this.group.add(graphic.mergePath(
  49772. lines, {
  49773. style: zrUtil.defaults(
  49774. tickModel.getModel('lineStyle').getLineStyle(),
  49775. {
  49776. stroke: angleAxisModel.get('axisLine.lineStyle.color')
  49777. }
  49778. )
  49779. }
  49780. ));
  49781. },
  49782. /**
  49783. * @private
  49784. */
  49785. _axisLabel: function (angleAxisModel, polar, ticksAngles, radiusExtent) {
  49786. var axis = angleAxisModel.axis;
  49787. var categoryData = angleAxisModel.get('data');
  49788. var labelModel = angleAxisModel.getModel('axisLabel');
  49789. var axisTextStyleModel = labelModel.getModel('textStyle');
  49790. var labels = angleAxisModel.getFormattedLabels();
  49791. var labelMargin = labelModel.get('margin');
  49792. var labelsAngles = axis.getLabelsCoords();
  49793. // Use length of ticksAngles because it may remove the last tick to avoid overlapping
  49794. for (var i = 0; i < ticksAngles.length; i++) {
  49795. var r = radiusExtent[1];
  49796. var p = polar.coordToPoint([r + labelMargin, labelsAngles[i]]);
  49797. var cx = polar.cx;
  49798. var cy = polar.cy;
  49799. var labelTextAlign = Math.abs(p[0] - cx) / r < 0.3
  49800. ? 'center' : (p[0] > cx ? 'left' : 'right');
  49801. var labelTextBaseline = Math.abs(p[1] - cy) / r < 0.3
  49802. ? 'middle' : (p[1] > cy ? 'top' : 'bottom');
  49803. var textStyleModel = axisTextStyleModel;
  49804. if (categoryData && categoryData[i] && categoryData[i].textStyle) {
  49805. textStyleModel = new Model(
  49806. categoryData[i].textStyle, axisTextStyleModel
  49807. );
  49808. }
  49809. this.group.add(new graphic.Text({
  49810. style: {
  49811. x: p[0],
  49812. y: p[1],
  49813. fill: textStyleModel.getTextColor() || angleAxisModel.get('axisLine.lineStyle.color'),
  49814. text: labels[i],
  49815. textAlign: labelTextAlign,
  49816. textVerticalAlign: labelTextBaseline,
  49817. textFont: textStyleModel.getFont()
  49818. },
  49819. silent: true
  49820. }));
  49821. }
  49822. },
  49823. /**
  49824. * @private
  49825. */
  49826. _splitLine: function (angleAxisModel, polar, ticksAngles, radiusExtent) {
  49827. var splitLineModel = angleAxisModel.getModel('splitLine');
  49828. var lineStyleModel = splitLineModel.getModel('lineStyle');
  49829. var lineColors = lineStyleModel.get('color');
  49830. var lineCount = 0;
  49831. lineColors = lineColors instanceof Array ? lineColors : [lineColors];
  49832. var splitLines = [];
  49833. for (var i = 0; i < ticksAngles.length; i++) {
  49834. var colorIndex = (lineCount++) % lineColors.length;
  49835. splitLines[colorIndex] = splitLines[colorIndex] || [];
  49836. splitLines[colorIndex].push(new graphic.Line({
  49837. shape: getAxisLineShape(polar, radiusExtent[0], radiusExtent[1], ticksAngles[i])
  49838. }));
  49839. }
  49840. // Simple optimization
  49841. // Batching the lines if color are the same
  49842. for (var i = 0; i < splitLines.length; i++) {
  49843. this.group.add(graphic.mergePath(splitLines[i], {
  49844. style: zrUtil.defaults({
  49845. stroke: lineColors[i % lineColors.length]
  49846. }, lineStyleModel.getLineStyle()),
  49847. silent: true,
  49848. z: angleAxisModel.get('z')
  49849. }));
  49850. }
  49851. },
  49852. /**
  49853. * @private
  49854. */
  49855. _splitArea: function (angleAxisModel, polar, ticksAngles, radiusExtent) {
  49856. var splitAreaModel = angleAxisModel.getModel('splitArea');
  49857. var areaStyleModel = splitAreaModel.getModel('areaStyle');
  49858. var areaColors = areaStyleModel.get('color');
  49859. var lineCount = 0;
  49860. areaColors = areaColors instanceof Array ? areaColors : [areaColors];
  49861. var splitAreas = [];
  49862. var RADIAN = Math.PI / 180;
  49863. var prevAngle = -ticksAngles[0] * RADIAN;
  49864. var r0 = Math.min(radiusExtent[0], radiusExtent[1]);
  49865. var r1 = Math.max(radiusExtent[0], radiusExtent[1]);
  49866. var clockwise = angleAxisModel.get('clockwise');
  49867. for (var i = 1; i < ticksAngles.length; i++) {
  49868. var colorIndex = (lineCount++) % areaColors.length;
  49869. splitAreas[colorIndex] = splitAreas[colorIndex] || [];
  49870. splitAreas[colorIndex].push(new graphic.Sector({
  49871. shape: {
  49872. cx: polar.cx,
  49873. cy: polar.cy,
  49874. r0: r0,
  49875. r: r1,
  49876. startAngle: prevAngle,
  49877. endAngle: -ticksAngles[i] * RADIAN,
  49878. clockwise: clockwise
  49879. },
  49880. silent: true
  49881. }));
  49882. prevAngle = -ticksAngles[i] * RADIAN;
  49883. }
  49884. // Simple optimization
  49885. // Batching the lines if color are the same
  49886. for (var i = 0; i < splitAreas.length; i++) {
  49887. this.group.add(graphic.mergePath(splitAreas[i], {
  49888. style: zrUtil.defaults({
  49889. fill: areaColors[i % areaColors.length]
  49890. }, areaStyleModel.getAreaStyle()),
  49891. silent: true
  49892. }));
  49893. }
  49894. }
  49895. });
  49896. /***/ },
  49897. /* 339 */
  49898. /***/ function(module, exports, __webpack_require__) {
  49899. __webpack_require__(331);
  49900. __webpack_require__(340);
  49901. /***/ },
  49902. /* 340 */
  49903. /***/ function(module, exports, __webpack_require__) {
  49904. 'use strict';
  49905. var zrUtil = __webpack_require__(4);
  49906. var graphic = __webpack_require__(18);
  49907. var AxisBuilder = __webpack_require__(135);
  49908. var axisBuilderAttrs = [
  49909. 'axisLine', 'axisLabel', 'axisTick', 'axisName'
  49910. ];
  49911. var selfBuilderAttrs = [
  49912. 'splitLine', 'splitArea'
  49913. ];
  49914. __webpack_require__(136).extend({
  49915. type: 'radiusAxis',
  49916. axisPointerClass: 'PolarAxisPointer',
  49917. render: function (radiusAxisModel, ecModel) {
  49918. this.group.removeAll();
  49919. if (!radiusAxisModel.get('show')) {
  49920. return;
  49921. }
  49922. var radiusAxis = radiusAxisModel.axis;
  49923. var polar = radiusAxis.polar;
  49924. var angleAxis = polar.getAngleAxis();
  49925. var ticksCoords = radiusAxis.getTicksCoords();
  49926. var axisAngle = angleAxis.getExtent()[0];
  49927. var radiusExtent = radiusAxis.getExtent();
  49928. var layout = layoutAxis(polar, radiusAxisModel, axisAngle);
  49929. var axisBuilder = new AxisBuilder(radiusAxisModel, layout);
  49930. zrUtil.each(axisBuilderAttrs, axisBuilder.add, axisBuilder);
  49931. this.group.add(axisBuilder.getGroup());
  49932. zrUtil.each(selfBuilderAttrs, function (name) {
  49933. if (radiusAxisModel.get(name +'.show') && !radiusAxis.scale.isBlank()) {
  49934. this['_' + name](radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords);
  49935. }
  49936. }, this);
  49937. },
  49938. /**
  49939. * @private
  49940. */
  49941. _splitLine: function (radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords) {
  49942. var splitLineModel = radiusAxisModel.getModel('splitLine');
  49943. var lineStyleModel = splitLineModel.getModel('lineStyle');
  49944. var lineColors = lineStyleModel.get('color');
  49945. var lineCount = 0;
  49946. lineColors = lineColors instanceof Array ? lineColors : [lineColors];
  49947. var splitLines = [];
  49948. for (var i = 0; i < ticksCoords.length; i++) {
  49949. var colorIndex = (lineCount++) % lineColors.length;
  49950. splitLines[colorIndex] = splitLines[colorIndex] || [];
  49951. splitLines[colorIndex].push(new graphic.Circle({
  49952. shape: {
  49953. cx: polar.cx,
  49954. cy: polar.cy,
  49955. r: ticksCoords[i]
  49956. },
  49957. silent: true
  49958. }));
  49959. }
  49960. // Simple optimization
  49961. // Batching the lines if color are the same
  49962. for (var i = 0; i < splitLines.length; i++) {
  49963. this.group.add(graphic.mergePath(splitLines[i], {
  49964. style: zrUtil.defaults({
  49965. stroke: lineColors[i % lineColors.length],
  49966. fill: null
  49967. }, lineStyleModel.getLineStyle()),
  49968. silent: true
  49969. }));
  49970. }
  49971. },
  49972. /**
  49973. * @private
  49974. */
  49975. _splitArea: function (radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords) {
  49976. var splitAreaModel = radiusAxisModel.getModel('splitArea');
  49977. var areaStyleModel = splitAreaModel.getModel('areaStyle');
  49978. var areaColors = areaStyleModel.get('color');
  49979. var lineCount = 0;
  49980. areaColors = areaColors instanceof Array ? areaColors : [areaColors];
  49981. var splitAreas = [];
  49982. var prevRadius = ticksCoords[0];
  49983. for (var i = 1; i < ticksCoords.length; i++) {
  49984. var colorIndex = (lineCount++) % areaColors.length;
  49985. splitAreas[colorIndex] = splitAreas[colorIndex] || [];
  49986. splitAreas[colorIndex].push(new graphic.Sector({
  49987. shape: {
  49988. cx: polar.cx,
  49989. cy: polar.cy,
  49990. r0: prevRadius,
  49991. r: ticksCoords[i],
  49992. startAngle: 0,
  49993. endAngle: Math.PI * 2
  49994. },
  49995. silent: true
  49996. }));
  49997. prevRadius = ticksCoords[i];
  49998. }
  49999. // Simple optimization
  50000. // Batching the lines if color are the same
  50001. for (var i = 0; i < splitAreas.length; i++) {
  50002. this.group.add(graphic.mergePath(splitAreas[i], {
  50003. style: zrUtil.defaults({
  50004. fill: areaColors[i % areaColors.length]
  50005. }, areaStyleModel.getAreaStyle()),
  50006. silent: true
  50007. }));
  50008. }
  50009. }
  50010. });
  50011. /**
  50012. * @inner
  50013. */
  50014. function layoutAxis(polar, radiusAxisModel, axisAngle) {
  50015. return {
  50016. position: [polar.cx, polar.cy],
  50017. rotation: axisAngle / 180 * Math.PI,
  50018. labelDirection: -1,
  50019. tickDirection: -1,
  50020. nameDirection: 1,
  50021. labelRotate: radiusAxisModel.getModel('axisLabel').get('rotate'),
  50022. // Over splitLine and splitArea
  50023. z2: 1
  50024. };
  50025. }
  50026. /***/ },
  50027. /* 341 */
  50028. /***/ function(module, exports, __webpack_require__) {
  50029. 'use strict';
  50030. var formatUtil = __webpack_require__(6);
  50031. var BaseAxisPointer = __webpack_require__(304);
  50032. var graphic = __webpack_require__(18);
  50033. var viewHelper = __webpack_require__(305);
  50034. var matrix = __webpack_require__(11);
  50035. var AxisBuilder = __webpack_require__(135);
  50036. var AxisView = __webpack_require__(136);
  50037. var PolarAxisPointer = BaseAxisPointer.extend({
  50038. /**
  50039. * @override
  50040. */
  50041. makeElOption: function (elOption, value, axisModel, axisPointerModel, api) {
  50042. var axis = axisModel.axis;
  50043. if (axis.dim === 'angle') {
  50044. this.animationThreshold = Math.PI / 18;
  50045. }
  50046. var polar = axis.polar;
  50047. var otherAxis = polar.getOtherAxis(axis);
  50048. var otherExtent = otherAxis.getExtent();
  50049. var coordValue;
  50050. coordValue = axis['dataTo' + formatUtil.capitalFirst(axis.dim)](value);
  50051. var axisPointerType = axisPointerModel.get('type');
  50052. if (axisPointerType && axisPointerType !== 'none') {
  50053. var elStyle = viewHelper.buildElStyle(axisPointerModel);
  50054. var pointerOption = pointerShapeBuilder[axisPointerType](
  50055. axis, polar, coordValue, otherExtent, elStyle
  50056. );
  50057. pointerOption.style = elStyle;
  50058. elOption.graphicKey = pointerOption.type;
  50059. elOption.pointer = pointerOption;
  50060. }
  50061. var labelMargin = axisPointerModel.get('label.margin');
  50062. var labelPos = getLabelPosition(value, axisModel, axisPointerModel, polar, labelMargin);
  50063. viewHelper.buildLabelElOption(elOption, axisModel, axisPointerModel, api, labelPos);
  50064. }
  50065. // Do not support handle, utill any user requires it.
  50066. });
  50067. function getLabelPosition(value, axisModel, axisPointerModel, polar, labelMargin) {
  50068. var axis = axisModel.axis;
  50069. var coord = axis.dataToCoord(value);
  50070. var axisAngle = polar.getAngleAxis().getExtent()[0];
  50071. axisAngle = axisAngle / 180 * Math.PI;
  50072. var radiusExtent = polar.getRadiusAxis().getExtent();
  50073. var position;
  50074. var align;
  50075. var verticalAlign;
  50076. if (axis.dim === 'radius') {
  50077. var transform = matrix.create();
  50078. matrix.rotate(transform, transform, axisAngle);
  50079. matrix.translate(transform, transform, [polar.cx, polar.cy]);
  50080. position = graphic.applyTransform([coord, -labelMargin], transform);
  50081. var labelRotation = axisModel.getModel('axisLabel').get('rotate') || 0;
  50082. var labelLayout = AxisBuilder.innerTextLayout(
  50083. axisAngle, labelRotation * Math.PI / 180, -1
  50084. );
  50085. align = labelLayout.textAlign;
  50086. verticalAlign = labelLayout.textVerticalAlign;
  50087. }
  50088. else { // angle axis
  50089. var r = radiusExtent[1];
  50090. position = polar.coordToPoint([r + labelMargin, coord]);
  50091. var cx = polar.cx;
  50092. var cy = polar.cy;
  50093. align = Math.abs(position[0] - cx) / r < 0.3
  50094. ? 'center' : (position[0] > cx ? 'left' : 'right');
  50095. verticalAlign = Math.abs(position[1] - cy) / r < 0.3
  50096. ? 'middle' : (position[1] > cy ? 'top' : 'bottom');
  50097. }
  50098. return {
  50099. position: position,
  50100. align: align,
  50101. verticalAlign: verticalAlign
  50102. };
  50103. }
  50104. var pointerShapeBuilder = {
  50105. line: function (axis, polar, coordValue, otherExtent, elStyle) {
  50106. return axis.dim === 'angle'
  50107. ? {
  50108. type: 'Line',
  50109. shape: viewHelper.makeLineShape(
  50110. polar.coordToPoint([otherExtent[0], coordValue]),
  50111. polar.coordToPoint([otherExtent[1], coordValue])
  50112. )
  50113. }
  50114. : {
  50115. type: 'Circle',
  50116. shape: {
  50117. cx: polar.cx,
  50118. cy: polar.cy,
  50119. r: coordValue
  50120. }
  50121. };
  50122. },
  50123. shadow: function (axis, polar, coordValue, otherExtent, elStyle) {
  50124. var bandWidth = axis.getBandWidth();
  50125. var radian = Math.PI / 180;
  50126. return axis.dim === 'angle'
  50127. ? {
  50128. type: 'Sector',
  50129. shape: viewHelper.makeSectorShape(
  50130. polar.cx, polar.cy,
  50131. otherExtent[0], otherExtent[1],
  50132. // In ECharts y is negative if angle is positive
  50133. (-coordValue - bandWidth / 2) * radian,
  50134. (-coordValue + bandWidth / 2) * radian
  50135. )
  50136. }
  50137. : {
  50138. type: 'Sector',
  50139. shape: viewHelper.makeSectorShape(
  50140. polar.cx, polar.cy,
  50141. coordValue - bandWidth / 2,
  50142. coordValue + bandWidth / 2,
  50143. 0, Math.PI * 2
  50144. )
  50145. };
  50146. }
  50147. };
  50148. AxisView.registerAxisPointerClass('PolarAxisPointer', PolarAxisPointer);
  50149. module.exports = PolarAxisPointer;
  50150. /***/ },
  50151. /* 342 */
  50152. /***/ function(module, exports, __webpack_require__) {
  50153. 'use strict';
  50154. var zrUtil = __webpack_require__(4);
  50155. var parsePercent = __webpack_require__(7).parsePercent;
  50156. function getSeriesStackId(seriesModel) {
  50157. return seriesModel.get('stack')
  50158. || '__ec_stack_' + seriesModel.seriesIndex;
  50159. }
  50160. function getAxisKey(axis) {
  50161. return axis.dim;
  50162. }
  50163. /**
  50164. * @param {string} seriesType
  50165. * @param {module:echarts/model/Global} ecModel
  50166. * @param {module:echarts/ExtensionAPI} api
  50167. */
  50168. function barLayoutPolar(seriesType, ecModel, api) {
  50169. var width = api.getWidth();
  50170. var height = api.getHeight();
  50171. var lastStackCoords = {};
  50172. var lastStackCoordsOrigin = {};
  50173. var barWidthAndOffset = calRadialBar(
  50174. zrUtil.filter(
  50175. ecModel.getSeriesByType(seriesType),
  50176. function (seriesModel) {
  50177. return !ecModel.isSeriesFiltered(seriesModel)
  50178. && seriesModel.coordinateSystem
  50179. && seriesModel.coordinateSystem.type === 'polar';
  50180. }
  50181. )
  50182. );
  50183. ecModel.eachSeriesByType(seriesType, function (seriesModel) {
  50184. // Check series coordinate, do layout for polar only
  50185. if (seriesModel.coordinateSystem.type !== 'polar') {
  50186. return;
  50187. }
  50188. var data = seriesModel.getData();
  50189. var polar = seriesModel.coordinateSystem;
  50190. var angleAxis = polar.getAngleAxis();
  50191. var baseAxis = polar.getBaseAxis();
  50192. var stackId = getSeriesStackId(seriesModel);
  50193. var columnLayoutInfo
  50194. = barWidthAndOffset[getAxisKey(baseAxis)][stackId];
  50195. var columnOffset = columnLayoutInfo.offset;
  50196. var columnWidth = columnLayoutInfo.width;
  50197. var valueAxis = polar.getOtherAxis(baseAxis);
  50198. var center = seriesModel.get('center') || ['50%', '50%'];
  50199. var cx = parsePercent(center[0], width);
  50200. var cy = parsePercent(center[1], height);
  50201. var barMinHeight = seriesModel.get('barMinHeight') || 0;
  50202. var barMinAngle = seriesModel.get('barMinAngle') || 0;
  50203. var valueAxisStart = valueAxis.getExtent()[0];
  50204. var valueMax = valueAxis.model.get('max');
  50205. var valueMin = valueAxis.model.get('min');
  50206. var coords = polar.dataToPoints(data);
  50207. lastStackCoords[stackId] = lastStackCoords[stackId] || [];
  50208. lastStackCoordsOrigin[stackId] = lastStackCoordsOrigin[stackId] || []; // Fix #4243
  50209. data.each(valueAxis.dim, function (value, idx) {
  50210. if (isNaN(value)) {
  50211. return;
  50212. }
  50213. if (!lastStackCoords[stackId][idx]) {
  50214. lastStackCoords[stackId][idx] = {
  50215. p: valueAxisStart, // Positive stack
  50216. n: valueAxisStart // Negative stack
  50217. };
  50218. lastStackCoordsOrigin[stackId][idx] = {
  50219. p: valueAxisStart, // Positive stack
  50220. n: valueAxisStart // Negative stack
  50221. };
  50222. }
  50223. var sign = value >= 0 ? 'p' : 'n';
  50224. var coord = polar.pointToCoord(coords[idx]);
  50225. var lastCoordOrigin = lastStackCoordsOrigin[stackId][idx][sign];
  50226. var r0;
  50227. var r;
  50228. var startAngle;
  50229. var endAngle;
  50230. if (valueAxis.dim === 'radius') {
  50231. // radial sector
  50232. r0 = lastCoordOrigin;
  50233. r = coord[0];
  50234. startAngle = (-coord[1] + columnOffset) * Math.PI / 180;
  50235. endAngle = startAngle + columnWidth * Math.PI / 180;
  50236. if (Math.abs(r) < barMinHeight) {
  50237. r = r0 + (r < 0 ? -1 : 1) * barMinHeight;
  50238. }
  50239. lastStackCoordsOrigin[stackId][idx][sign] = r;
  50240. }
  50241. else {
  50242. // tangential sector
  50243. r0 = coord[0] + columnOffset;
  50244. r = r0 + columnWidth;
  50245. // clamp data if min or max is defined for valueAxis
  50246. if (valueMax != null) {
  50247. value = Math.min(value, valueMax);
  50248. }
  50249. if (valueMin != null) {
  50250. value = Math.max(value, valueMin);
  50251. }
  50252. var angle = angleAxis.dataToAngle(value);
  50253. if (Math.abs(angle - lastCoordOrigin) < barMinAngle) {
  50254. angle = lastCoordOrigin - (value < 0 ? -1 : 1)
  50255. * barMinAngle;
  50256. }
  50257. startAngle = -lastCoordOrigin * Math.PI / 180;
  50258. endAngle = -angle * Math.PI / 180;
  50259. // if the previous stack is at the end of the ring,
  50260. // add a round to differentiate it from origin
  50261. var extent = angleAxis.getExtent();
  50262. var stackCoord = angle;
  50263. if (stackCoord === extent[0] && value > 0) {
  50264. stackCoord = extent[1];
  50265. }
  50266. else if (stackCoord === extent[1] && value < 0) {
  50267. stackCoord = extent[0];
  50268. }
  50269. lastStackCoordsOrigin[stackId][idx][sign] = stackCoord;
  50270. }
  50271. data.setItemLayout(idx, {
  50272. cx: cx,
  50273. cy: cy,
  50274. r0: r0,
  50275. r: r,
  50276. startAngle: startAngle,
  50277. endAngle: endAngle
  50278. });
  50279. }, true);
  50280. }, this);
  50281. }
  50282. /**
  50283. * Calculate bar width and offset for radial bar charts
  50284. */
  50285. function calRadialBar(barSeries, api) {
  50286. // Columns info on each category axis. Key is polar name
  50287. var columnsMap = {};
  50288. zrUtil.each(barSeries, function (seriesModel, idx) {
  50289. var data = seriesModel.getData();
  50290. var polar = seriesModel.coordinateSystem;
  50291. var baseAxis = polar.getBaseAxis();
  50292. var axisExtent = baseAxis.getExtent();
  50293. var bandWidth = baseAxis.type === 'category'
  50294. ? baseAxis.getBandWidth()
  50295. : (Math.abs(axisExtent[1] - axisExtent[0]) / data.count());
  50296. var columnsOnAxis = columnsMap[getAxisKey(baseAxis)] || {
  50297. bandWidth: bandWidth,
  50298. remainedWidth: bandWidth,
  50299. autoWidthCount: 0,
  50300. categoryGap: '20%',
  50301. gap: '30%',
  50302. stacks: {}
  50303. };
  50304. var stacks = columnsOnAxis.stacks;
  50305. columnsMap[getAxisKey(baseAxis)] = columnsOnAxis;
  50306. var stackId = getSeriesStackId(seriesModel);
  50307. if (!stacks[stackId]) {
  50308. columnsOnAxis.autoWidthCount++;
  50309. }
  50310. stacks[stackId] = stacks[stackId] || {
  50311. width: 0,
  50312. maxWidth: 0
  50313. };
  50314. var barWidth = parsePercent(
  50315. seriesModel.get('barWidth'),
  50316. bandWidth
  50317. );
  50318. var barMaxWidth = parsePercent(
  50319. seriesModel.get('barMaxWidth'),
  50320. bandWidth
  50321. );
  50322. var barGap = seriesModel.get('barGap');
  50323. var barCategoryGap = seriesModel.get('barCategoryGap');
  50324. if (barWidth && !stacks[stackId].width) {
  50325. barWidth = Math.min(columnsOnAxis.remainedWidth, barWidth);
  50326. stacks[stackId].width = barWidth;
  50327. columnsOnAxis.remainedWidth -= barWidth;
  50328. }
  50329. barMaxWidth && (stacks[stackId].maxWidth = barMaxWidth);
  50330. (barGap != null) && (columnsOnAxis.gap = barGap);
  50331. (barCategoryGap != null) && (columnsOnAxis.categoryGap = barCategoryGap);
  50332. });
  50333. var result = {};
  50334. zrUtil.each(columnsMap, function (columnsOnAxis, coordSysName) {
  50335. result[coordSysName] = {};
  50336. var stacks = columnsOnAxis.stacks;
  50337. var bandWidth = columnsOnAxis.bandWidth;
  50338. var categoryGap = parsePercent(columnsOnAxis.categoryGap, bandWidth);
  50339. var barGapPercent = parsePercent(columnsOnAxis.gap, 1);
  50340. var remainedWidth = columnsOnAxis.remainedWidth;
  50341. var autoWidthCount = columnsOnAxis.autoWidthCount;
  50342. var autoWidth = (remainedWidth - categoryGap)
  50343. / (autoWidthCount + (autoWidthCount - 1) * barGapPercent);
  50344. autoWidth = Math.max(autoWidth, 0);
  50345. // Find if any auto calculated bar exceeded maxBarWidth
  50346. zrUtil.each(stacks, function (column, stack) {
  50347. var maxWidth = column.maxWidth;
  50348. if (maxWidth && maxWidth < autoWidth) {
  50349. maxWidth = Math.min(maxWidth, remainedWidth);
  50350. if (column.width) {
  50351. maxWidth = Math.min(maxWidth, column.width);
  50352. }
  50353. remainedWidth -= maxWidth;
  50354. column.width = maxWidth;
  50355. autoWidthCount--;
  50356. }
  50357. });
  50358. // Recalculate width again
  50359. autoWidth = (remainedWidth - categoryGap)
  50360. / (autoWidthCount + (autoWidthCount - 1) * barGapPercent);
  50361. autoWidth = Math.max(autoWidth, 0);
  50362. var widthSum = 0;
  50363. var lastColumn;
  50364. zrUtil.each(stacks, function (column, idx) {
  50365. if (!column.width) {
  50366. column.width = autoWidth;
  50367. }
  50368. lastColumn = column;
  50369. widthSum += column.width * (1 + barGapPercent);
  50370. });
  50371. if (lastColumn) {
  50372. widthSum -= lastColumn.width * barGapPercent;
  50373. }
  50374. var offset = -widthSum / 2;
  50375. zrUtil.each(stacks, function (column, stackId) {
  50376. result[coordSysName][stackId] = result[coordSysName][stackId] || {
  50377. offset: offset,
  50378. width: column.width
  50379. };
  50380. offset += column.width * (1 + barGapPercent);
  50381. });
  50382. });
  50383. return result;
  50384. }
  50385. module.exports = barLayoutPolar;
  50386. /***/ },
  50387. /* 343 */
  50388. /***/ function(module, exports, __webpack_require__) {
  50389. __webpack_require__(344);
  50390. __webpack_require__(171);
  50391. __webpack_require__(345);
  50392. __webpack_require__(186);
  50393. var echarts = __webpack_require__(1);
  50394. var zrUtil = __webpack_require__(4);
  50395. function makeAction(method, actionInfo) {
  50396. actionInfo.update = 'updateView';
  50397. echarts.registerAction(actionInfo, function (payload, ecModel) {
  50398. var selected = {};
  50399. ecModel.eachComponent(
  50400. { mainType: 'geo', query: payload},
  50401. function (geoModel) {
  50402. geoModel[method](payload.name);
  50403. var geo = geoModel.coordinateSystem;
  50404. zrUtil.each(geo.regions, function (region) {
  50405. selected[region.name] = geoModel.isSelected(region.name) || false;
  50406. });
  50407. }
  50408. );
  50409. return {
  50410. selected: selected,
  50411. name: payload.name
  50412. };
  50413. });
  50414. }
  50415. makeAction('toggleSelected', {
  50416. type: 'geoToggleSelect',
  50417. event: 'geoselectchanged'
  50418. });
  50419. makeAction('select', {
  50420. type: 'geoSelect',
  50421. event: 'geoselected'
  50422. });
  50423. makeAction('unSelect', {
  50424. type: 'geoUnSelect',
  50425. event: 'geounselected'
  50426. });
  50427. /***/ },
  50428. /* 344 */
  50429. /***/ function(module, exports, __webpack_require__) {
  50430. 'use strict';
  50431. var modelUtil = __webpack_require__(5);
  50432. var ComponentModel = __webpack_require__(69);
  50433. var Model = __webpack_require__(12);
  50434. var zrUtil = __webpack_require__(4);
  50435. var selectableMixin = __webpack_require__(148);
  50436. var geoCreator = __webpack_require__(171);
  50437. var GeoModel = ComponentModel.extend({
  50438. type: 'geo',
  50439. /**
  50440. * @type {module:echarts/coord/geo/Geo}
  50441. */
  50442. coordinateSystem: null,
  50443. layoutMode: 'box',
  50444. init: function (option) {
  50445. ComponentModel.prototype.init.apply(this, arguments);
  50446. // Default label emphasis `position` and `show`
  50447. modelUtil.defaultEmphasis(
  50448. option.label, ['position', 'show', 'textStyle', 'distance', 'formatter']
  50449. );
  50450. },
  50451. optionUpdated: function () {
  50452. var option = this.option;
  50453. var self = this;
  50454. option.regions = geoCreator.getFilledRegions(option.regions, option.map);
  50455. this._optionModelMap = zrUtil.reduce(option.regions || [], function (optionModelMap, regionOpt) {
  50456. if (regionOpt.name) {
  50457. optionModelMap.set(regionOpt.name, new Model(regionOpt, self));
  50458. }
  50459. return optionModelMap;
  50460. }, zrUtil.createHashMap());
  50461. this.updateSelectedMap(option.regions);
  50462. },
  50463. defaultOption: {
  50464. zlevel: 0,
  50465. z: 0,
  50466. show: true,
  50467. left: 'center',
  50468. top: 'center',
  50469. // width:,
  50470. // height:,
  50471. // right
  50472. // bottom
  50473. // Aspect is width / height. Inited to be geoJson bbox aspect
  50474. // This parameter is used for scale this aspect
  50475. aspectScale: 0.75,
  50476. ///// Layout with center and size
  50477. // If you wan't to put map in a fixed size box with right aspect ratio
  50478. // This two properties may more conveninet
  50479. // layoutCenter: [50%, 50%]
  50480. // layoutSize: 100
  50481. silent: false,
  50482. // Map type
  50483. map: '',
  50484. // Define left-top, right-bottom coords to control view
  50485. // For example, [ [180, 90], [-180, -90] ]
  50486. boundingCoords: null,
  50487. // Default on center of map
  50488. center: null,
  50489. zoom: 1,
  50490. scaleLimit: null,
  50491. // selectedMode: false
  50492. label: {
  50493. normal: {
  50494. show: false,
  50495. textStyle: {
  50496. color: '#000'
  50497. }
  50498. },
  50499. emphasis: {
  50500. show: true,
  50501. textStyle: {
  50502. color: 'rgb(100,0,0)'
  50503. }
  50504. }
  50505. },
  50506. itemStyle: {
  50507. normal: {
  50508. // color: 各异,
  50509. borderWidth: 0.5,
  50510. borderColor: '#444',
  50511. color: '#eee'
  50512. },
  50513. emphasis: { // 也是选中样式
  50514. color: 'rgba(255,215,0,0.8)'
  50515. }
  50516. },
  50517. regions: []
  50518. },
  50519. /**
  50520. * Get model of region
  50521. * @param {string} name
  50522. * @return {module:echarts/model/Model}
  50523. */
  50524. getRegionModel: function (name) {
  50525. return this._optionModelMap.get(name) || new Model(null, this, this.ecModel);
  50526. },
  50527. /**
  50528. * Format label
  50529. * @param {string} name Region name
  50530. * @param {string} [status='normal'] 'normal' or 'emphasis'
  50531. * @return {string}
  50532. */
  50533. getFormattedLabel: function (name, status) {
  50534. var regionModel = this.getRegionModel(name);
  50535. var formatter = regionModel.get('label.' + status + '.formatter');
  50536. var params = {
  50537. name: name
  50538. };
  50539. if (typeof formatter === 'function') {
  50540. params.status = status;
  50541. return formatter(params);
  50542. }
  50543. else if (typeof formatter === 'string') {
  50544. var serName = params.seriesName;
  50545. return formatter.replace('{a}', serName != null ? serName : '');
  50546. }
  50547. },
  50548. setZoom: function (zoom) {
  50549. this.option.zoom = zoom;
  50550. },
  50551. setCenter: function (center) {
  50552. this.option.center = center;
  50553. }
  50554. });
  50555. zrUtil.mixin(GeoModel, selectableMixin);
  50556. module.exports = GeoModel;
  50557. /***/ },
  50558. /* 345 */
  50559. /***/ function(module, exports, __webpack_require__) {
  50560. 'use strict';
  50561. var MapDraw = __webpack_require__(181);
  50562. module.exports = __webpack_require__(1).extendComponentView({
  50563. type: 'geo',
  50564. init: function (ecModel, api) {
  50565. var mapDraw = new MapDraw(api, true);
  50566. this._mapDraw = mapDraw;
  50567. this.group.add(mapDraw.group);
  50568. },
  50569. render: function (geoModel, ecModel, api, payload) {
  50570. // Not render if it is an toggleSelect action from self
  50571. if (payload && payload.type === 'geoToggleSelect'
  50572. && payload.from === this.uid
  50573. ) {
  50574. return;
  50575. }
  50576. var mapDraw = this._mapDraw;
  50577. if (geoModel.get('show')) {
  50578. mapDraw.draw(geoModel, ecModel, api, this, payload);
  50579. }
  50580. else {
  50581. this._mapDraw.group.removeAll();
  50582. }
  50583. this.group.silent = geoModel.get('silent');
  50584. },
  50585. dispose: function () {
  50586. this._mapDraw && this._mapDraw.remove();
  50587. }
  50588. });
  50589. /***/ },
  50590. /* 346 */
  50591. /***/ function(module, exports, __webpack_require__) {
  50592. /**
  50593. * Brush component entry
  50594. */
  50595. __webpack_require__(1).registerPreprocessor(
  50596. __webpack_require__(347)
  50597. );
  50598. __webpack_require__(348);
  50599. __webpack_require__(352);
  50600. __webpack_require__(353);
  50601. __webpack_require__(354);
  50602. __webpack_require__(355);
  50603. /***/ },
  50604. /* 347 */
  50605. /***/ function(module, exports, __webpack_require__) {
  50606. /**
  50607. * @file brush preprocessor
  50608. */
  50609. var zrUtil = __webpack_require__(4);
  50610. var DEFAULT_TOOLBOX_BTNS = ['rect', 'polygon', 'keep', 'clear'];
  50611. module.exports = function (option, isNew) {
  50612. var brushComponents = option && option.brush;
  50613. if (!zrUtil.isArray(brushComponents)) {
  50614. brushComponents = brushComponents ? [brushComponents] : [];
  50615. }
  50616. if (!brushComponents.length) {
  50617. return;
  50618. }
  50619. var brushComponentSpecifiedBtns = [];
  50620. zrUtil.each(brushComponents, function (brushOpt) {
  50621. var tbs = brushOpt.hasOwnProperty('toolbox')
  50622. ? brushOpt.toolbox : [];
  50623. if (tbs instanceof Array) {
  50624. brushComponentSpecifiedBtns = brushComponentSpecifiedBtns.concat(tbs);
  50625. }
  50626. });
  50627. var toolbox = option && option.toolbox;
  50628. if (zrUtil.isArray(toolbox)) {
  50629. toolbox = toolbox[0];
  50630. }
  50631. if (!toolbox) {
  50632. toolbox = {feature: {}};
  50633. option.toolbox = [toolbox];
  50634. }
  50635. var toolboxFeature = (toolbox.feature || (toolbox.feature = {}));
  50636. var toolboxBrush = toolboxFeature.brush || (toolboxFeature.brush = {});
  50637. var brushTypes = toolboxBrush.type || (toolboxBrush.type = []);
  50638. brushTypes.push.apply(brushTypes, brushComponentSpecifiedBtns);
  50639. removeDuplicate(brushTypes);
  50640. if (isNew && !brushTypes.length) {
  50641. brushTypes.push.apply(brushTypes, DEFAULT_TOOLBOX_BTNS);
  50642. }
  50643. };
  50644. function removeDuplicate(arr) {
  50645. var map = {};
  50646. zrUtil.each(arr, function (val) {
  50647. map[val] = 1;
  50648. });
  50649. arr.length = 0;
  50650. zrUtil.each(map, function (flag, val) {
  50651. arr.push(val);
  50652. });
  50653. }
  50654. /***/ },
  50655. /* 348 */
  50656. /***/ function(module, exports, __webpack_require__) {
  50657. /**
  50658. * @file Brush visual coding.
  50659. */
  50660. var echarts = __webpack_require__(1);
  50661. var visualSolution = __webpack_require__(349);
  50662. var zrUtil = __webpack_require__(4);
  50663. var BoundingRect = __webpack_require__(9);
  50664. var selector = __webpack_require__(350);
  50665. var throttle = __webpack_require__(81);
  50666. var BrushTargetManager = __webpack_require__(351);
  50667. var STATE_LIST = ['inBrush', 'outOfBrush'];
  50668. var DISPATCH_METHOD = '__ecBrushSelect';
  50669. var DISPATCH_FLAG = '__ecInBrushSelectEvent';
  50670. var PRIORITY_BRUSH = echarts.PRIORITY.VISUAL.BRUSH;
  50671. /**
  50672. * Layout for visual, the priority higher than other layout, and before brush visual.
  50673. */
  50674. echarts.registerLayout(PRIORITY_BRUSH, function (ecModel, api, payload) {
  50675. ecModel.eachComponent({mainType: 'brush'}, function (brushModel) {
  50676. payload && payload.type === 'takeGlobalCursor' && brushModel.setBrushOption(
  50677. payload.key === 'brush' ? payload.brushOption : {brushType: false}
  50678. );
  50679. var brushTargetManager = brushModel.brushTargetManager = new BrushTargetManager(brushModel.option, ecModel);
  50680. brushTargetManager.setInputRanges(brushModel.areas, ecModel);
  50681. });
  50682. });
  50683. /**
  50684. * Register the visual encoding if this modules required.
  50685. */
  50686. echarts.registerVisual(PRIORITY_BRUSH, function (ecModel, api, payload) {
  50687. var brushSelected = [];
  50688. var throttleType;
  50689. var throttleDelay;
  50690. ecModel.eachComponent({mainType: 'brush'}, function (brushModel, brushIndex) {
  50691. var thisBrushSelected = {
  50692. brushId: brushModel.id,
  50693. brushIndex: brushIndex,
  50694. brushName: brushModel.name,
  50695. areas: zrUtil.clone(brushModel.areas),
  50696. selected: []
  50697. };
  50698. // Every brush component exists in event params, convenient
  50699. // for user to find by index.
  50700. brushSelected.push(thisBrushSelected);
  50701. var brushOption = brushModel.option;
  50702. var brushLink = brushOption.brushLink;
  50703. var linkedSeriesMap = [];
  50704. var selectedDataIndexForLink = [];
  50705. var rangeInfoBySeries = [];
  50706. var hasBrushExists = 0;
  50707. if (!brushIndex) { // Only the first throttle setting works.
  50708. throttleType = brushOption.throttleType;
  50709. throttleDelay = brushOption.throttleDelay;
  50710. }
  50711. // Add boundingRect and selectors to range.
  50712. var areas = zrUtil.map(brushModel.areas, function (area) {
  50713. return bindSelector(
  50714. zrUtil.defaults(
  50715. {boundingRect: boundingRectBuilders[area.brushType](area)},
  50716. area
  50717. )
  50718. );
  50719. });
  50720. var visualMappings = visualSolution.createVisualMappings(
  50721. brushModel.option, STATE_LIST, function (mappingOption) {
  50722. mappingOption.mappingMethod = 'fixed';
  50723. }
  50724. );
  50725. zrUtil.isArray(brushLink) && zrUtil.each(brushLink, function (seriesIndex) {
  50726. linkedSeriesMap[seriesIndex] = 1;
  50727. });
  50728. function linkOthers(seriesIndex) {
  50729. return brushLink === 'all' || linkedSeriesMap[seriesIndex];
  50730. }
  50731. // If no supported brush or no brush on the series,
  50732. // all visuals should be in original state.
  50733. function brushed(rangeInfoList) {
  50734. return !!rangeInfoList.length;
  50735. }
  50736. /**
  50737. * Logic for each series: (If the logic has to be modified one day, do it carefully!)
  50738. *
  50739. * ( brushed ┬ && ┬hasBrushExist ┬ && linkOthers ) => StepA: ┬record, ┬ StepB: ┬visualByRecord.
  50740. * !brushed┘ ├hasBrushExist ┤ └nothing,┘ ├visualByRecord.
  50741. * └!hasBrushExist┘ └nothing.
  50742. * ( !brushed && ┬hasBrushExist ┬ && linkOthers ) => StepA: nothing, StepB: ┬visualByRecord.
  50743. * └!hasBrushExist┘ └nothing.
  50744. * ( brushed ┬ && !linkOthers ) => StepA: nothing, StepB: ┬visualByCheck.
  50745. * !brushed┘ └nothing.
  50746. * ( !brushed && !linkOthers ) => StepA: nothing, StepB: nothing.
  50747. */
  50748. // Step A
  50749. ecModel.eachSeries(function (seriesModel, seriesIndex) {
  50750. var rangeInfoList = rangeInfoBySeries[seriesIndex] = [];
  50751. seriesModel.subType === 'parallel'
  50752. ? stepAParallel(seriesModel, seriesIndex, rangeInfoList)
  50753. : stepAOthers(seriesModel, seriesIndex, rangeInfoList);
  50754. });
  50755. function stepAParallel(seriesModel, seriesIndex) {
  50756. var coordSys = seriesModel.coordinateSystem;
  50757. hasBrushExists |= coordSys.hasAxisBrushed();
  50758. linkOthers(seriesIndex) && coordSys.eachActiveState(
  50759. seriesModel.getData(),
  50760. function (activeState, dataIndex) {
  50761. activeState === 'active' && (selectedDataIndexForLink[dataIndex] = 1);
  50762. }
  50763. );
  50764. }
  50765. function stepAOthers(seriesModel, seriesIndex, rangeInfoList) {
  50766. var selectorsByBrushType = getSelectorsByBrushType(seriesModel);
  50767. if (!selectorsByBrushType || brushModelNotControll(brushModel, seriesIndex)) {
  50768. return;
  50769. }
  50770. zrUtil.each(areas, function (area) {
  50771. selectorsByBrushType[area.brushType]
  50772. && brushModel.brushTargetManager.controlSeries(area, seriesModel, ecModel)
  50773. && rangeInfoList.push(area);
  50774. hasBrushExists |= brushed(rangeInfoList);
  50775. });
  50776. if (linkOthers(seriesIndex) && brushed(rangeInfoList)) {
  50777. var data = seriesModel.getData();
  50778. data.each(function (dataIndex) {
  50779. if (checkInRange(selectorsByBrushType, rangeInfoList, data, dataIndex)) {
  50780. selectedDataIndexForLink[dataIndex] = 1;
  50781. }
  50782. });
  50783. }
  50784. }
  50785. // Step B
  50786. ecModel.eachSeries(function (seriesModel, seriesIndex) {
  50787. var seriesBrushSelected = {
  50788. seriesId: seriesModel.id,
  50789. seriesIndex: seriesIndex,
  50790. seriesName: seriesModel.name,
  50791. dataIndex: []
  50792. };
  50793. // Every series exists in event params, convenient
  50794. // for user to find series by seriesIndex.
  50795. thisBrushSelected.selected.push(seriesBrushSelected);
  50796. var selectorsByBrushType = getSelectorsByBrushType(seriesModel);
  50797. var rangeInfoList = rangeInfoBySeries[seriesIndex];
  50798. var data = seriesModel.getData();
  50799. var getValueState = linkOthers(seriesIndex)
  50800. ? function (dataIndex) {
  50801. return selectedDataIndexForLink[dataIndex]
  50802. ? (seriesBrushSelected.dataIndex.push(data.getRawIndex(dataIndex)), 'inBrush')
  50803. : 'outOfBrush';
  50804. }
  50805. : function (dataIndex) {
  50806. return checkInRange(selectorsByBrushType, rangeInfoList, data, dataIndex)
  50807. ? (seriesBrushSelected.dataIndex.push(data.getRawIndex(dataIndex)), 'inBrush')
  50808. : 'outOfBrush';
  50809. };
  50810. // If no supported brush or no brush, all visuals are in original state.
  50811. (linkOthers(seriesIndex) ? hasBrushExists : brushed(rangeInfoList))
  50812. && visualSolution.applyVisual(
  50813. STATE_LIST, visualMappings, data, getValueState
  50814. );
  50815. });
  50816. });
  50817. dispatchAction(api, throttleType, throttleDelay, brushSelected, payload);
  50818. });
  50819. function dispatchAction(api, throttleType, throttleDelay, brushSelected, payload) {
  50820. // This event will not be triggered when `setOpion`, otherwise dead lock may
  50821. // triggered when do `setOption` in event listener, which we do not find
  50822. // satisfactory way to solve yet. Some considered resolutions:
  50823. // (a) Diff with prevoius selected data ant only trigger event when changed.
  50824. // But store previous data and diff precisely (i.e., not only by dataIndex, but
  50825. // also detect value changes in selected data) might bring complexity or fragility.
  50826. // (b) Use spectial param like `silent` to suppress event triggering.
  50827. // But such kind of volatile param may be weird in `setOption`.
  50828. if (!payload) {
  50829. return;
  50830. }
  50831. var zr = api.getZr();
  50832. if (zr[DISPATCH_FLAG]) {
  50833. return;
  50834. }
  50835. if (!zr[DISPATCH_METHOD]) {
  50836. zr[DISPATCH_METHOD] = doDispatch;
  50837. }
  50838. var fn = throttle.createOrUpdate(zr, DISPATCH_METHOD, throttleDelay, throttleType);
  50839. fn(api, brushSelected);
  50840. }
  50841. function doDispatch(api, brushSelected) {
  50842. if (!api.isDisposed()) {
  50843. var zr = api.getZr();
  50844. zr[DISPATCH_FLAG] = true;
  50845. api.dispatchAction({
  50846. type: 'brushSelect',
  50847. batch: brushSelected
  50848. });
  50849. zr[DISPATCH_FLAG] = false;
  50850. }
  50851. }
  50852. function checkInRange(selectorsByBrushType, rangeInfoList, data, dataIndex) {
  50853. for (var i = 0, len = rangeInfoList.length; i < len; i++) {
  50854. var area = rangeInfoList[i];
  50855. if (selectorsByBrushType[area.brushType](
  50856. dataIndex, data, area.selectors, area
  50857. )) {
  50858. return true;
  50859. }
  50860. }
  50861. }
  50862. function getSelectorsByBrushType(seriesModel) {
  50863. var brushSelector = seriesModel.brushSelector;
  50864. if (zrUtil.isString(brushSelector)) {
  50865. var sels = [];
  50866. zrUtil.each(selector, function (selectorsByElementType, brushType) {
  50867. sels[brushType] = function (dataIndex, data, selectors, area) {
  50868. var itemLayout = data.getItemLayout(dataIndex);
  50869. return selectorsByElementType[brushSelector](itemLayout, selectors, area);
  50870. };
  50871. });
  50872. return sels;
  50873. }
  50874. else if (zrUtil.isFunction(brushSelector)) {
  50875. var bSelector = {};
  50876. zrUtil.each(selector, function (sel, brushType) {
  50877. bSelector[brushType] = brushSelector;
  50878. });
  50879. return bSelector;
  50880. }
  50881. return brushSelector;
  50882. }
  50883. function brushModelNotControll(brushModel, seriesIndex) {
  50884. var seriesIndices = brushModel.option.seriesIndex;
  50885. return seriesIndices != null
  50886. && seriesIndices !== 'all'
  50887. && (
  50888. zrUtil.isArray(seriesIndices)
  50889. ? zrUtil.indexOf(seriesIndices, seriesIndex) < 0
  50890. : seriesIndex !== seriesIndices
  50891. );
  50892. }
  50893. function bindSelector(area) {
  50894. var selectors = area.selectors = {};
  50895. zrUtil.each(selector[area.brushType], function (selFn, elType) {
  50896. // Do not use function binding or curry for performance.
  50897. selectors[elType] = function (itemLayout) {
  50898. return selFn(itemLayout, selectors, area);
  50899. };
  50900. });
  50901. return area;
  50902. }
  50903. var boundingRectBuilders = {
  50904. lineX: zrUtil.noop,
  50905. lineY: zrUtil.noop,
  50906. rect: function (area) {
  50907. return getBoundingRectFromMinMax(area.range);
  50908. },
  50909. polygon: function (area) {
  50910. var minMax;
  50911. var range = area.range;
  50912. for (var i = 0, len = range.length; i < len; i++) {
  50913. minMax = minMax || [[Infinity, -Infinity], [Infinity, -Infinity]];
  50914. var rg = range[i];
  50915. rg[0] < minMax[0][0] && (minMax[0][0] = rg[0]);
  50916. rg[0] > minMax[0][1] && (minMax[0][1] = rg[0]);
  50917. rg[1] < minMax[1][0] && (minMax[1][0] = rg[1]);
  50918. rg[1] > minMax[1][1] && (minMax[1][1] = rg[1]);
  50919. }
  50920. return minMax && getBoundingRectFromMinMax(minMax);
  50921. }
  50922. };
  50923. function getBoundingRectFromMinMax(minMax) {
  50924. return new BoundingRect(
  50925. minMax[0][0],
  50926. minMax[1][0],
  50927. minMax[0][1] - minMax[0][0],
  50928. minMax[1][1] - minMax[1][0]
  50929. );
  50930. }
  50931. /***/ },
  50932. /* 349 */
  50933. /***/ function(module, exports, __webpack_require__) {
  50934. /**
  50935. * @file Visual solution, for consistent option specification.
  50936. */
  50937. var zrUtil = __webpack_require__(4);
  50938. var VisualMapping = __webpack_require__(202);
  50939. var each = zrUtil.each;
  50940. function hasKeys(obj) {
  50941. if (obj) {
  50942. for (var name in obj){
  50943. if (obj.hasOwnProperty(name)) {
  50944. return true;
  50945. }
  50946. }
  50947. }
  50948. }
  50949. var visualSolution = {
  50950. /**
  50951. * @param {Object} option
  50952. * @param {Array.<string>} stateList
  50953. * @param {Function} [supplementVisualOption]
  50954. * @return {Object} visualMappings <state, <visualType, module:echarts/visual/VisualMapping>>
  50955. */
  50956. createVisualMappings: function (option, stateList, supplementVisualOption) {
  50957. var visualMappings = {};
  50958. each(stateList, function (state) {
  50959. var mappings = visualMappings[state] = createMappings();
  50960. each(option[state], function (visualData, visualType) {
  50961. if (!VisualMapping.isValidType(visualType)) {
  50962. return;
  50963. }
  50964. var mappingOption = {
  50965. type: visualType,
  50966. visual: visualData
  50967. };
  50968. supplementVisualOption && supplementVisualOption(mappingOption, state);
  50969. mappings[visualType] = new VisualMapping(mappingOption);
  50970. // Prepare a alpha for opacity, for some case that opacity
  50971. // is not supported, such as rendering using gradient color.
  50972. if (visualType === 'opacity') {
  50973. mappingOption = zrUtil.clone(mappingOption);
  50974. mappingOption.type = 'colorAlpha';
  50975. mappings.__hidden.__alphaForOpacity = new VisualMapping(mappingOption);
  50976. }
  50977. });
  50978. });
  50979. return visualMappings;
  50980. function createMappings() {
  50981. var Creater = function () {};
  50982. // Make sure hidden fields will not be visited by
  50983. // object iteration (with hasOwnProperty checking).
  50984. Creater.prototype.__hidden = Creater.prototype;
  50985. var obj = new Creater();
  50986. return obj;
  50987. }
  50988. },
  50989. /**
  50990. * @param {Object} thisOption
  50991. * @param {Object} newOption
  50992. * @param {Array.<string>} keys
  50993. */
  50994. replaceVisualOption: function (thisOption, newOption, keys) {
  50995. // Visual attributes merge is not supported, otherwise it
  50996. // brings overcomplicated merge logic. See #2853. So if
  50997. // newOption has anyone of these keys, all of these keys
  50998. // will be reset. Otherwise, all keys remain.
  50999. var has;
  51000. zrUtil.each(keys, function (key) {
  51001. if (newOption.hasOwnProperty(key) && hasKeys(newOption[key])) {
  51002. has = true;
  51003. }
  51004. });
  51005. has && zrUtil.each(keys, function (key) {
  51006. if (newOption.hasOwnProperty(key) && hasKeys(newOption[key])) {
  51007. thisOption[key] = zrUtil.clone(newOption[key]);
  51008. }
  51009. else {
  51010. delete thisOption[key];
  51011. }
  51012. });
  51013. },
  51014. /**
  51015. * @param {Array.<string>} stateList
  51016. * @param {Object} visualMappings <state, Object.<visualType, module:echarts/visual/VisualMapping>>
  51017. * @param {module:echarts/data/List} list
  51018. * @param {Function} getValueState param: valueOrIndex, return: state.
  51019. * @param {object} [scope] Scope for getValueState
  51020. * @param {string} [dimension] Concrete dimension, if used.
  51021. */
  51022. applyVisual: function (stateList, visualMappings, data, getValueState, scope, dimension) {
  51023. var visualTypesMap = {};
  51024. zrUtil.each(stateList, function (state) {
  51025. var visualTypes = VisualMapping.prepareVisualTypes(visualMappings[state]);
  51026. visualTypesMap[state] = visualTypes;
  51027. });
  51028. var dataIndex;
  51029. function getVisual(key) {
  51030. return data.getItemVisual(dataIndex, key);
  51031. }
  51032. function setVisual(key, value) {
  51033. data.setItemVisual(dataIndex, key, value);
  51034. }
  51035. if (dimension == null) {
  51036. data.each(eachItem, true);
  51037. }
  51038. else {
  51039. data.each([dimension], eachItem, true);
  51040. }
  51041. function eachItem(valueOrIndex, index) {
  51042. dataIndex = dimension == null ? valueOrIndex : index;
  51043. var rawDataItem = data.getRawDataItem(dataIndex);
  51044. // Consider performance
  51045. if (rawDataItem && rawDataItem.visualMap === false) {
  51046. return;
  51047. }
  51048. var valueState = getValueState.call(scope, valueOrIndex);
  51049. var mappings = visualMappings[valueState];
  51050. var visualTypes = visualTypesMap[valueState];
  51051. for (var i = 0, len = visualTypes.length; i < len; i++) {
  51052. var type = visualTypes[i];
  51053. mappings[type] && mappings[type].applyVisual(
  51054. valueOrIndex, getVisual, setVisual
  51055. );
  51056. }
  51057. }
  51058. }
  51059. };
  51060. module.exports = visualSolution;
  51061. /***/ },
  51062. /* 350 */
  51063. /***/ function(module, exports, __webpack_require__) {
  51064. var polygonContain = __webpack_require__(175).contain;
  51065. var BoundingRect = __webpack_require__(9);
  51066. // Key of the first level is brushType: `line`, `rect`, `polygon`.
  51067. // Key of the second level is chart element type: `point`, `rect`.
  51068. // See moudule:echarts/component/helper/BrushController
  51069. // function param:
  51070. // {Object} itemLayout fetch from data.getItemLayout(dataIndex)
  51071. // {Object} selectors {point: selector, rect: selector, ...}
  51072. // {Object} area {range: [[], [], ..], boudingRect}
  51073. // function return:
  51074. // {boolean} Whether in the given brush.
  51075. var selector = {
  51076. lineX: getLineSelectors(0),
  51077. lineY: getLineSelectors(1),
  51078. rect: {
  51079. point: function (itemLayout, selectors, area) {
  51080. return area.boundingRect.contain(itemLayout[0], itemLayout[1]);
  51081. },
  51082. rect: function (itemLayout, selectors, area) {
  51083. return area.boundingRect.intersect(itemLayout);
  51084. }
  51085. },
  51086. polygon: {
  51087. point: function (itemLayout, selectors, area) {
  51088. return area.boundingRect.contain(itemLayout[0], itemLayout[1])
  51089. && polygonContain(area.range, itemLayout[0], itemLayout[1]);
  51090. },
  51091. rect: function (itemLayout, selectors, area) {
  51092. var points = area.range;
  51093. if (points.length <= 1) {
  51094. return false;
  51095. }
  51096. var x = itemLayout.x;
  51097. var y = itemLayout.y;
  51098. var width = itemLayout.width;
  51099. var height = itemLayout.height;
  51100. var p = points[0];
  51101. if (polygonContain(points, x, y)
  51102. || polygonContain(points, x + width, y)
  51103. || polygonContain(points, x, y + height)
  51104. || polygonContain(points, x + width, y + height)
  51105. || BoundingRect.create(itemLayout).contain(p[0], p[1])
  51106. || lineIntersectPolygon(x, y, x + width, y, points)
  51107. || lineIntersectPolygon(x, y, x, y + height, points)
  51108. || lineIntersectPolygon(x + width, y, x + width, y + height, points)
  51109. || lineIntersectPolygon(x, y + height, x + width, y + height, points)
  51110. ) {
  51111. return true;
  51112. }
  51113. }
  51114. }
  51115. };
  51116. function getLineSelectors(xyIndex) {
  51117. var xy = ['x', 'y'];
  51118. var wh = ['width', 'height'];
  51119. return {
  51120. point: function (itemLayout, selectors, area) {
  51121. var range = area.range;
  51122. var p = itemLayout[xyIndex];
  51123. return inLineRange(p, range);
  51124. },
  51125. rect: function (itemLayout, selectors, area) {
  51126. var range = area.range;
  51127. var layoutRange = [
  51128. itemLayout[xy[xyIndex]],
  51129. itemLayout[xy[xyIndex]] + itemLayout[wh[xyIndex]]
  51130. ];
  51131. layoutRange[1] < layoutRange[0] && layoutRange.reverse();
  51132. return inLineRange(layoutRange[0], range)
  51133. || inLineRange(layoutRange[1], range)
  51134. || inLineRange(range[0], layoutRange)
  51135. || inLineRange(range[1], layoutRange);
  51136. }
  51137. };
  51138. }
  51139. function inLineRange(p, range) {
  51140. return range[0] <= p && p <= range[1];
  51141. }
  51142. function lineIntersectPolygon(lx, ly, l2x, l2y, points) {
  51143. for (var i = 0, p2 = points[points.length - 1]; i < points.length; i++) {
  51144. var p = points[i];
  51145. if (lineIntersect(lx, ly, l2x, l2y, p[0], p[1], p2[0], p2[1])) {
  51146. return true;
  51147. }
  51148. p2 = p;
  51149. }
  51150. }
  51151. // Code from <http://blog.csdn.net/rickliuxiao/article/details/6259322> with some fix.
  51152. // See <https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection>
  51153. function lineIntersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y) {
  51154. var delta = determinant(a2x - a1x, b1x - b2x, a2y - a1y, b1y - b2y);
  51155. if (nearZero(delta)) { // parallel
  51156. return false;
  51157. }
  51158. var namenda = determinant(b1x - a1x, b1x - b2x, b1y - a1y, b1y - b2y) / delta;
  51159. if (namenda < 0 || namenda > 1) {
  51160. return false;
  51161. }
  51162. var miu = determinant(a2x - a1x, b1x - a1x, a2y - a1y, b1y - a1y) / delta;
  51163. if (miu < 0 || miu > 1) {
  51164. return false;
  51165. }
  51166. return true;
  51167. }
  51168. function nearZero(val) {
  51169. return val <= (1e-6) && val >= -(1e-6);
  51170. }
  51171. function determinant(v1, v2, v3, v4) {
  51172. return v1 * v4 - v2 * v3;
  51173. }
  51174. module.exports = selector;
  51175. /***/ },
  51176. /* 351 */
  51177. /***/ function(module, exports, __webpack_require__) {
  51178. var zrUtil = __webpack_require__(4);
  51179. var graphic = __webpack_require__(18);
  51180. var modelUtil = __webpack_require__(5);
  51181. var brushHelper = __webpack_require__(245);
  51182. var each = zrUtil.each;
  51183. var indexOf = zrUtil.indexOf;
  51184. var curry = zrUtil.curry;
  51185. var COORD_CONVERTS = ['dataToPoint', 'pointToData'];
  51186. // FIXME
  51187. // how to genarialize to more coordinate systems.
  51188. var INCLUDE_FINDER_MAIN_TYPES = [
  51189. 'grid', 'xAxis', 'yAxis', 'geo', 'graph',
  51190. 'polar', 'radiusAxis', 'angleAxis', 'bmap'
  51191. ];
  51192. /**
  51193. * [option in constructor]:
  51194. * {
  51195. * Index/Id/Name of geo, xAxis, yAxis, grid: See util/model#parseFinder.
  51196. * }
  51197. *
  51198. *
  51199. * [targetInfo]:
  51200. *
  51201. * There can be multiple axes in a single targetInfo. Consider the case
  51202. * of `grid` component, a targetInfo represents a grid which contains one or more
  51203. * cartesian and one or more axes. And consider the case of parallel system,
  51204. * which has multiple axes in a coordinate system.
  51205. * Can be {
  51206. * panelId: ...,
  51207. * coordSys: <a representitive cartesian in grid (first cartesian by default)>,
  51208. * coordSyses: all cartesians.
  51209. * gridModel: <grid component>
  51210. * xAxes: correspond to coordSyses on index
  51211. * yAxes: correspond to coordSyses on index
  51212. * }
  51213. * or {
  51214. * panelId: ...,
  51215. * coordSys: <geo coord sys>
  51216. * coordSyses: [<geo coord sys>]
  51217. * geoModel: <geo component>
  51218. * }
  51219. *
  51220. *
  51221. * [panelOpt]:
  51222. *
  51223. * Make from targetInfo. Input to BrushController.
  51224. * {
  51225. * panelId: ...,
  51226. * rect: ...
  51227. * }
  51228. *
  51229. *
  51230. * [area]:
  51231. *
  51232. * Generated by BrushController or user input.
  51233. * {
  51234. * panelId: Used to locate coordInfo directly. If user inpput, no panelId.
  51235. * brushType: determine how to convert to/from coord('rect' or 'polygon' or 'lineX/Y').
  51236. * Index/Id/Name of geo, xAxis, yAxis, grid: See util/model#parseFinder.
  51237. * range: pixel range.
  51238. * coordRange: representitive coord range (the first one of coordRanges).
  51239. * coordRanges: <Array> coord ranges, used in multiple cartesian in one grid.
  51240. * }
  51241. */
  51242. /**
  51243. * @param {Object} option contains Index/Id/Name of xAxis/yAxis/geo/grid
  51244. * Each can be {number|Array.<number>}. like: {xAxisIndex: [3, 4]}
  51245. * @param {module:echarts/model/Global} ecModel
  51246. * @param {Object} [opt]
  51247. * @param {Array.<string>} [opt.include] include coordinate system types.
  51248. */
  51249. function BrushTargetManager(option, ecModel, opt) {
  51250. /**
  51251. * @private
  51252. * @type {Array.<Object>}
  51253. */
  51254. var targetInfoList = this._targetInfoList = [];
  51255. var info = {};
  51256. var foundCpts = parseFinder(ecModel, option);
  51257. each(targetInfoBuilders, function (builder, type) {
  51258. if (!opt || !opt.include || indexOf(opt.include, type) >= 0) {
  51259. builder(foundCpts, targetInfoList, info);
  51260. }
  51261. });
  51262. }
  51263. var proto = BrushTargetManager.prototype;
  51264. proto.setOutputRanges = function (areas, ecModel) {
  51265. this.matchOutputRanges(areas, ecModel, function (area, coordRange, coordSys) {
  51266. (area.coordRanges || (area.coordRanges = [])).push(coordRange);
  51267. // area.coordRange is the first of area.coordRanges
  51268. if (!area.coordRange) {
  51269. area.coordRange = coordRange;
  51270. // In 'category' axis, coord to pixel is not reversible, so we can not
  51271. // rebuild range by coordRange accrately, which may bring trouble when
  51272. // brushing only one item. So we use __rangeOffset to rebuilding range
  51273. // by coordRange. And this it only used in brush component so it is no
  51274. // need to be adapted to coordRanges.
  51275. var result = coordConvert[area.brushType](0, coordSys, coordRange);
  51276. area.__rangeOffset = {
  51277. offset: diffProcessor[area.brushType](result.values, area.range, [1, 1]),
  51278. xyMinMax: result.xyMinMax
  51279. };
  51280. }
  51281. });
  51282. };
  51283. proto.matchOutputRanges = function (areas, ecModel, cb) {
  51284. each(areas, function (area) {
  51285. var targetInfo = this.findTargetInfo(area, ecModel);
  51286. if (targetInfo && targetInfo !== true) {
  51287. zrUtil.each(
  51288. targetInfo.coordSyses,
  51289. function (coordSys) {
  51290. var result = coordConvert[area.brushType](1, coordSys, area.range);
  51291. cb(area, result.values, coordSys, ecModel);
  51292. }
  51293. );
  51294. }
  51295. }, this);
  51296. };
  51297. proto.setInputRanges = function (areas, ecModel) {
  51298. each(areas, function (area) {
  51299. var targetInfo = this.findTargetInfo(area, ecModel);
  51300. if (true) {
  51301. zrUtil.assert(
  51302. !targetInfo || targetInfo === true || area.coordRange,
  51303. 'coordRange must be specified when coord index specified.'
  51304. );
  51305. zrUtil.assert(
  51306. !targetInfo || targetInfo !== true || area.range,
  51307. 'range must be specified in global brush.'
  51308. );
  51309. }
  51310. area.range = area.range || [];
  51311. // convert coordRange to global range and set panelId.
  51312. if (targetInfo && targetInfo !== true) {
  51313. area.panelId = targetInfo.panelId;
  51314. // (1) area.range shoule always be calculate from coordRange but does
  51315. // not keep its original value, for the sake of the dataZoom scenario,
  51316. // where area.coordRange remains unchanged but area.range may be changed.
  51317. // (2) Only support converting one coordRange to pixel range in brush
  51318. // component. So do not consider `coordRanges`.
  51319. // (3) About __rangeOffset, see comment above.
  51320. var result = coordConvert[area.brushType](0, targetInfo.coordSys, area.coordRange);
  51321. var rangeOffset = area.__rangeOffset;
  51322. area.range = rangeOffset
  51323. ? diffProcessor[area.brushType](
  51324. result.values,
  51325. rangeOffset.offset,
  51326. getScales(result.xyMinMax, rangeOffset.xyMinMax)
  51327. )
  51328. : result.values;
  51329. }
  51330. }, this);
  51331. };
  51332. proto.makePanelOpts = function (api, getDefaultBrushType) {
  51333. return zrUtil.map(this._targetInfoList, function (targetInfo) {
  51334. var rect = targetInfo.getPanelRect();
  51335. return {
  51336. panelId: targetInfo.panelId,
  51337. defaultBrushType: getDefaultBrushType && getDefaultBrushType(targetInfo),
  51338. clipPath: brushHelper.makeRectPanelClipPath(rect),
  51339. isTargetByCursor: brushHelper.makeRectIsTargetByCursor(
  51340. rect, api, targetInfo.coordSysModel
  51341. ),
  51342. getLinearBrushOtherExtent: brushHelper.makeLinearBrushOtherExtent(rect)
  51343. };
  51344. });
  51345. };
  51346. proto.controlSeries = function (area, seriesModel, ecModel) {
  51347. // Check whether area is bound in coord, and series do not belong to that coord.
  51348. // If do not do this check, some brush (like lineX) will controll all axes.
  51349. var targetInfo = this.findTargetInfo(area, ecModel);
  51350. return targetInfo === true || (
  51351. targetInfo && indexOf(targetInfo.coordSyses, seriesModel.coordinateSystem) >= 0
  51352. );
  51353. };
  51354. /**
  51355. * If return Object, a coord found.
  51356. * If reutrn true, global found.
  51357. * Otherwise nothing found.
  51358. *
  51359. * @param {Object} area
  51360. * @param {Array} targetInfoList
  51361. * @return {Obejct|boolean}
  51362. */
  51363. proto.findTargetInfo = function (area, ecModel) {
  51364. var targetInfoList = this._targetInfoList;
  51365. var foundCpts = parseFinder(ecModel, area);
  51366. for (var i = 0; i < targetInfoList.length; i++) {
  51367. var targetInfo = targetInfoList[i];
  51368. var areaPanelId = area.panelId;
  51369. if (areaPanelId) {
  51370. if (targetInfo.panelId === areaPanelId) {
  51371. return targetInfo;
  51372. }
  51373. }
  51374. else {
  51375. for (var i = 0; i < targetInfoMatchers.length; i++) {
  51376. if (targetInfoMatchers[i](foundCpts, targetInfo)) {
  51377. return targetInfo;
  51378. }
  51379. }
  51380. }
  51381. }
  51382. return true;
  51383. };
  51384. function formatMinMax(minMax) {
  51385. minMax[0] > minMax[1] && minMax.reverse();
  51386. return minMax;
  51387. }
  51388. function parseFinder(ecModel, option) {
  51389. return modelUtil.parseFinder(
  51390. ecModel, option, {includeMainTypes: INCLUDE_FINDER_MAIN_TYPES}
  51391. );
  51392. }
  51393. var targetInfoBuilders = {
  51394. grid: function (foundCpts, targetInfoList) {
  51395. var xAxisModels = foundCpts.xAxisModels;
  51396. var yAxisModels = foundCpts.yAxisModels;
  51397. var gridModels = foundCpts.gridModels;
  51398. // Remove duplicated.
  51399. var gridModelMap = zrUtil.createHashMap();
  51400. var xAxesHas = {};
  51401. var yAxesHas = {};
  51402. if (!xAxisModels && !yAxisModels && !gridModels) {
  51403. return;
  51404. }
  51405. each(xAxisModels, function (axisModel) {
  51406. var gridModel = axisModel.axis.grid.model;
  51407. gridModelMap.set(gridModel.id, gridModel);
  51408. xAxesHas[gridModel.id] = true;
  51409. });
  51410. each(yAxisModels, function (axisModel) {
  51411. var gridModel = axisModel.axis.grid.model;
  51412. gridModelMap.set(gridModel.id, gridModel);
  51413. yAxesHas[gridModel.id] = true;
  51414. });
  51415. each(gridModels, function (gridModel) {
  51416. gridModelMap.set(gridModel.id, gridModel);
  51417. xAxesHas[gridModel.id] = true;
  51418. yAxesHas[gridModel.id] = true;
  51419. });
  51420. gridModelMap.each(function (gridModel) {
  51421. var grid = gridModel.coordinateSystem;
  51422. var cartesians = [];
  51423. each(grid.getCartesians(), function (cartesian, index) {
  51424. if (indexOf(xAxisModels, cartesian.getAxis('x').model) >= 0
  51425. || indexOf(yAxisModels, cartesian.getAxis('y').model) >= 0
  51426. ) {
  51427. cartesians.push(cartesian);
  51428. }
  51429. });
  51430. targetInfoList.push({
  51431. panelId: 'grid--' + gridModel.id,
  51432. gridModel: gridModel,
  51433. coordSysModel: gridModel,
  51434. // Use the first one as the representitive coordSys.
  51435. coordSys: cartesians[0],
  51436. coordSyses: cartesians,
  51437. getPanelRect: panelRectBuilder.grid,
  51438. xAxisDeclared: xAxesHas[gridModel.id],
  51439. yAxisDeclared: yAxesHas[gridModel.id]
  51440. });
  51441. });
  51442. },
  51443. geo: function (foundCpts, targetInfoList) {
  51444. each(foundCpts.geoModels, function (geoModel) {
  51445. var coordSys = geoModel.coordinateSystem;
  51446. targetInfoList.push({
  51447. panelId: 'geo--' + geoModel.id,
  51448. geoModel: geoModel,
  51449. coordSysModel: geoModel,
  51450. coordSys: coordSys,
  51451. coordSyses: [coordSys],
  51452. getPanelRect: panelRectBuilder.geo
  51453. });
  51454. });
  51455. }
  51456. };
  51457. var targetInfoMatchers = [
  51458. // grid
  51459. function (foundCpts, targetInfo) {
  51460. var xAxisModel = foundCpts.xAxisModel;
  51461. var yAxisModel = foundCpts.yAxisModel;
  51462. var gridModel = foundCpts.gridModel;
  51463. !gridModel && xAxisModel && (gridModel = xAxisModel.axis.grid.model);
  51464. !gridModel && yAxisModel && (gridModel = yAxisModel.axis.grid.model);
  51465. return gridModel && gridModel === targetInfo.gridModel;
  51466. },
  51467. // geo
  51468. function (foundCpts, targetInfo) {
  51469. var geoModel = foundCpts.geoModel;
  51470. return geoModel && geoModel === targetInfo.geoModel;
  51471. }
  51472. ];
  51473. var panelRectBuilder = {
  51474. grid: function () {
  51475. // grid is not Transformable.
  51476. return this.coordSys.grid.getRect().clone();
  51477. },
  51478. geo: function () {
  51479. var coordSys = this.coordSys;
  51480. var rect = coordSys.getBoundingRect().clone();
  51481. // geo roam and zoom transform
  51482. rect.applyTransform(graphic.getTransform(coordSys));
  51483. return rect;
  51484. }
  51485. };
  51486. var coordConvert = {
  51487. lineX: curry(axisConvert, 0),
  51488. lineY: curry(axisConvert, 1),
  51489. rect: function (to, coordSys, rangeOrCoordRange) {
  51490. var xminymin = coordSys[COORD_CONVERTS[to]]([rangeOrCoordRange[0][0], rangeOrCoordRange[1][0]]);
  51491. var xmaxymax = coordSys[COORD_CONVERTS[to]]([rangeOrCoordRange[0][1], rangeOrCoordRange[1][1]]);
  51492. var values = [
  51493. formatMinMax([xminymin[0], xmaxymax[0]]),
  51494. formatMinMax([xminymin[1], xmaxymax[1]])
  51495. ];
  51496. return {values: values, xyMinMax: values};
  51497. },
  51498. polygon: function (to, coordSys, rangeOrCoordRange) {
  51499. var xyMinMax = [[Infinity, -Infinity], [Infinity, -Infinity]];
  51500. var values = zrUtil.map(rangeOrCoordRange, function (item) {
  51501. var p = coordSys[COORD_CONVERTS[to]](item);
  51502. xyMinMax[0][0] = Math.min(xyMinMax[0][0], p[0]);
  51503. xyMinMax[1][0] = Math.min(xyMinMax[1][0], p[1]);
  51504. xyMinMax[0][1] = Math.max(xyMinMax[0][1], p[0]);
  51505. xyMinMax[1][1] = Math.max(xyMinMax[1][1], p[1]);
  51506. return p;
  51507. });
  51508. return {values: values, xyMinMax: xyMinMax};
  51509. }
  51510. };
  51511. function axisConvert(axisNameIndex, to, coordSys, rangeOrCoordRange) {
  51512. if (true) {
  51513. zrUtil.assert(
  51514. coordSys.type === 'cartesian2d',
  51515. 'lineX/lineY brush is available only in cartesian2d.'
  51516. );
  51517. }
  51518. var axis = coordSys.getAxis(['x', 'y'][axisNameIndex]);
  51519. var values = formatMinMax(zrUtil.map([0, 1], function (i) {
  51520. return to
  51521. ? axis.coordToData(axis.toLocalCoord(rangeOrCoordRange[i]))
  51522. : axis.toGlobalCoord(axis.dataToCoord(rangeOrCoordRange[i]));
  51523. }));
  51524. var xyMinMax = [];
  51525. xyMinMax[axisNameIndex] = values;
  51526. xyMinMax[1 - axisNameIndex] = [NaN, NaN];
  51527. return {values: values, xyMinMax: xyMinMax};
  51528. }
  51529. var diffProcessor = {
  51530. lineX: curry(axisDiffProcessor, 0),
  51531. lineY: curry(axisDiffProcessor, 1),
  51532. rect: function (values, refer, scales) {
  51533. return [
  51534. [values[0][0] - scales[0] * refer[0][0], values[0][1] - scales[0] * refer[0][1]],
  51535. [values[1][0] - scales[1] * refer[1][0], values[1][1] - scales[1] * refer[1][1]]
  51536. ];
  51537. },
  51538. polygon: function (values, refer, scales) {
  51539. return zrUtil.map(values, function (item, idx) {
  51540. return [item[0] - scales[0] * refer[idx][0], item[1] - scales[1] * refer[idx][1]];
  51541. });
  51542. }
  51543. };
  51544. function axisDiffProcessor(axisNameIndex, values, refer, scales) {
  51545. return [
  51546. values[0] - scales[axisNameIndex] * refer[0],
  51547. values[1] - scales[axisNameIndex] * refer[1]
  51548. ];
  51549. }
  51550. // We have to process scale caused by dataZoom manually,
  51551. // although it might be not accurate.
  51552. function getScales(xyMinMaxCurr, xyMinMaxOrigin) {
  51553. var sizeCurr = getSize(xyMinMaxCurr);
  51554. var sizeOrigin = getSize(xyMinMaxOrigin);
  51555. var scales = [sizeCurr[0] / sizeOrigin[0], sizeCurr[1] / sizeOrigin[1]];
  51556. isNaN(scales[0]) && (scales[0] = 1);
  51557. isNaN(scales[1]) && (scales[1] = 1);
  51558. return scales;
  51559. }
  51560. function getSize(xyMinMax) {
  51561. return xyMinMax
  51562. ? [xyMinMax[0][1] - xyMinMax[0][0], xyMinMax[1][1] - xyMinMax[1][0]]
  51563. : [NaN, NaN];
  51564. }
  51565. module.exports = BrushTargetManager;
  51566. /***/ },
  51567. /* 352 */
  51568. /***/ function(module, exports, __webpack_require__) {
  51569. /**
  51570. * @file Brush model
  51571. */
  51572. var echarts = __webpack_require__(1);
  51573. var zrUtil = __webpack_require__(4);
  51574. var visualSolution = __webpack_require__(349);
  51575. var Model = __webpack_require__(12);
  51576. var DEFAULT_OUT_OF_BRUSH_COLOR = ['#ddd'];
  51577. var BrushModel = echarts.extendComponentModel({
  51578. type: 'brush',
  51579. dependencies: ['geo', 'grid', 'xAxis', 'yAxis', 'parallel', 'series'],
  51580. /**
  51581. * @protected
  51582. */
  51583. defaultOption: {
  51584. // inBrush: null,
  51585. // outOfBrush: null,
  51586. toolbox: null, // Default value see preprocessor.
  51587. brushLink: null, // Series indices array, broadcast using dataIndex.
  51588. // or 'all', which means all series. 'none' or null means no series.
  51589. seriesIndex: 'all', // seriesIndex array, specify series controlled by this brush component.
  51590. geoIndex: null, //
  51591. xAxisIndex: null,
  51592. yAxisIndex: null,
  51593. brushType: 'rect', // Default brushType, see BrushController.
  51594. brushMode: 'single', // Default brushMode, 'single' or 'multiple'
  51595. transformable: true, // Default transformable.
  51596. brushStyle: { // Default brushStyle
  51597. borderWidth: 1,
  51598. color: 'rgba(120,140,180,0.3)',
  51599. borderColor: 'rgba(120,140,180,0.8)'
  51600. },
  51601. throttleType: 'fixRate',// Throttle in brushSelected event. 'fixRate' or 'debounce'.
  51602. // If null, no throttle. Valid only in the first brush component
  51603. throttleDelay: 0, // Unit: ms, 0 means every event will be triggered.
  51604. // FIXME
  51605. // 试验效果
  51606. removeOnClick: true,
  51607. z: 10000
  51608. },
  51609. /**
  51610. * @readOnly
  51611. * @type {Array.<Object>}
  51612. */
  51613. areas: [],
  51614. /**
  51615. * Current activated brush type.
  51616. * If null, brush is inactived.
  51617. * see module:echarts/component/helper/BrushController
  51618. * @readOnly
  51619. * @type {string}
  51620. */
  51621. brushType: null,
  51622. /**
  51623. * Current brush opt.
  51624. * see module:echarts/component/helper/BrushController
  51625. * @readOnly
  51626. * @type {Object}
  51627. */
  51628. brushOption: {},
  51629. /**
  51630. * @readOnly
  51631. * @type {Array.<Object>}
  51632. */
  51633. coordInfoList: [],
  51634. optionUpdated: function (newOption, isInit) {
  51635. var thisOption = this.option;
  51636. !isInit && visualSolution.replaceVisualOption(
  51637. thisOption, newOption, ['inBrush', 'outOfBrush']
  51638. );
  51639. thisOption.inBrush = thisOption.inBrush || {};
  51640. // Always give default visual, consider setOption at the second time.
  51641. thisOption.outOfBrush = thisOption.outOfBrush || {color: DEFAULT_OUT_OF_BRUSH_COLOR};
  51642. },
  51643. /**
  51644. * If ranges is null/undefined, range state remain.
  51645. *
  51646. * @param {Array.<Object>} [ranges]
  51647. */
  51648. setAreas: function (areas) {
  51649. if (true) {
  51650. zrUtil.assert(zrUtil.isArray(areas));
  51651. zrUtil.each(areas, function (area) {
  51652. zrUtil.assert(area.brushType, 'Illegal areas');
  51653. });
  51654. }
  51655. // If ranges is null/undefined, range state remain.
  51656. // This helps user to dispatchAction({type: 'brush'}) with no areas
  51657. // set but just want to get the current brush select info from a `brush` event.
  51658. if (!areas) {
  51659. return;
  51660. }
  51661. this.areas = zrUtil.map(areas, function (area) {
  51662. return generateBrushOption(this.option, area);
  51663. }, this);
  51664. },
  51665. /**
  51666. * see module:echarts/component/helper/BrushController
  51667. * @param {Object} brushOption
  51668. */
  51669. setBrushOption: function (brushOption) {
  51670. this.brushOption = generateBrushOption(this.option, brushOption);
  51671. this.brushType = this.brushOption.brushType;
  51672. }
  51673. });
  51674. function generateBrushOption(option, brushOption) {
  51675. return zrUtil.merge(
  51676. {
  51677. brushType: option.brushType,
  51678. brushMode: option.brushMode,
  51679. transformable: option.transformable,
  51680. brushStyle: new Model(option.brushStyle).getItemStyle(),
  51681. removeOnClick: option.removeOnClick,
  51682. z: option.z
  51683. },
  51684. brushOption,
  51685. true
  51686. );
  51687. }
  51688. module.exports = BrushModel;
  51689. /***/ },
  51690. /* 353 */
  51691. /***/ function(module, exports, __webpack_require__) {
  51692. var zrUtil = __webpack_require__(4);
  51693. var BrushController = __webpack_require__(244);
  51694. var echarts = __webpack_require__(1);
  51695. module.exports = echarts.extendComponentView({
  51696. type: 'brush',
  51697. init: function (ecModel, api) {
  51698. /**
  51699. * @readOnly
  51700. * @type {module:echarts/model/Global}
  51701. */
  51702. this.ecModel = ecModel;
  51703. /**
  51704. * @readOnly
  51705. * @type {module:echarts/ExtensionAPI}
  51706. */
  51707. this.api = api;
  51708. /**
  51709. * @readOnly
  51710. * @type {module:echarts/component/brush/BrushModel}
  51711. */
  51712. this.model;
  51713. /**
  51714. * @private
  51715. * @type {module:echarts/component/helper/BrushController}
  51716. */
  51717. (this._brushController = new BrushController(api.getZr()))
  51718. .on('brush', zrUtil.bind(this._onBrush, this))
  51719. .mount();
  51720. },
  51721. /**
  51722. * @override
  51723. */
  51724. render: function (brushModel) {
  51725. this.model = brushModel;
  51726. return updateController.apply(this, arguments);
  51727. },
  51728. /**
  51729. * @override
  51730. */
  51731. updateView: updateController,
  51732. /**
  51733. * @override
  51734. */
  51735. updateLayout: updateController,
  51736. /**
  51737. * @override
  51738. */
  51739. updateVisual: updateController,
  51740. /**
  51741. * @override
  51742. */
  51743. dispose: function () {
  51744. this._brushController.dispose();
  51745. },
  51746. /**
  51747. * @private
  51748. */
  51749. _onBrush: function (areas, opt) {
  51750. var modelId = this.model.id;
  51751. this.model.brushTargetManager.setOutputRanges(areas, this.ecModel);
  51752. // Action is not dispatched on drag end, because the drag end
  51753. // emits the same params with the last drag move event, and
  51754. // may have some delay when using touch pad, which makes
  51755. // animation not smooth (when using debounce).
  51756. (!opt.isEnd || opt.removeOnClick) && this.api.dispatchAction({
  51757. type: 'brush',
  51758. brushId: modelId,
  51759. areas: zrUtil.clone(areas),
  51760. $from: modelId
  51761. });
  51762. }
  51763. });
  51764. function updateController(brushModel, ecModel, api, payload) {
  51765. // Do not update controller when drawing.
  51766. (!payload || payload.$from !== brushModel.id) && this._brushController
  51767. .setPanels(brushModel.brushTargetManager.makePanelOpts(api))
  51768. .enableBrush(brushModel.brushOption)
  51769. .updateCovers(brushModel.areas.slice());
  51770. }
  51771. /***/ },
  51772. /* 354 */
  51773. /***/ function(module, exports, __webpack_require__) {
  51774. /**
  51775. * @file Brush action
  51776. */
  51777. var echarts = __webpack_require__(1);
  51778. /**
  51779. * payload: {
  51780. * brushIndex: number, or,
  51781. * brushId: string, or,
  51782. * brushName: string,
  51783. * globalRanges: Array
  51784. * }
  51785. */
  51786. echarts.registerAction(
  51787. {type: 'brush', event: 'brush', update: 'updateView'},
  51788. function (payload, ecModel) {
  51789. ecModel.eachComponent({mainType: 'brush', query: payload}, function (brushModel) {
  51790. brushModel.setAreas(payload.areas);
  51791. });
  51792. }
  51793. );
  51794. /**
  51795. * payload: {
  51796. * brushComponents: [
  51797. * {
  51798. * brushId,
  51799. * brushIndex,
  51800. * brushName,
  51801. * series: [
  51802. * {
  51803. * seriesId,
  51804. * seriesIndex,
  51805. * seriesName,
  51806. * rawIndices: [21, 34, ...]
  51807. * },
  51808. * ...
  51809. * ]
  51810. * },
  51811. * ...
  51812. * ]
  51813. * }
  51814. */
  51815. echarts.registerAction(
  51816. {type: 'brushSelect', event: 'brushSelected', update: 'none'},
  51817. function () {}
  51818. );
  51819. /***/ },
  51820. /* 355 */
  51821. /***/ function(module, exports, __webpack_require__) {
  51822. 'use strict';
  51823. var featureManager = __webpack_require__(356);
  51824. var zrUtil = __webpack_require__(4);
  51825. function Brush(model, ecModel, api) {
  51826. this.model = model;
  51827. this.ecModel = ecModel;
  51828. this.api = api;
  51829. /**
  51830. * @private
  51831. * @type {string}
  51832. */
  51833. this._brushType;
  51834. /**
  51835. * @private
  51836. * @type {string}
  51837. */
  51838. this._brushMode;
  51839. }
  51840. Brush.defaultOption = {
  51841. show: true,
  51842. type: ['rect', 'polygon', 'lineX', 'lineY', 'keep', 'clear'],
  51843. icon: {
  51844. rect: 'M7.3,34.7 M0.4,10V-0.2h9.8 M89.6,10V-0.2h-9.8 M0.4,60v10.2h9.8 M89.6,60v10.2h-9.8 M12.3,22.4V10.5h13.1 M33.6,10.5h7.8 M49.1,10.5h7.8 M77.5,22.4V10.5h-13 M12.3,31.1v8.2 M77.7,31.1v8.2 M12.3,47.6v11.9h13.1 M33.6,59.5h7.6 M49.1,59.5 h7.7 M77.5,47.6v11.9h-13', // jshint ignore:line
  51845. polygon: 'M55.2,34.9c1.7,0,3.1,1.4,3.1,3.1s-1.4,3.1-3.1,3.1 s-3.1-1.4-3.1-3.1S53.5,34.9,55.2,34.9z M50.4,51c1.7,0,3.1,1.4,3.1,3.1c0,1.7-1.4,3.1-3.1,3.1c-1.7,0-3.1-1.4-3.1-3.1 C47.3,52.4,48.7,51,50.4,51z M55.6,37.1l1.5-7.8 M60.1,13.5l1.6-8.7l-7.8,4 M59,19l-1,5.3 M24,16.1l6.4,4.9l6.4-3.3 M48.5,11.6 l-5.9,3.1 M19.1,12.8L9.7,5.1l1.1,7.7 M13.4,29.8l1,7.3l6.6,1.6 M11.6,18.4l1,6.1 M32.8,41.9 M26.6,40.4 M27.3,40.2l6.1,1.6 M49.9,52.1l-5.6-7.6l-4.9-1.2', // jshint ignore:line
  51846. lineX: 'M15.2,30 M19.7,15.6V1.9H29 M34.8,1.9H40.4 M55.3,15.6V1.9H45.9 M19.7,44.4V58.1H29 M34.8,58.1H40.4 M55.3,44.4 V58.1H45.9 M12.5,20.3l-9.4,9.6l9.6,9.8 M3.1,29.9h16.5 M62.5,20.3l9.4,9.6L62.3,39.7 M71.9,29.9H55.4', // jshint ignore:line
  51847. lineY: 'M38.8,7.7 M52.7,12h13.2v9 M65.9,26.6V32 M52.7,46.3h13.2v-9 M24.9,12H11.8v9 M11.8,26.6V32 M24.9,46.3H11.8v-9 M48.2,5.1l-9.3-9l-9.4,9.2 M38.9-3.9V12 M48.2,53.3l-9.3,9l-9.4-9.2 M38.9,62.3V46.4', // jshint ignore:line
  51848. keep: 'M4,10.5V1h10.3 M20.7,1h6.1 M33,1h6.1 M55.4,10.5V1H45.2 M4,17.3v6.6 M55.6,17.3v6.6 M4,30.5V40h10.3 M20.7,40 h6.1 M33,40h6.1 M55.4,30.5V40H45.2 M21,18.9h62.9v48.6H21V18.9z', // jshint ignore:line
  51849. clear: 'M22,14.7l30.9,31 M52.9,14.7L22,45.7 M4.7,16.8V4.2h13.1 M26,4.2h7.8 M41.6,4.2h7.8 M70.3,16.8V4.2H57.2 M4.7,25.9v8.6 M70.3,25.9v8.6 M4.7,43.2v12.6h13.1 M26,55.8h7.8 M41.6,55.8h7.8 M70.3,43.2v12.6H57.2' // jshint ignore:line
  51850. },
  51851. title: {
  51852. rect: '矩形选择',
  51853. polygon: '圈选',
  51854. lineX: '横向选择',
  51855. lineY: '纵向选择',
  51856. keep: '保持选择',
  51857. clear: '清除选择'
  51858. }
  51859. };
  51860. var proto = Brush.prototype;
  51861. proto.render =
  51862. proto.updateView =
  51863. proto.updateLayout = function (featureModel, ecModel, api) {
  51864. var brushType;
  51865. var brushMode;
  51866. var isBrushed;
  51867. ecModel.eachComponent({mainType: 'brush'}, function (brushModel) {
  51868. brushType = brushModel.brushType;
  51869. brushMode = brushModel.brushOption.brushMode || 'single';
  51870. isBrushed |= brushModel.areas.length;
  51871. });
  51872. this._brushType = brushType;
  51873. this._brushMode = brushMode;
  51874. zrUtil.each(featureModel.get('type', true), function (type) {
  51875. featureModel.setIconStatus(
  51876. type,
  51877. (
  51878. type === 'keep'
  51879. ? brushMode === 'multiple'
  51880. : type === 'clear'
  51881. ? isBrushed
  51882. : type === brushType
  51883. ) ? 'emphasis' : 'normal'
  51884. );
  51885. });
  51886. };
  51887. proto.getIcons = function () {
  51888. var model = this.model;
  51889. var availableIcons = model.get('icon', true);
  51890. var icons = {};
  51891. zrUtil.each(model.get('type', true), function (type) {
  51892. if (availableIcons[type]) {
  51893. icons[type] = availableIcons[type];
  51894. }
  51895. });
  51896. return icons;
  51897. };
  51898. proto.onclick = function (ecModel, api, type) {
  51899. var api = this.api;
  51900. var brushType = this._brushType;
  51901. var brushMode = this._brushMode;
  51902. if (type === 'clear') {
  51903. // Trigger parallel action firstly
  51904. api.dispatchAction({
  51905. type: 'axisAreaSelect',
  51906. intervals: []
  51907. });
  51908. api.dispatchAction({
  51909. type: 'brush',
  51910. command: 'clear',
  51911. // Clear all areas of all brush components.
  51912. areas: []
  51913. });
  51914. }
  51915. else {
  51916. api.dispatchAction({
  51917. type: 'takeGlobalCursor',
  51918. key: 'brush',
  51919. brushOption: {
  51920. brushType: type === 'keep'
  51921. ? brushType
  51922. : (brushType === type ? false : type),
  51923. brushMode: type === 'keep'
  51924. ? (brushMode === 'multiple' ? 'single' : 'multiple')
  51925. : brushMode
  51926. }
  51927. });
  51928. }
  51929. };
  51930. featureManager.register('brush', Brush);
  51931. module.exports = Brush;
  51932. /***/ },
  51933. /* 356 */
  51934. /***/ function(module, exports) {
  51935. 'use strict';
  51936. var features = {};
  51937. module.exports = {
  51938. register: function (name, ctor) {
  51939. features[name] = ctor;
  51940. },
  51941. get: function (name) {
  51942. return features[name];
  51943. }
  51944. };
  51945. /***/ },
  51946. /* 357 */
  51947. /***/ function(module, exports, __webpack_require__) {
  51948. 'use strict';
  51949. /**
  51950. * @file calendar.js
  51951. * @author dxh
  51952. */
  51953. __webpack_require__(358);
  51954. __webpack_require__(359);
  51955. __webpack_require__(360);
  51956. /***/ },
  51957. /* 358 */
  51958. /***/ function(module, exports, __webpack_require__) {
  51959. 'use strict';
  51960. var layout = __webpack_require__(71);
  51961. var numberUtil = __webpack_require__(7);
  51962. var zrUtil = __webpack_require__(4);
  51963. // (24*60*60*1000)
  51964. var ONE_DAY = 86400000;
  51965. /**
  51966. * Calendar
  51967. *
  51968. * @constructor
  51969. *
  51970. * @param {Object} calendarModel calendarModel
  51971. * @param {Object} ecModel ecModel
  51972. * @param {Object} api api
  51973. */
  51974. function Calendar(calendarModel, ecModel, api) {
  51975. this._model = calendarModel;
  51976. }
  51977. Calendar.prototype = {
  51978. constructor: Calendar,
  51979. type: 'calendar',
  51980. dimensions: ['time', 'value'],
  51981. // Required in createListFromData
  51982. getDimensionsInfo: function () {
  51983. return [{name: 'time', type: 'time'}];
  51984. },
  51985. getRangeInfo: function () {
  51986. return this._rangeInfo;
  51987. },
  51988. getModel: function () {
  51989. return this._model;
  51990. },
  51991. getRect: function () {
  51992. return this._rect;
  51993. },
  51994. getCellWidth: function () {
  51995. return this._sw;
  51996. },
  51997. getCellHeight: function () {
  51998. return this._sh;
  51999. },
  52000. getOrient: function () {
  52001. return this._orient;
  52002. },
  52003. /**
  52004. * getFirstDayOfWeek
  52005. *
  52006. * @example
  52007. * 0 : start at Sunday
  52008. * 1 : start at Monday
  52009. *
  52010. * @return {number}
  52011. */
  52012. getFirstDayOfWeek: function () {
  52013. return this._firstDayOfWeek;
  52014. },
  52015. /**
  52016. * get date info
  52017. *
  52018. * @param {string|number} date date
  52019. * @return {Object} info
  52020. */
  52021. getDateInfo: function (date) {
  52022. date = numberUtil.parseDate(date);
  52023. var y = date.getFullYear();
  52024. var m = date.getMonth() + 1;
  52025. m = m < 10 ? '0' + m : m;
  52026. var d = date.getDate();
  52027. d = d < 10 ? '0' + d : d;
  52028. var day = date.getDay();
  52029. day = Math.abs((day + 7 - this.getFirstDayOfWeek()) % 7);
  52030. return {
  52031. y: y,
  52032. m: m,
  52033. d: d,
  52034. day: day,
  52035. time: date.getTime(),
  52036. formatedDate: y + '-' + m + '-' + d,
  52037. date: date
  52038. };
  52039. },
  52040. getNextNDay: function (date, n) {
  52041. n = n || 0;
  52042. if (n === 0) {
  52043. return this.getDateInfo(date);
  52044. }
  52045. var time = this.getDateInfo(date).time;
  52046. return this.getDateInfo(time + ONE_DAY * n);
  52047. },
  52048. update: function (ecModel, api) {
  52049. this._firstDayOfWeek = this._model.getModel('dayLabel').get('firstDay');
  52050. this._orient = this._model.get('orient');
  52051. this._lineWidth = this._model.getModel('itemStyle.normal').getItemStyle().lineWidth || 0;
  52052. this._rangeInfo = this._getRangeInfo(this._initRangeOption());
  52053. var weeks = this._rangeInfo.weeks || 1;
  52054. var whNames = ['width', 'height'];
  52055. var cellSize = this._model.get('cellSize').slice();
  52056. var layoutParams = this._model.getBoxLayoutParams();
  52057. var cellNumbers = this._orient === 'horizontal' ? [weeks, 7] : [7, weeks];
  52058. zrUtil.each([0, 1], function (idx) {
  52059. if (cellSizeSpecified(cellSize, idx)) {
  52060. layoutParams[whNames[idx]] = cellSize[idx] * cellNumbers[idx];
  52061. }
  52062. });
  52063. var whGlobal = {
  52064. width: api.getWidth(),
  52065. height: api.getHeight()
  52066. };
  52067. var calendarRect = this._rect = layout.getLayoutRect(layoutParams, whGlobal);
  52068. zrUtil.each([0, 1], function (idx) {
  52069. if (!cellSizeSpecified(cellSize, idx)) {
  52070. cellSize[idx] = calendarRect[whNames[idx]] / cellNumbers[idx];
  52071. }
  52072. });
  52073. function cellSizeSpecified(cellSize, idx) {
  52074. return cellSize[idx] != null && cellSize[idx] !== 'auto';
  52075. }
  52076. this._sw = cellSize[0];
  52077. this._sh = cellSize[1];
  52078. },
  52079. /**
  52080. * Convert a time data(time, value) item to (x, y) point.
  52081. *
  52082. * @override
  52083. * @param {Array|number} data data
  52084. * @param {boolean} [clamp=true] out of range
  52085. * @return {Array} point
  52086. */
  52087. dataToPoint: function (data, clamp) {
  52088. zrUtil.isArray(data) && (data = data[0]);
  52089. clamp == null && (clamp = true);
  52090. var dayInfo = this.getDateInfo(data);
  52091. var range = this._rangeInfo;
  52092. var date = dayInfo.formatedDate;
  52093. // if not in range return [NaN, NaN]
  52094. if (clamp && !(dayInfo.time >= range.start.time && dayInfo.time <= range.end.time)) {
  52095. return [NaN, NaN];
  52096. }
  52097. var week = dayInfo.day;
  52098. var nthWeek = this._getRangeInfo([range.start.time, date]).weeks;
  52099. if (this._orient === 'vertical') {
  52100. return [
  52101. this._rect.x + week * this._sw + this._sw / 2,
  52102. this._rect.y + (nthWeek - 1) * this._sh + this._sh / 2
  52103. ];
  52104. }
  52105. return [
  52106. this._rect.x + (nthWeek - 1) * this._sw + this._sw / 2,
  52107. this._rect.y + week * this._sh + this._sh / 2
  52108. ];
  52109. },
  52110. /**
  52111. * Convert a (x, y) point to time data
  52112. *
  52113. * @override
  52114. * @param {string} point point
  52115. * @return {string} data
  52116. */
  52117. pointToData: function (point) {
  52118. var date = this.pointToDate(point);
  52119. return date && date.time;
  52120. },
  52121. /**
  52122. * Convert a time date item to (x, y) four point.
  52123. *
  52124. * @param {Array} data date[0] is date
  52125. * @param {boolean} [clamp=true] out of range
  52126. * @return {Object} point
  52127. */
  52128. dataToRect: function (data, clamp) {
  52129. var point = this.dataToPoint(data, clamp);
  52130. return {
  52131. contentShape: {
  52132. x: point[0] - (this._sw - this._lineWidth) / 2,
  52133. y: point[1] - (this._sh - this._lineWidth) / 2,
  52134. width: this._sw - this._lineWidth,
  52135. height: this._sh - this._lineWidth
  52136. },
  52137. center: point,
  52138. tl: [
  52139. point[0] - this._sw / 2,
  52140. point[1] - this._sh / 2
  52141. ],
  52142. tr: [
  52143. point[0] + this._sw / 2,
  52144. point[1] - this._sh / 2
  52145. ],
  52146. br: [
  52147. point[0] + this._sw / 2,
  52148. point[1] + this._sh / 2
  52149. ],
  52150. bl: [
  52151. point[0] - this._sw / 2,
  52152. point[1] + this._sh / 2
  52153. ]
  52154. };
  52155. },
  52156. /**
  52157. * Convert a (x, y) point to time date
  52158. *
  52159. * @param {string} point point
  52160. * @return {Object} date
  52161. */
  52162. pointToDate: function (point) {
  52163. var nthX = Math.floor((point[0] - this._rect.x) / this._sw) + 1;
  52164. var nthY = Math.floor((point[1] - this._rect.y) / this._sh) + 1;
  52165. var range = this._rangeInfo.range;
  52166. if (this._orient === 'vertical') {
  52167. return this._getDateByWeeksAndDay(nthY, nthX - 1, range);
  52168. }
  52169. return this._getDateByWeeksAndDay(nthX, nthY - 1, range);
  52170. },
  52171. /**
  52172. * @inheritDoc
  52173. */
  52174. convertToPixel: zrUtil.curry(doConvert, 'dataToPoint'),
  52175. /**
  52176. * @inheritDoc
  52177. */
  52178. convertFromPixel: zrUtil.curry(doConvert, 'pointToData'),
  52179. /**
  52180. * initRange
  52181. *
  52182. * @private
  52183. * @return {Array} [start, end]
  52184. */
  52185. _initRangeOption: function () {
  52186. var range = this._model.get('range');
  52187. var rg = range;
  52188. if (zrUtil.isArray(rg) && rg.length === 1) {
  52189. rg = rg[0];
  52190. }
  52191. if (/^\d{4}$/.test(rg)) {
  52192. range = [rg + '-01-01', rg + '-12-31'];
  52193. }
  52194. if (/^\d{4}[\/|-]\d{1,2}$/.test(rg)) {
  52195. var start = this.getDateInfo(rg);
  52196. var firstDay = start.date;
  52197. firstDay.setMonth(firstDay.getMonth() + 1);
  52198. var end = this.getNextNDay(firstDay, -1);
  52199. range = [start.formatedDate, end.formatedDate];
  52200. }
  52201. if (/^\d{4}[\/|-]\d{1,2}[\/|-]\d{1,2}$/.test(rg)) {
  52202. range = [rg, rg];
  52203. }
  52204. var tmp = this._getRangeInfo(range);
  52205. if (tmp.start.time > tmp.end.time) {
  52206. range.reverse();
  52207. }
  52208. return range;
  52209. },
  52210. /**
  52211. * range info
  52212. *
  52213. * @private
  52214. * @param {Array} range range ['2017-01-01', '2017-07-08']
  52215. * @return {Object} obj
  52216. */
  52217. _getRangeInfo: function (range) {
  52218. var start = this.getDateInfo(range[0]);
  52219. var end = this.getDateInfo(range[1]);
  52220. var allDay = Math.floor(end.time / ONE_DAY) - Math.floor(start.time / ONE_DAY) + 1;
  52221. var weeks = Math.floor((allDay + start.day + 6) / 7);
  52222. return {
  52223. range: [start.formatedDate, end.formatedDate],
  52224. start: start,
  52225. end: end,
  52226. allDay: allDay,
  52227. weeks: weeks,
  52228. fweek: start.day,
  52229. lweek: end.day
  52230. };
  52231. },
  52232. /**
  52233. * get date by nthWeeks and week day in range
  52234. *
  52235. * @private
  52236. * @param {number} nthWeek the week
  52237. * @param {number} day the week day
  52238. * @param {Array} range [d1, d2]
  52239. * @return {Object}
  52240. */
  52241. _getDateByWeeksAndDay: function (nthWeek, day, range) {
  52242. var rangeInfo = this._getRangeInfo(range);
  52243. if (nthWeek > rangeInfo.weeks
  52244. || (nthWeek === 0 && day < rangeInfo.fweek)
  52245. || (nthWeek === rangeInfo.weeks && day > rangeInfo.lweek)
  52246. ) {
  52247. return false;
  52248. }
  52249. var nthDay = (nthWeek - 1) * 7 - rangeInfo.fweek + day;
  52250. var time = rangeInfo.start.time + nthDay * ONE_DAY;
  52251. return this.getDateInfo(time);
  52252. }
  52253. };
  52254. Calendar.dimensions = Calendar.prototype.dimensions;
  52255. Calendar.getDimensionsInfo = Calendar.prototype.getDimensionsInfo;
  52256. Calendar.create = function (ecModel, api) {
  52257. var calendarList = [];
  52258. ecModel.eachComponent('calendar', function (calendarModel) {
  52259. var calendar = new Calendar(calendarModel, ecModel, api);
  52260. calendarList.push(calendar);
  52261. calendarModel.coordinateSystem = calendar;
  52262. });
  52263. ecModel.eachSeries(function (calendarSeries) {
  52264. if (calendarSeries.get('coordinateSystem') === 'calendar') {
  52265. // Inject coordinate system
  52266. calendarSeries.coordinateSystem = calendarList[calendarSeries.get('calendarIndex') || 0];
  52267. }
  52268. });
  52269. return calendarList;
  52270. };
  52271. function doConvert(methodName, ecModel, finder, value) {
  52272. var calendarModel = finder.calendarModel;
  52273. var seriesModel = finder.seriesModel;
  52274. var coordSys = calendarModel
  52275. ? calendarModel.coordinateSystem
  52276. : seriesModel
  52277. ? seriesModel.coordinateSystem
  52278. : null;
  52279. return coordSys === this ? coordSys[methodName](value) : null;
  52280. }
  52281. __webpack_require__(76).register('calendar', Calendar);
  52282. module.exports = Calendar;
  52283. /***/ },
  52284. /* 359 */
  52285. /***/ function(module, exports, __webpack_require__) {
  52286. 'use strict';
  52287. var ComponentModel = __webpack_require__(69);
  52288. var zrUtil = __webpack_require__(4);
  52289. var layout = __webpack_require__(71);
  52290. var CalendarModel = ComponentModel.extend({
  52291. type: 'calendar',
  52292. /**
  52293. * @type {module:echarts/coord/calendar/Calendar}
  52294. */
  52295. coordinateSystem: null,
  52296. defaultOption: {
  52297. zlevel: 0,
  52298. z: 2,
  52299. left: 80,
  52300. top: 60,
  52301. cellSize: 20,
  52302. // horizontal vertical
  52303. orient: 'horizontal',
  52304. // month separate line style
  52305. splitLine: {
  52306. show: true,
  52307. lineStyle: {
  52308. color: '#000',
  52309. width: 1,
  52310. type: 'solid'
  52311. }
  52312. },
  52313. // rect style temporarily unused emphasis
  52314. itemStyle: {
  52315. normal: {
  52316. color: '#fff',
  52317. borderWidth: 1,
  52318. borderColor: '#ccc'
  52319. }
  52320. },
  52321. // week text style
  52322. dayLabel: {
  52323. show: true,
  52324. // a week first day
  52325. firstDay: 0,
  52326. // start end
  52327. position: 'start',
  52328. margin: '50%', // 50% of cellSize
  52329. nameMap: 'en',
  52330. textStyle: {
  52331. color: '#000'
  52332. }
  52333. },
  52334. // month text style
  52335. monthLabel: {
  52336. show: true,
  52337. // start end
  52338. position: 'start',
  52339. margin: 5,
  52340. // center or left
  52341. align: 'center',
  52342. // cn en []
  52343. nameMap: 'en',
  52344. formatter: null,
  52345. textStyle: {
  52346. color: '#000'
  52347. }
  52348. },
  52349. // year text style
  52350. yearLabel: {
  52351. show: true,
  52352. // top bottom left right
  52353. position: null,
  52354. margin: 30,
  52355. formatter: null,
  52356. textStyle: {
  52357. color: '#ccc',
  52358. fontFamily: 'sans-serif',
  52359. fontWeight: 'bolder',
  52360. fontSize: 20
  52361. }
  52362. }
  52363. },
  52364. /**
  52365. * @override
  52366. */
  52367. init: function (option, parentModel, ecModel, extraOpt) {
  52368. var inputPositionParams = layout.getLayoutParams(option);
  52369. CalendarModel.superApply(this, 'init', arguments);
  52370. mergeAndNormalizeLayoutParams(option, inputPositionParams);
  52371. },
  52372. /**
  52373. * @override
  52374. */
  52375. mergeOption: function (option, extraOpt) {
  52376. CalendarModel.superApply(this, 'mergeOption', arguments);
  52377. mergeAndNormalizeLayoutParams(this.option, option);
  52378. }
  52379. });
  52380. function mergeAndNormalizeLayoutParams(target, raw) {
  52381. // Normalize cellSize
  52382. var cellSize = target.cellSize;
  52383. if (!zrUtil.isArray(cellSize)) {
  52384. cellSize = target.cellSize = [cellSize, cellSize];
  52385. }
  52386. else if (cellSize.length === 1) {
  52387. cellSize[1] = cellSize[0];
  52388. }
  52389. var ignoreSize = zrUtil.map([0, 1], function (hvIdx) {
  52390. // If user have set `width` or both `left` and `right`, cellSize
  52391. // will be automatically set to 'auto', otherwise the default
  52392. // setting of cellSize will make `width` setting not work.
  52393. if (layout.sizeCalculable(raw, hvIdx)) {
  52394. cellSize[hvIdx] = 'auto';
  52395. }
  52396. return cellSize[hvIdx] != null && cellSize[hvIdx] !== 'auto';
  52397. });
  52398. layout.mergeLayoutParam(target, raw, {
  52399. type: 'box', ignoreSize: ignoreSize
  52400. });
  52401. }
  52402. module.exports = CalendarModel;
  52403. /***/ },
  52404. /* 360 */
  52405. /***/ function(module, exports, __webpack_require__) {
  52406. 'use strict';
  52407. var zrUtil = __webpack_require__(4);
  52408. var graphic = __webpack_require__(18);
  52409. var formatUtil = __webpack_require__(6);
  52410. var numberUtil = __webpack_require__(7);
  52411. var MONTH_TEXT = {
  52412. EN: [
  52413. 'Jan', 'Feb', 'Mar',
  52414. 'Apr', 'May', 'Jun',
  52415. 'Jul', 'Aug', 'Sep',
  52416. 'Oct', 'Nov', 'Dec'
  52417. ],
  52418. CN: [
  52419. '一月', '二月', '三月',
  52420. '四月', '五月', '六月',
  52421. '七月', '八月', '九月',
  52422. '十月', '十一月', '十二月'
  52423. ]
  52424. };
  52425. var WEEK_TEXT = {
  52426. EN: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
  52427. CN: ['日', '一', '二', '三', '四', '五', '六']
  52428. };
  52429. module.exports = __webpack_require__(1).extendComponentView({
  52430. type: 'calendar',
  52431. /**
  52432. * top/left line points
  52433. * @private
  52434. */
  52435. _tlpoints: null,
  52436. /**
  52437. * bottom/right line points
  52438. * @private
  52439. */
  52440. _blpoints: null,
  52441. /**
  52442. * first day of month
  52443. * @private
  52444. */
  52445. _firstDayOfMonth: null,
  52446. /**
  52447. * first day point of month
  52448. * @private
  52449. */
  52450. _firstDayPoints: null,
  52451. render: function (calendarModel, ecModel, api) {
  52452. var group = this.group;
  52453. group.removeAll();
  52454. var coordSys = calendarModel.coordinateSystem;
  52455. // range info
  52456. var rangeData = coordSys.getRangeInfo();
  52457. var orient = coordSys.getOrient();
  52458. this._renderDayRect(calendarModel, rangeData, group);
  52459. // _renderLines must be called prior to following function
  52460. this._renderLines(calendarModel, rangeData, orient, group);
  52461. this._renderYearText(calendarModel, rangeData, orient, group);
  52462. this._renderMonthText(calendarModel, orient, group);
  52463. this._renderWeekText(calendarModel, rangeData, orient, group);
  52464. },
  52465. // render day rect
  52466. _renderDayRect: function (calendarModel, rangeData, group) {
  52467. var coordSys = calendarModel.coordinateSystem;
  52468. var itemRectStyleModel = calendarModel.getModel('itemStyle.normal').getItemStyle();
  52469. var sw = coordSys.getCellWidth();
  52470. var sh = coordSys.getCellHeight();
  52471. for (var i = rangeData.start.time;
  52472. i <= rangeData.end.time;
  52473. i = coordSys.getNextNDay(i, 1).time
  52474. ) {
  52475. var point = coordSys.dataToRect([i], false).tl;
  52476. // every rect
  52477. var rect = new graphic.Rect({
  52478. shape: {
  52479. x: point[0],
  52480. y: point[1],
  52481. width: sw,
  52482. height: sh
  52483. },
  52484. style: itemRectStyleModel
  52485. });
  52486. group.add(rect);
  52487. }
  52488. },
  52489. // render separate line
  52490. _renderLines: function (calendarModel, rangeData, orient, group) {
  52491. var self = this;
  52492. var coordSys = calendarModel.coordinateSystem;
  52493. var lineStyleModel = calendarModel.getModel('splitLine.lineStyle').getLineStyle();
  52494. var show = calendarModel.get('splitLine.show');
  52495. var lineWidth = lineStyleModel.lineWidth;
  52496. this._tlpoints = [];
  52497. this._blpoints = [];
  52498. this._firstDayOfMonth = [];
  52499. this._firstDayPoints = [];
  52500. var firstDay = rangeData.start;
  52501. for (var i = 0; firstDay.time <= rangeData.end.time; i++) {
  52502. addPoints(firstDay.formatedDate);
  52503. if (i === 0) {
  52504. firstDay = coordSys.getDateInfo(rangeData.start.y + '-' + rangeData.start.m);
  52505. }
  52506. var date = firstDay.date;
  52507. date.setMonth(date.getMonth() + 1);
  52508. firstDay = coordSys.getDateInfo(date);
  52509. }
  52510. addPoints(coordSys.getNextNDay(rangeData.end.time, 1).formatedDate);
  52511. function addPoints(date) {
  52512. self._firstDayOfMonth.push(coordSys.getDateInfo(date));
  52513. self._firstDayPoints.push(coordSys.dataToRect([date], false).tl);
  52514. var points = self._getLinePointsOfOneWeek(calendarModel, date, orient);
  52515. self._tlpoints.push(points[0]);
  52516. self._blpoints.push(points[points.length - 1]);
  52517. show && self._drawSplitline(points, lineStyleModel, group);
  52518. }
  52519. // render top/left line
  52520. show && this._drawSplitline(self._getEdgesPoints(self._tlpoints, lineWidth, orient), lineStyleModel, group);
  52521. // render bottom/right line
  52522. show && this._drawSplitline(self._getEdgesPoints(self._blpoints, lineWidth, orient), lineStyleModel, group);
  52523. },
  52524. // get points at both ends
  52525. _getEdgesPoints: function (points, lineWidth, orient) {
  52526. var rs = [points[0].slice(), points[points.length - 1].slice()];
  52527. var idx = orient === 'horizontal' ? 0 : 1;
  52528. // both ends of the line are extend half lineWidth
  52529. rs[0][idx] = rs[0][idx] - lineWidth / 2;
  52530. rs[1][idx] = rs[1][idx] + lineWidth / 2;
  52531. return rs;
  52532. },
  52533. // render split line
  52534. _drawSplitline: function (points, lineStyleModel, group) {
  52535. var poyline = new graphic.Polyline({
  52536. z2: 20,
  52537. shape: {
  52538. points: points
  52539. },
  52540. style: lineStyleModel
  52541. });
  52542. group.add(poyline);
  52543. },
  52544. // render month line of one week points
  52545. _getLinePointsOfOneWeek: function (calendarModel, date, orient) {
  52546. var coordSys = calendarModel.coordinateSystem;
  52547. date = coordSys.getDateInfo(date);
  52548. var points = [];
  52549. for (var i = 0; i < 7; i++) {
  52550. var tmpD = coordSys.getNextNDay(date.time, i);
  52551. var point = coordSys.dataToRect([tmpD.time], false);
  52552. points[2 * tmpD.day] = point.tl;
  52553. points[2 * tmpD.day + 1] = point[orient === 'horizontal' ? 'bl' : 'tr'];
  52554. }
  52555. return points;
  52556. },
  52557. _formatterLabel: function (formatter, params) {
  52558. if (typeof formatter === 'string' && formatter) {
  52559. return formatUtil.formatTplSimple(formatter, params);
  52560. }
  52561. if (typeof formatter === 'function') {
  52562. return formatter(params);
  52563. }
  52564. return params.nameMap;
  52565. },
  52566. _yearTextPositionControl: function (point, orient, position, margin) {
  52567. point = point.slice();
  52568. var aligns = ['center', 'bottom'];
  52569. if (position === 'top') {
  52570. point[1] -= margin;
  52571. }
  52572. if (position === 'bottom') {
  52573. point[1] += margin;
  52574. aligns = ['center', 'top'];
  52575. }
  52576. if (position === 'left') {
  52577. point[0] -= margin;
  52578. }
  52579. if (position === 'right') {
  52580. point[0] += margin;
  52581. aligns = ['center', 'top'];
  52582. }
  52583. var rotate = 0;
  52584. if (position === 'left' || position === 'right') {
  52585. rotate = Math.PI / 2;
  52586. }
  52587. return {
  52588. rotation: rotate,
  52589. origin: point,
  52590. style: {
  52591. x: point[0],
  52592. y: point[1],
  52593. textAlign: aligns[0],
  52594. textVerticalAlign: aligns[1]
  52595. }
  52596. };
  52597. },
  52598. // render year
  52599. _renderYearText: function (calendarModel, rangeData, orient, group) {
  52600. var yearLabel = calendarModel.getModel('yearLabel');
  52601. if (!yearLabel.get('show')) {
  52602. return;
  52603. }
  52604. var yearLabelStyleModel = calendarModel.getModel('yearLabel.textStyle');
  52605. var margin = yearLabel.get('margin');
  52606. var pos = yearLabel.get('position');
  52607. if (!pos) {
  52608. pos = orient !== 'horizontal' ? 'top' : 'left';
  52609. }
  52610. var points = [this._tlpoints[this._tlpoints.length - 1], this._blpoints[0]];
  52611. var xc = (points[0][0] + points[1][0]) / 2;
  52612. var yc = (points[0][1] + points[1][1]) / 2;
  52613. var idx = orient === 'horizontal' ? 0 : 1;
  52614. var posPoints = {
  52615. top: [xc, points[idx][1]],
  52616. bottom: [xc, points[1 - idx][1]],
  52617. left: [points[1 - idx][0], yc],
  52618. right: [points[idx][0], yc]
  52619. };
  52620. var name = rangeData.start.y;
  52621. if (+rangeData.end.y > +rangeData.start.y) {
  52622. name = name + '-' + rangeData.end.y;
  52623. }
  52624. var formatter = yearLabel.get('formatter');
  52625. var params = {
  52626. start: rangeData.start.y,
  52627. end: rangeData.end.y,
  52628. nameMap: name
  52629. };
  52630. var content = this._formatterLabel(formatter, params);
  52631. var yearText = new graphic.Text(
  52632. zrUtil.merge({
  52633. z2: 30,
  52634. style: {
  52635. text: content,
  52636. font: yearLabelStyleModel.getFont(),
  52637. fill: yearLabelStyleModel.getTextColor()
  52638. }
  52639. }, this._yearTextPositionControl(posPoints[pos], orient, pos, margin))
  52640. );
  52641. group.add(yearText);
  52642. },
  52643. _monthTextPositionControl: function (point, isCenter, orient, position, margin) {
  52644. var align = 'left';
  52645. var vAlign = 'top';
  52646. var x = point[0];
  52647. var y = point[1];
  52648. if (orient === 'horizontal') {
  52649. y = y + margin;
  52650. if (isCenter) {
  52651. align = 'center';
  52652. }
  52653. if (position === 'start') {
  52654. vAlign = 'bottom';
  52655. }
  52656. }
  52657. else {
  52658. x = x + margin;
  52659. if (isCenter) {
  52660. vAlign = 'middle';
  52661. }
  52662. if (position === 'start') {
  52663. align = 'right';
  52664. }
  52665. }
  52666. return {
  52667. x: x,
  52668. y: y,
  52669. textAlign: align,
  52670. textVerticalAlign: vAlign
  52671. };
  52672. },
  52673. // render month and year text
  52674. _renderMonthText: function (calendarModel, orient, group) {
  52675. var monthLabel = calendarModel.getModel('monthLabel');
  52676. if (!monthLabel.get('show')) {
  52677. return;
  52678. }
  52679. var monthLabelStyleModel = calendarModel.getModel('monthLabel.textStyle');
  52680. var nameMap = monthLabel.get('nameMap');
  52681. var margin = monthLabel.get('margin');
  52682. var pos = monthLabel.get('position');
  52683. var align = monthLabel.get('align');
  52684. var termPoints = [this._tlpoints, this._blpoints];
  52685. if (zrUtil.isString(nameMap)) {
  52686. nameMap = MONTH_TEXT[nameMap.toUpperCase()] || [];
  52687. }
  52688. var idx = pos === 'start' ? 0 : 1;
  52689. var axis = orient === 'horizontal' ? 0 : 1;
  52690. margin = pos === 'start' ? -margin : margin;
  52691. var isCenter = (align === 'center');
  52692. for (var i = 0; i < termPoints[idx].length - 1; i++) {
  52693. var tmp = termPoints[idx][i].slice();
  52694. var firstDay = this._firstDayOfMonth[i];
  52695. if (isCenter) {
  52696. var firstDayPoints = this._firstDayPoints[i];
  52697. tmp[axis] = (firstDayPoints[axis] + termPoints[0][i + 1][axis]) / 2;
  52698. }
  52699. var formatter = monthLabel.get('formatter');
  52700. var name = nameMap[+firstDay.m - 1];
  52701. var params = {
  52702. yyyy: firstDay.y,
  52703. yy: (firstDay.y + '').slice(2),
  52704. MM: firstDay.m,
  52705. M: +firstDay.m,
  52706. nameMap: name
  52707. };
  52708. var content = this._formatterLabel(formatter, params);
  52709. var monthText = new graphic.Text({
  52710. z2: 30,
  52711. style: zrUtil.extend({
  52712. text: content,
  52713. font: monthLabelStyleModel.getFont(),
  52714. fill: monthLabelStyleModel.getTextColor()
  52715. }, this._monthTextPositionControl(tmp, isCenter, orient, pos, margin))
  52716. });
  52717. group.add(monthText);
  52718. }
  52719. },
  52720. _weekTextPositionControl: function (point, orient, position, margin, cellSize) {
  52721. var align = 'center';
  52722. var vAlign = 'middle';
  52723. var x = point[0];
  52724. var y = point[1];
  52725. var isStart = position === 'start';
  52726. if (orient === 'horizontal') {
  52727. x = x + margin + (isStart ? 1 : -1) * cellSize[0] / 2;
  52728. align = isStart ? 'right' : 'left';
  52729. }
  52730. else {
  52731. y = y + margin + (isStart ? 1 : -1) * cellSize[1] / 2;
  52732. vAlign = isStart ? 'bottom' : 'top';
  52733. }
  52734. return {
  52735. x: x,
  52736. y: y,
  52737. textAlign: align,
  52738. textVerticalAlign: vAlign
  52739. };
  52740. },
  52741. // render weeks
  52742. _renderWeekText: function (calendarModel, rangeData, orient, group) {
  52743. var dayLabel = calendarModel.getModel('dayLabel');
  52744. if (!dayLabel.get('show')) {
  52745. return;
  52746. }
  52747. var coordSys = calendarModel.coordinateSystem;
  52748. var dayLabelStyleModel = calendarModel.getModel('dayLabel.textStyle');
  52749. var pos = dayLabel.get('position');
  52750. var nameMap = dayLabel.get('nameMap');
  52751. var margin = dayLabel.get('margin');
  52752. var firstDayOfWeek = coordSys.getFirstDayOfWeek();
  52753. if (zrUtil.isString(nameMap)) {
  52754. nameMap = WEEK_TEXT[nameMap.toUpperCase()] || [];
  52755. }
  52756. var start = coordSys.getNextNDay(
  52757. rangeData.end.time, (7 - rangeData.lweek)
  52758. ).time;
  52759. var cellSize = [coordSys.getCellWidth(), coordSys.getCellHeight()];
  52760. margin = numberUtil.parsePercent(margin, cellSize[orient === 'horizontal' ? 0 : 1]);
  52761. if (pos === 'start') {
  52762. start = coordSys.getNextNDay(
  52763. rangeData.start.time, -(7 + rangeData.fweek)
  52764. ).time;
  52765. margin = -margin;
  52766. }
  52767. for (var i = 0; i < 7; i++) {
  52768. var tmpD = coordSys.getNextNDay(start, i);
  52769. var point = coordSys.dataToRect([tmpD.time], false).center;
  52770. var day = i;
  52771. day = Math.abs((i + firstDayOfWeek) % 7);
  52772. var weekText = new graphic.Text({
  52773. z2: 30,
  52774. style: zrUtil.extend({
  52775. text: nameMap[day],
  52776. font: dayLabelStyleModel.getFont(),
  52777. fill: dayLabelStyleModel.getTextColor()
  52778. }, this._weekTextPositionControl(point, orient, pos, margin, cellSize))
  52779. });
  52780. group.add(weekText);
  52781. }
  52782. }
  52783. });
  52784. /***/ },
  52785. /* 361 */
  52786. /***/ function(module, exports, __webpack_require__) {
  52787. 'use strict';
  52788. var echarts = __webpack_require__(1);
  52789. var graphic = __webpack_require__(18);
  52790. var layout = __webpack_require__(71);
  52791. // Model
  52792. echarts.extendComponentModel({
  52793. type: 'title',
  52794. layoutMode: {type: 'box', ignoreSize: true},
  52795. defaultOption: {
  52796. // 一级层叠
  52797. zlevel: 0,
  52798. // 二级层叠
  52799. z: 6,
  52800. show: true,
  52801. text: '',
  52802. // 超链接跳转
  52803. // link: null,
  52804. // 仅支持self | blank
  52805. target: 'blank',
  52806. subtext: '',
  52807. // 超链接跳转
  52808. // sublink: null,
  52809. // 仅支持self | blank
  52810. subtarget: 'blank',
  52811. // 'center' ¦ 'left' ¦ 'right'
  52812. // ¦ {number}(x坐标,单位px)
  52813. left: 0,
  52814. // 'top' ¦ 'bottom' ¦ 'center'
  52815. // ¦ {number}(y坐标,单位px)
  52816. top: 0,
  52817. // 水平对齐
  52818. // 'auto' | 'left' | 'right' | 'center'
  52819. // 默认根据 left 的位置判断是左对齐还是右对齐
  52820. // textAlign: null
  52821. //
  52822. // 垂直对齐
  52823. // 'auto' | 'top' | 'bottom' | 'middle'
  52824. // 默认根据 top 位置判断是上对齐还是下对齐
  52825. // textBaseline: null
  52826. backgroundColor: 'rgba(0,0,0,0)',
  52827. // 标题边框颜色
  52828. borderColor: '#ccc',
  52829. // 标题边框线宽,单位px,默认为0(无边框)
  52830. borderWidth: 0,
  52831. // 标题内边距,单位px,默认各方向内边距为5,
  52832. // 接受数组分别设定上右下左边距,同css
  52833. padding: 5,
  52834. // 主副标题纵向间隔,单位px,默认为10,
  52835. itemGap: 10,
  52836. textStyle: {
  52837. fontSize: 18,
  52838. fontWeight: 'bolder',
  52839. color: '#333'
  52840. },
  52841. subtextStyle: {
  52842. color: '#aaa'
  52843. }
  52844. }
  52845. });
  52846. // View
  52847. echarts.extendComponentView({
  52848. type: 'title',
  52849. render: function (titleModel, ecModel, api) {
  52850. this.group.removeAll();
  52851. if (!titleModel.get('show')) {
  52852. return;
  52853. }
  52854. var group = this.group;
  52855. var textStyleModel = titleModel.getModel('textStyle');
  52856. var subtextStyleModel = titleModel.getModel('subtextStyle');
  52857. var textAlign = titleModel.get('textAlign');
  52858. var textBaseline = titleModel.get('textBaseline');
  52859. var textEl = new graphic.Text({
  52860. style: {
  52861. text: titleModel.get('text'),
  52862. textFont: textStyleModel.getFont(),
  52863. fill: textStyleModel.getTextColor()
  52864. },
  52865. z2: 10
  52866. });
  52867. var textRect = textEl.getBoundingRect();
  52868. var subText = titleModel.get('subtext');
  52869. var subTextEl = new graphic.Text({
  52870. style: {
  52871. text: subText,
  52872. textFont: subtextStyleModel.getFont(),
  52873. fill: subtextStyleModel.getTextColor(),
  52874. y: textRect.height + titleModel.get('itemGap'),
  52875. textBaseline: 'top'
  52876. },
  52877. z2: 10
  52878. });
  52879. var link = titleModel.get('link');
  52880. var sublink = titleModel.get('sublink');
  52881. textEl.silent = !link;
  52882. subTextEl.silent = !sublink;
  52883. if (link) {
  52884. textEl.on('click', function () {
  52885. window.open(link, '_' + titleModel.get('target'));
  52886. });
  52887. }
  52888. if (sublink) {
  52889. subTextEl.on('click', function () {
  52890. window.open(sublink, '_' + titleModel.get('subtarget'));
  52891. });
  52892. }
  52893. group.add(textEl);
  52894. subText && group.add(subTextEl);
  52895. // If no subText, but add subTextEl, there will be an empty line.
  52896. var groupRect = group.getBoundingRect();
  52897. var layoutOption = titleModel.getBoxLayoutParams();
  52898. layoutOption.width = groupRect.width;
  52899. layoutOption.height = groupRect.height;
  52900. var layoutRect = layout.getLayoutRect(
  52901. layoutOption, {
  52902. width: api.getWidth(),
  52903. height: api.getHeight()
  52904. }, titleModel.get('padding')
  52905. );
  52906. // Adjust text align based on position
  52907. if (!textAlign) {
  52908. // Align left if title is on the left. center and right is same
  52909. textAlign = titleModel.get('left') || titleModel.get('right');
  52910. if (textAlign === 'middle') {
  52911. textAlign = 'center';
  52912. }
  52913. // Adjust layout by text align
  52914. if (textAlign === 'right') {
  52915. layoutRect.x += layoutRect.width;
  52916. }
  52917. else if (textAlign === 'center') {
  52918. layoutRect.x += layoutRect.width / 2;
  52919. }
  52920. }
  52921. if (!textBaseline) {
  52922. textBaseline = titleModel.get('top') || titleModel.get('bottom');
  52923. if (textBaseline === 'center') {
  52924. textBaseline = 'middle';
  52925. }
  52926. if (textBaseline === 'bottom') {
  52927. layoutRect.y += layoutRect.height;
  52928. }
  52929. else if (textBaseline === 'middle') {
  52930. layoutRect.y += layoutRect.height / 2;
  52931. }
  52932. textBaseline = textBaseline || 'top';
  52933. }
  52934. group.attr('position', [layoutRect.x, layoutRect.y]);
  52935. var alignStyle = {
  52936. textAlign: textAlign,
  52937. textVerticalAlign: textBaseline
  52938. };
  52939. textEl.setStyle(alignStyle);
  52940. subTextEl.setStyle(alignStyle);
  52941. // Render background
  52942. // Get groupRect again because textAlign has been changed
  52943. groupRect = group.getBoundingRect();
  52944. var padding = layoutRect.margin;
  52945. var style = titleModel.getItemStyle(['color', 'opacity']);
  52946. style.fill = titleModel.get('backgroundColor');
  52947. var rect = new graphic.Rect({
  52948. shape: {
  52949. x: groupRect.x - padding[3],
  52950. y: groupRect.y - padding[0],
  52951. width: groupRect.width + padding[1] + padding[3],
  52952. height: groupRect.height + padding[0] + padding[2]
  52953. },
  52954. style: style,
  52955. silent: true
  52956. });
  52957. graphic.subPixelOptimizeRect(rect);
  52958. group.add(rect);
  52959. }
  52960. });
  52961. /***/ },
  52962. /* 362 */
  52963. /***/ function(module, exports, __webpack_require__) {
  52964. /**
  52965. * DataZoom component entry
  52966. */
  52967. __webpack_require__(363);
  52968. __webpack_require__(364);
  52969. __webpack_require__(367);
  52970. __webpack_require__(368);
  52971. __webpack_require__(369);
  52972. __webpack_require__(370);
  52973. __webpack_require__(371);
  52974. __webpack_require__(373);
  52975. __webpack_require__(374);
  52976. /***/ },
  52977. /* 363 */
  52978. /***/ function(module, exports, __webpack_require__) {
  52979. __webpack_require__(69).registerSubTypeDefaulter('dataZoom', function (option) {
  52980. // Default 'slider' when no type specified.
  52981. return 'slider';
  52982. });
  52983. /***/ },
  52984. /* 364 */
  52985. /***/ function(module, exports, __webpack_require__) {
  52986. /**
  52987. * @file Data zoom model
  52988. */
  52989. var zrUtil = __webpack_require__(4);
  52990. var env = __webpack_require__(2);
  52991. var echarts = __webpack_require__(1);
  52992. var modelUtil = __webpack_require__(5);
  52993. var helper = __webpack_require__(365);
  52994. var AxisProxy = __webpack_require__(366);
  52995. var each = zrUtil.each;
  52996. var eachAxisDim = helper.eachAxisDim;
  52997. var DataZoomModel = echarts.extendComponentModel({
  52998. type: 'dataZoom',
  52999. dependencies: [
  53000. 'xAxis', 'yAxis', 'zAxis', 'radiusAxis', 'angleAxis', 'singleAxis', 'series'
  53001. ],
  53002. /**
  53003. * @protected
  53004. */
  53005. defaultOption: {
  53006. zlevel: 0,
  53007. z: 4, // Higher than normal component (z: 2).
  53008. orient: null, // Default auto by axisIndex. Possible value: 'horizontal', 'vertical'.
  53009. xAxisIndex: null, // Default the first horizontal category axis.
  53010. yAxisIndex: null, // Default the first vertical category axis.
  53011. filterMode: 'filter', // Possible values: 'filter' or 'empty' or 'weakFilter'.
  53012. // 'filter': data items which are out of window will be removed. This option is
  53013. // applicable when filtering outliers. For each data item, it will be
  53014. // filtered if one of the relevant dimensions is out of the window.
  53015. // 'weakFilter': data items which are out of window will be removed. This option
  53016. // is applicable when filtering outliers. For each data item, it will be
  53017. // filtered only if all of the relevant dimensions are out of the same
  53018. // side of the window.
  53019. // 'empty': data items which are out of window will be set to empty.
  53020. // This option is applicable when user should not neglect
  53021. // that there are some data items out of window.
  53022. // 'none': Do not filter.
  53023. // Taking line chart as an example, line will be broken in
  53024. // the filtered points when filterModel is set to 'empty', but
  53025. // be connected when set to 'filter'.
  53026. throttle: null, // Dispatch action by the fixed rate, avoid frequency.
  53027. // default 100. Do not throttle when use null/undefined.
  53028. // If animation === true and animationDurationUpdate > 0,
  53029. // default value is 100, otherwise 20.
  53030. start: 0, // Start percent. 0 ~ 100
  53031. end: 100, // End percent. 0 ~ 100
  53032. startValue: null, // Start value. If startValue specified, start is ignored.
  53033. endValue: null, // End value. If endValue specified, end is ignored.
  53034. minSpan: null, // 0 ~ 100
  53035. maxSpan: null, // 0 ~ 100
  53036. minValueSpan: null, // The range of dataZoom can not be smaller than that.
  53037. maxValueSpan: null // The range of dataZoom can not be larger than that.
  53038. },
  53039. /**
  53040. * @override
  53041. */
  53042. init: function (option, parentModel, ecModel) {
  53043. /**
  53044. * key like x_0, y_1
  53045. * @private
  53046. * @type {Object}
  53047. */
  53048. this._dataIntervalByAxis = {};
  53049. /**
  53050. * @private
  53051. */
  53052. this._dataInfo = {};
  53053. /**
  53054. * key like x_0, y_1
  53055. * @private
  53056. */
  53057. this._axisProxies = {};
  53058. /**
  53059. * @readOnly
  53060. */
  53061. this.textStyleModel;
  53062. /**
  53063. * @private
  53064. */
  53065. this._autoThrottle = true;
  53066. /**
  53067. * 'percent' or 'value'
  53068. * @private
  53069. */
  53070. this._rangePropMode = ['percent', 'percent'];
  53071. var rawOption = retrieveRaw(option);
  53072. this.mergeDefaultAndTheme(option, ecModel);
  53073. this.doInit(rawOption);
  53074. },
  53075. /**
  53076. * @override
  53077. */
  53078. mergeOption: function (newOption) {
  53079. var rawOption = retrieveRaw(newOption);
  53080. //FIX #2591
  53081. zrUtil.merge(this.option, newOption, true);
  53082. this.doInit(rawOption);
  53083. },
  53084. /**
  53085. * @protected
  53086. */
  53087. doInit: function (rawOption) {
  53088. var thisOption = this.option;
  53089. // Disable realtime view update if canvas is not supported.
  53090. if (!env.canvasSupported) {
  53091. thisOption.realtime = false;
  53092. }
  53093. this._setDefaultThrottle(rawOption);
  53094. updateRangeUse(this, rawOption);
  53095. each([['start', 'startValue'], ['end', 'endValue']], function (names, index) {
  53096. // start/end has higher priority over startValue/endValue if they
  53097. // both set, but we should make chart.setOption({endValue: 1000})
  53098. // effective, rather than chart.setOption({endValue: 1000, end: null}).
  53099. if (this._rangePropMode[index] === 'value') {
  53100. thisOption[names[0]] = null;
  53101. }
  53102. // Otherwise do nothing and use the merge result.
  53103. }, this);
  53104. this.textStyleModel = this.getModel('textStyle');
  53105. this._resetTarget();
  53106. this._giveAxisProxies();
  53107. },
  53108. /**
  53109. * @private
  53110. */
  53111. _giveAxisProxies: function () {
  53112. var axisProxies = this._axisProxies;
  53113. this.eachTargetAxis(function (dimNames, axisIndex, dataZoomModel, ecModel) {
  53114. var axisModel = this.dependentModels[dimNames.axis][axisIndex];
  53115. // If exists, share axisProxy with other dataZoomModels.
  53116. var axisProxy = axisModel.__dzAxisProxy || (
  53117. // Use the first dataZoomModel as the main model of axisProxy.
  53118. axisModel.__dzAxisProxy = new AxisProxy(
  53119. dimNames.name, axisIndex, this, ecModel
  53120. )
  53121. );
  53122. // FIXME
  53123. // dispose __dzAxisProxy
  53124. axisProxies[dimNames.name + '_' + axisIndex] = axisProxy;
  53125. }, this);
  53126. },
  53127. /**
  53128. * @private
  53129. */
  53130. _resetTarget: function () {
  53131. var thisOption = this.option;
  53132. var autoMode = this._judgeAutoMode();
  53133. eachAxisDim(function (dimNames) {
  53134. var axisIndexName = dimNames.axisIndex;
  53135. thisOption[axisIndexName] = modelUtil.normalizeToArray(
  53136. thisOption[axisIndexName]
  53137. );
  53138. }, this);
  53139. if (autoMode === 'axisIndex') {
  53140. this._autoSetAxisIndex();
  53141. }
  53142. else if (autoMode === 'orient') {
  53143. this._autoSetOrient();
  53144. }
  53145. },
  53146. /**
  53147. * @private
  53148. */
  53149. _judgeAutoMode: function () {
  53150. // Auto set only works for setOption at the first time.
  53151. // The following is user's reponsibility. So using merged
  53152. // option is OK.
  53153. var thisOption = this.option;
  53154. var hasIndexSpecified = false;
  53155. eachAxisDim(function (dimNames) {
  53156. // When user set axisIndex as a empty array, we think that user specify axisIndex
  53157. // but do not want use auto mode. Because empty array may be encountered when
  53158. // some error occured.
  53159. if (thisOption[dimNames.axisIndex] != null) {
  53160. hasIndexSpecified = true;
  53161. }
  53162. }, this);
  53163. var orient = thisOption.orient;
  53164. if (orient == null && hasIndexSpecified) {
  53165. return 'orient';
  53166. }
  53167. else if (!hasIndexSpecified) {
  53168. if (orient == null) {
  53169. thisOption.orient = 'horizontal';
  53170. }
  53171. return 'axisIndex';
  53172. }
  53173. },
  53174. /**
  53175. * @private
  53176. */
  53177. _autoSetAxisIndex: function () {
  53178. var autoAxisIndex = true;
  53179. var orient = this.get('orient', true);
  53180. var thisOption = this.option;
  53181. var dependentModels = this.dependentModels;
  53182. if (autoAxisIndex) {
  53183. // Find axis that parallel to dataZoom as default.
  53184. var dimName = orient === 'vertical' ? 'y' : 'x';
  53185. if (dependentModels[dimName + 'Axis'].length) {
  53186. thisOption[dimName + 'AxisIndex'] = [0];
  53187. autoAxisIndex = false;
  53188. }
  53189. else {
  53190. each(dependentModels.singleAxis, function (singleAxisModel) {
  53191. if (autoAxisIndex && singleAxisModel.get('orient', true) === orient) {
  53192. thisOption.singleAxisIndex = [singleAxisModel.componentIndex];
  53193. autoAxisIndex = false;
  53194. }
  53195. });
  53196. }
  53197. }
  53198. if (autoAxisIndex) {
  53199. // Find the first category axis as default. (consider polar)
  53200. eachAxisDim(function (dimNames) {
  53201. if (!autoAxisIndex) {
  53202. return;
  53203. }
  53204. var axisIndices = [];
  53205. var axisModels = this.dependentModels[dimNames.axis];
  53206. if (axisModels.length && !axisIndices.length) {
  53207. for (var i = 0, len = axisModels.length; i < len; i++) {
  53208. if (axisModels[i].get('type') === 'category') {
  53209. axisIndices.push(i);
  53210. }
  53211. }
  53212. }
  53213. thisOption[dimNames.axisIndex] = axisIndices;
  53214. if (axisIndices.length) {
  53215. autoAxisIndex = false;
  53216. }
  53217. }, this);
  53218. }
  53219. if (autoAxisIndex) {
  53220. // FIXME
  53221. // 这里是兼容ec2的写法(没指定xAxisIndex和yAxisIndex时把scatter和双数值轴折柱纳入dataZoom控制),
  53222. // 但是实际是否需要Grid.js#getScaleByOption来判断(考虑time,log等axis type)?
  53223. // If both dataZoom.xAxisIndex and dataZoom.yAxisIndex is not specified,
  53224. // dataZoom component auto adopts series that reference to
  53225. // both xAxis and yAxis which type is 'value'.
  53226. this.ecModel.eachSeries(function (seriesModel) {
  53227. if (this._isSeriesHasAllAxesTypeOf(seriesModel, 'value')) {
  53228. eachAxisDim(function (dimNames) {
  53229. var axisIndices = thisOption[dimNames.axisIndex];
  53230. var axisIndex = seriesModel.get(dimNames.axisIndex);
  53231. var axisId = seriesModel.get(dimNames.axisId);
  53232. var axisModel = seriesModel.ecModel.queryComponents({
  53233. mainType: dimNames.axis,
  53234. index: axisIndex,
  53235. id: axisId
  53236. })[0];
  53237. if (true) {
  53238. if (!axisModel) {
  53239. throw new Error(
  53240. dimNames.axis + ' "' + zrUtil.retrieve(
  53241. axisIndex,
  53242. axisId,
  53243. 0
  53244. ) + '" not found'
  53245. );
  53246. }
  53247. }
  53248. axisIndex = axisModel.componentIndex;
  53249. if (zrUtil.indexOf(axisIndices, axisIndex) < 0) {
  53250. axisIndices.push(axisIndex);
  53251. }
  53252. });
  53253. }
  53254. }, this);
  53255. }
  53256. },
  53257. /**
  53258. * @private
  53259. */
  53260. _autoSetOrient: function () {
  53261. var dim;
  53262. // Find the first axis
  53263. this.eachTargetAxis(function (dimNames) {
  53264. !dim && (dim = dimNames.name);
  53265. }, this);
  53266. this.option.orient = dim === 'y' ? 'vertical' : 'horizontal';
  53267. },
  53268. /**
  53269. * @private
  53270. */
  53271. _isSeriesHasAllAxesTypeOf: function (seriesModel, axisType) {
  53272. // FIXME
  53273. // 需要series的xAxisIndex和yAxisIndex都首先自动设置上。
  53274. // 例如series.type === scatter时。
  53275. var is = true;
  53276. eachAxisDim(function (dimNames) {
  53277. var seriesAxisIndex = seriesModel.get(dimNames.axisIndex);
  53278. var axisModel = this.dependentModels[dimNames.axis][seriesAxisIndex];
  53279. if (!axisModel || axisModel.get('type') !== axisType) {
  53280. is = false;
  53281. }
  53282. }, this);
  53283. return is;
  53284. },
  53285. /**
  53286. * @private
  53287. */
  53288. _setDefaultThrottle: function (rawOption) {
  53289. // When first time user set throttle, auto throttle ends.
  53290. if (rawOption.hasOwnProperty('throttle')) {
  53291. this._autoThrottle = false;
  53292. }
  53293. if (this._autoThrottle) {
  53294. var globalOption = this.ecModel.option;
  53295. this.option.throttle =
  53296. (globalOption.animation && globalOption.animationDurationUpdate > 0)
  53297. ? 100 : 20;
  53298. }
  53299. },
  53300. /**
  53301. * @public
  53302. */
  53303. getFirstTargetAxisModel: function () {
  53304. var firstAxisModel;
  53305. eachAxisDim(function (dimNames) {
  53306. if (firstAxisModel == null) {
  53307. var indices = this.get(dimNames.axisIndex);
  53308. if (indices.length) {
  53309. firstAxisModel = this.dependentModels[dimNames.axis][indices[0]];
  53310. }
  53311. }
  53312. }, this);
  53313. return firstAxisModel;
  53314. },
  53315. /**
  53316. * @public
  53317. * @param {Function} callback param: axisModel, dimNames, axisIndex, dataZoomModel, ecModel
  53318. */
  53319. eachTargetAxis: function (callback, context) {
  53320. var ecModel = this.ecModel;
  53321. eachAxisDim(function (dimNames) {
  53322. each(
  53323. this.get(dimNames.axisIndex),
  53324. function (axisIndex) {
  53325. callback.call(context, dimNames, axisIndex, this, ecModel);
  53326. },
  53327. this
  53328. );
  53329. }, this);
  53330. },
  53331. /**
  53332. * @param {string} dimName
  53333. * @param {number} axisIndex
  53334. * @return {module:echarts/component/dataZoom/AxisProxy} If not found, return null/undefined.
  53335. */
  53336. getAxisProxy: function (dimName, axisIndex) {
  53337. return this._axisProxies[dimName + '_' + axisIndex];
  53338. },
  53339. /**
  53340. * @param {string} dimName
  53341. * @param {number} axisIndex
  53342. * @return {module:echarts/model/Model} If not found, return null/undefined.
  53343. */
  53344. getAxisModel: function (dimName, axisIndex) {
  53345. var axisProxy = this.getAxisProxy(dimName, axisIndex);
  53346. return axisProxy && axisProxy.getAxisModel();
  53347. },
  53348. /**
  53349. * If not specified, set to undefined.
  53350. *
  53351. * @public
  53352. * @param {Object} opt
  53353. * @param {number} [opt.start]
  53354. * @param {number} [opt.end]
  53355. * @param {number} [opt.startValue]
  53356. * @param {number} [opt.endValue]
  53357. * @param {boolean} [ignoreUpdateRangeUsg=false]
  53358. */
  53359. setRawRange: function (opt, ignoreUpdateRangeUsg) {
  53360. each(['start', 'end', 'startValue', 'endValue'], function (name) {
  53361. // If any of those prop is null/undefined, we should alos set
  53362. // them, because only one pair between start/end and
  53363. // startValue/endValue can work.
  53364. this.option[name] = opt[name];
  53365. }, this);
  53366. !ignoreUpdateRangeUsg && updateRangeUse(this, opt);
  53367. },
  53368. /**
  53369. * @public
  53370. * @return {Array.<number>} [startPercent, endPercent]
  53371. */
  53372. getPercentRange: function () {
  53373. var axisProxy = this.findRepresentativeAxisProxy();
  53374. if (axisProxy) {
  53375. return axisProxy.getDataPercentWindow();
  53376. }
  53377. },
  53378. /**
  53379. * @public
  53380. * For example, chart.getModel().getComponent('dataZoom').getValueRange('y', 0);
  53381. *
  53382. * @param {string} [axisDimName]
  53383. * @param {number} [axisIndex]
  53384. * @return {Array.<number>} [startValue, endValue] value can only be '-' or finite number.
  53385. */
  53386. getValueRange: function (axisDimName, axisIndex) {
  53387. if (axisDimName == null && axisIndex == null) {
  53388. var axisProxy = this.findRepresentativeAxisProxy();
  53389. if (axisProxy) {
  53390. return axisProxy.getDataValueWindow();
  53391. }
  53392. }
  53393. else {
  53394. return this.getAxisProxy(axisDimName, axisIndex).getDataValueWindow();
  53395. }
  53396. },
  53397. /**
  53398. * @public
  53399. * @param {module:echarts/model/Model} [axisModel] If axisModel given, find axisProxy
  53400. * corresponding to the axisModel
  53401. * @return {module:echarts/component/dataZoom/AxisProxy}
  53402. */
  53403. findRepresentativeAxisProxy: function (axisModel) {
  53404. if (axisModel) {
  53405. return axisModel.__dzAxisProxy;
  53406. }
  53407. // Find the first hosted axisProxy
  53408. var axisProxies = this._axisProxies;
  53409. for (var key in axisProxies) {
  53410. if (axisProxies.hasOwnProperty(key) && axisProxies[key].hostedBy(this)) {
  53411. return axisProxies[key];
  53412. }
  53413. }
  53414. // If no hosted axis find not hosted axisProxy.
  53415. // Consider this case: dataZoomModel1 and dataZoomModel2 control the same axis,
  53416. // and the option.start or option.end settings are different. The percentRange
  53417. // should follow axisProxy.
  53418. // (We encounter this problem in toolbox data zoom.)
  53419. for (var key in axisProxies) {
  53420. if (axisProxies.hasOwnProperty(key) && !axisProxies[key].hostedBy(this)) {
  53421. return axisProxies[key];
  53422. }
  53423. }
  53424. },
  53425. /**
  53426. * @return {Array.<string>}
  53427. */
  53428. getRangePropMode: function () {
  53429. return this._rangePropMode.slice();
  53430. }
  53431. });
  53432. function retrieveRaw(option) {
  53433. var ret = {};
  53434. each(
  53435. ['start', 'end', 'startValue', 'endValue', 'throttle'],
  53436. function (name) {
  53437. option.hasOwnProperty(name) && (ret[name] = option[name]);
  53438. }
  53439. );
  53440. return ret;
  53441. }
  53442. function updateRangeUse(dataZoomModel, rawOption) {
  53443. each([['start', 'startValue'], ['end', 'endValue']], function (names, index) {
  53444. var rangePropMode = dataZoomModel._rangePropMode;
  53445. if (rawOption[names[0]] != null) {
  53446. rangePropMode[index] = 'percent';
  53447. }
  53448. else if (rawOption[names[1]] != null) {
  53449. rangePropMode[index] = 'value';
  53450. }
  53451. // else remain its original setting.
  53452. });
  53453. }
  53454. module.exports = DataZoomModel;
  53455. /***/ },
  53456. /* 365 */
  53457. /***/ function(module, exports, __webpack_require__) {
  53458. var formatUtil = __webpack_require__(6);
  53459. var zrUtil = __webpack_require__(4);
  53460. var helper = {};
  53461. var AXIS_DIMS = ['x', 'y', 'z', 'radius', 'angle', 'single'];
  53462. // Supported coords.
  53463. var COORDS = ['cartesian2d', 'polar', 'singleAxis'];
  53464. /**
  53465. * @param {string} coordType
  53466. * @return {boolean}
  53467. */
  53468. helper.isCoordSupported = function (coordType) {
  53469. return zrUtil.indexOf(COORDS, coordType) >= 0;
  53470. };
  53471. /**
  53472. * Create "each" method to iterate names.
  53473. *
  53474. * @pubilc
  53475. * @param {Array.<string>} names
  53476. * @param {Array.<string>=} attrs
  53477. * @return {Function}
  53478. */
  53479. helper.createNameEach = function (names, attrs) {
  53480. names = names.slice();
  53481. var capitalNames = zrUtil.map(names, formatUtil.capitalFirst);
  53482. attrs = (attrs || []).slice();
  53483. var capitalAttrs = zrUtil.map(attrs, formatUtil.capitalFirst);
  53484. return function (callback, context) {
  53485. zrUtil.each(names, function (name, index) {
  53486. var nameObj = {name: name, capital: capitalNames[index]};
  53487. for (var j = 0; j < attrs.length; j++) {
  53488. nameObj[attrs[j]] = name + capitalAttrs[j];
  53489. }
  53490. callback.call(context, nameObj);
  53491. });
  53492. };
  53493. };
  53494. /**
  53495. * Iterate each dimension name.
  53496. *
  53497. * @public
  53498. * @param {Function} callback The parameter is like:
  53499. * {
  53500. * name: 'angle',
  53501. * capital: 'Angle',
  53502. * axis: 'angleAxis',
  53503. * axisIndex: 'angleAixs',
  53504. * index: 'angleIndex'
  53505. * }
  53506. * @param {Object} context
  53507. */
  53508. helper.eachAxisDim = helper.createNameEach(AXIS_DIMS, ['axisIndex', 'axis', 'index', 'id']);
  53509. /**
  53510. * If tow dataZoomModels has the same axis controlled, we say that they are 'linked'.
  53511. * dataZoomModels and 'links' make up one or more graphics.
  53512. * This function finds the graphic where the source dataZoomModel is in.
  53513. *
  53514. * @public
  53515. * @param {Function} forEachNode Node iterator.
  53516. * @param {Function} forEachEdgeType edgeType iterator
  53517. * @param {Function} edgeIdGetter Giving node and edgeType, return an array of edge id.
  53518. * @return {Function} Input: sourceNode, Output: Like {nodes: [], dims: {}}
  53519. */
  53520. helper.createLinkedNodesFinder = function (forEachNode, forEachEdgeType, edgeIdGetter) {
  53521. return function (sourceNode) {
  53522. var result = {
  53523. nodes: [],
  53524. records: {} // key: edgeType.name, value: Object (key: edge id, value: boolean).
  53525. };
  53526. forEachEdgeType(function (edgeType) {
  53527. result.records[edgeType.name] = {};
  53528. });
  53529. if (!sourceNode) {
  53530. return result;
  53531. }
  53532. absorb(sourceNode, result);
  53533. var existsLink;
  53534. do {
  53535. existsLink = false;
  53536. forEachNode(processSingleNode);
  53537. }
  53538. while (existsLink);
  53539. function processSingleNode(node) {
  53540. if (!isNodeAbsorded(node, result) && isLinked(node, result)) {
  53541. absorb(node, result);
  53542. existsLink = true;
  53543. }
  53544. }
  53545. return result;
  53546. };
  53547. function isNodeAbsorded(node, result) {
  53548. return zrUtil.indexOf(result.nodes, node) >= 0;
  53549. }
  53550. function isLinked(node, result) {
  53551. var hasLink = false;
  53552. forEachEdgeType(function (edgeType) {
  53553. zrUtil.each(edgeIdGetter(node, edgeType) || [], function (edgeId) {
  53554. result.records[edgeType.name][edgeId] && (hasLink = true);
  53555. });
  53556. });
  53557. return hasLink;
  53558. }
  53559. function absorb(node, result) {
  53560. result.nodes.push(node);
  53561. forEachEdgeType(function (edgeType) {
  53562. zrUtil.each(edgeIdGetter(node, edgeType) || [], function (edgeId) {
  53563. result.records[edgeType.name][edgeId] = true;
  53564. });
  53565. });
  53566. }
  53567. };
  53568. module.exports = helper;
  53569. /***/ },
  53570. /* 366 */
  53571. /***/ function(module, exports, __webpack_require__) {
  53572. /**
  53573. * @file Axis operator
  53574. */
  53575. var zrUtil = __webpack_require__(4);
  53576. var numberUtil = __webpack_require__(7);
  53577. var helper = __webpack_require__(365);
  53578. var each = zrUtil.each;
  53579. var asc = numberUtil.asc;
  53580. /**
  53581. * Operate single axis.
  53582. * One axis can only operated by one axis operator.
  53583. * Different dataZoomModels may be defined to operate the same axis.
  53584. * (i.e. 'inside' data zoom and 'slider' data zoom components)
  53585. * So dataZoomModels share one axisProxy in that case.
  53586. *
  53587. * @class
  53588. */
  53589. var AxisProxy = function (dimName, axisIndex, dataZoomModel, ecModel) {
  53590. /**
  53591. * @private
  53592. * @type {string}
  53593. */
  53594. this._dimName = dimName;
  53595. /**
  53596. * @private
  53597. */
  53598. this._axisIndex = axisIndex;
  53599. /**
  53600. * @private
  53601. * @type {Array.<number>}
  53602. */
  53603. this._valueWindow;
  53604. /**
  53605. * @private
  53606. * @type {Array.<number>}
  53607. */
  53608. this._percentWindow;
  53609. /**
  53610. * @private
  53611. * @type {Array.<number>}
  53612. */
  53613. this._dataExtent;
  53614. /**
  53615. * {minSpan, maxSpan, minValueSpan, maxValueSpan}
  53616. * @private
  53617. * @type {Object}
  53618. */
  53619. this._minMaxSpan;
  53620. /**
  53621. * @readOnly
  53622. * @type {module: echarts/model/Global}
  53623. */
  53624. this.ecModel = ecModel;
  53625. /**
  53626. * @private
  53627. * @type {module: echarts/component/dataZoom/DataZoomModel}
  53628. */
  53629. this._dataZoomModel = dataZoomModel;
  53630. };
  53631. AxisProxy.prototype = {
  53632. constructor: AxisProxy,
  53633. /**
  53634. * Whether the axisProxy is hosted by dataZoomModel.
  53635. *
  53636. * @public
  53637. * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel
  53638. * @return {boolean}
  53639. */
  53640. hostedBy: function (dataZoomModel) {
  53641. return this._dataZoomModel === dataZoomModel;
  53642. },
  53643. /**
  53644. * @return {Array.<number>} Value can only be NaN or finite value.
  53645. */
  53646. getDataValueWindow: function () {
  53647. return this._valueWindow.slice();
  53648. },
  53649. /**
  53650. * @return {Array.<number>}
  53651. */
  53652. getDataPercentWindow: function () {
  53653. return this._percentWindow.slice();
  53654. },
  53655. /**
  53656. * @public
  53657. * @param {number} axisIndex
  53658. * @return {Array} seriesModels
  53659. */
  53660. getTargetSeriesModels: function () {
  53661. var seriesModels = [];
  53662. var ecModel = this.ecModel;
  53663. ecModel.eachSeries(function (seriesModel) {
  53664. if (helper.isCoordSupported(seriesModel.get('coordinateSystem'))) {
  53665. var dimName = this._dimName;
  53666. var axisModel = ecModel.queryComponents({
  53667. mainType: dimName + 'Axis',
  53668. index: seriesModel.get(dimName + 'AxisIndex'),
  53669. id: seriesModel.get(dimName + 'AxisId')
  53670. })[0];
  53671. if (this._axisIndex === (axisModel && axisModel.componentIndex)) {
  53672. seriesModels.push(seriesModel);
  53673. }
  53674. }
  53675. }, this);
  53676. return seriesModels;
  53677. },
  53678. getAxisModel: function () {
  53679. return this.ecModel.getComponent(this._dimName + 'Axis', this._axisIndex);
  53680. },
  53681. getOtherAxisModel: function () {
  53682. var axisDim = this._dimName;
  53683. var ecModel = this.ecModel;
  53684. var axisModel = this.getAxisModel();
  53685. var isCartesian = axisDim === 'x' || axisDim === 'y';
  53686. var otherAxisDim;
  53687. var coordSysIndexName;
  53688. if (isCartesian) {
  53689. coordSysIndexName = 'gridIndex';
  53690. otherAxisDim = axisDim === 'x' ? 'y' : 'x';
  53691. }
  53692. else {
  53693. coordSysIndexName = 'polarIndex';
  53694. otherAxisDim = axisDim === 'angle' ? 'radius' : 'angle';
  53695. }
  53696. var foundOtherAxisModel;
  53697. ecModel.eachComponent(otherAxisDim + 'Axis', function (otherAxisModel) {
  53698. if ((otherAxisModel.get(coordSysIndexName) || 0)
  53699. === (axisModel.get(coordSysIndexName) || 0)
  53700. ) {
  53701. foundOtherAxisModel = otherAxisModel;
  53702. }
  53703. });
  53704. return foundOtherAxisModel;
  53705. },
  53706. getMinMaxSpan: function () {
  53707. return zrUtil.clone(this._minMaxSpan);
  53708. },
  53709. /**
  53710. * Only calculate by given range and this._dataExtent, do not change anything.
  53711. *
  53712. * @param {Object} opt
  53713. * @param {number} [opt.start]
  53714. * @param {number} [opt.end]
  53715. * @param {number} [opt.startValue]
  53716. * @param {number} [opt.endValue]
  53717. */
  53718. calculateDataWindow: function (opt) {
  53719. var dataExtent = this._dataExtent;
  53720. var axisModel = this.getAxisModel();
  53721. var scale = axisModel.axis.scale;
  53722. var rangePropMode = this._dataZoomModel.getRangePropMode();
  53723. var percentExtent = [0, 100];
  53724. var percentWindow = [
  53725. opt.start,
  53726. opt.end
  53727. ];
  53728. var valueWindow = [];
  53729. each(['startValue', 'endValue'], function (prop) {
  53730. valueWindow.push(opt[prop] != null ? scale.parse(opt[prop]) : null);
  53731. });
  53732. // Normalize bound.
  53733. each([0, 1], function (idx) {
  53734. var boundValue = valueWindow[idx];
  53735. var boundPercent = percentWindow[idx];
  53736. // Notice: dataZoom is based either on `percentProp` ('start', 'end') or
  53737. // on `valueProp` ('startValue', 'endValue'). The former one is suitable
  53738. // for cases that a dataZoom component controls multiple axes with different
  53739. // unit or extent, and the latter one is suitable for accurate zoom by pixel
  53740. // (e.g., in dataZoomSelect). `valueProp` can be calculated from `percentProp`,
  53741. // but it is awkward that `percentProp` can not be obtained from `valueProp`
  53742. // accurately (because all of values that are overflow the `dataExtent` will
  53743. // be calculated to percent '100%'). So we have to use
  53744. // `dataZoom.getRangePropMode()` to mark which prop is used.
  53745. // `rangePropMode` is updated only when setOption or dispatchAction, otherwise
  53746. // it remains its original value.
  53747. if (rangePropMode[idx] === 'percent') {
  53748. if (boundPercent == null) {
  53749. boundPercent = percentExtent[idx];
  53750. }
  53751. // Use scale.parse to math round for category or time axis.
  53752. boundValue = scale.parse(numberUtil.linearMap(
  53753. boundPercent, percentExtent, dataExtent, true
  53754. ));
  53755. }
  53756. else {
  53757. // Calculating `percent` from `value` may be not accurate, because
  53758. // This calculation can not be inversed, because all of values that
  53759. // are overflow the `dataExtent` will be calculated to percent '100%'
  53760. boundPercent = numberUtil.linearMap(
  53761. boundValue, dataExtent, percentExtent, true
  53762. );
  53763. }
  53764. // valueWindow[idx] = round(boundValue);
  53765. // percentWindow[idx] = round(boundPercent);
  53766. valueWindow[idx] = boundValue;
  53767. percentWindow[idx] = boundPercent;
  53768. });
  53769. return {
  53770. valueWindow: asc(valueWindow),
  53771. percentWindow: asc(percentWindow)
  53772. };
  53773. },
  53774. /**
  53775. * Notice: reset should not be called before series.restoreData() called,
  53776. * so it is recommanded to be called in "process stage" but not "model init
  53777. * stage".
  53778. *
  53779. * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel
  53780. */
  53781. reset: function (dataZoomModel) {
  53782. if (dataZoomModel !== this._dataZoomModel) {
  53783. return;
  53784. }
  53785. // Culculate data window and data extent, and record them.
  53786. this._dataExtent = calculateDataExtent(
  53787. this, this._dimName, this.getTargetSeriesModels()
  53788. );
  53789. var dataWindow = this.calculateDataWindow(dataZoomModel.option);
  53790. this._valueWindow = dataWindow.valueWindow;
  53791. this._percentWindow = dataWindow.percentWindow;
  53792. setMinMaxSpan(this);
  53793. // Update axis setting then.
  53794. setAxisModel(this);
  53795. },
  53796. /**
  53797. * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel
  53798. */
  53799. restore: function (dataZoomModel) {
  53800. if (dataZoomModel !== this._dataZoomModel) {
  53801. return;
  53802. }
  53803. this._valueWindow = this._percentWindow = null;
  53804. setAxisModel(this, true);
  53805. },
  53806. /**
  53807. * @param {module: echarts/component/dataZoom/DataZoomModel} dataZoomModel
  53808. */
  53809. filterData: function (dataZoomModel) {
  53810. if (dataZoomModel !== this._dataZoomModel) {
  53811. return;
  53812. }
  53813. var axisDim = this._dimName;
  53814. var seriesModels = this.getTargetSeriesModels();
  53815. var filterMode = dataZoomModel.get('filterMode');
  53816. var valueWindow = this._valueWindow;
  53817. if (filterMode === 'none') {
  53818. return;
  53819. }
  53820. // FIXME
  53821. // Toolbox may has dataZoom injected. And if there are stacked bar chart
  53822. // with NaN data, NaN will be filtered and stack will be wrong.
  53823. // So we need to force the mode to be set empty.
  53824. // In fect, it is not a big deal that do not support filterMode-'filter'
  53825. // when using toolbox#dataZoom, utill tooltip#dataZoom support "single axis
  53826. // selection" some day, which might need "adapt to data extent on the
  53827. // otherAxis", which is disabled by filterMode-'empty'.
  53828. var otherAxisModel = this.getOtherAxisModel();
  53829. if (dataZoomModel.get('$fromToolbox')
  53830. && otherAxisModel
  53831. && otherAxisModel.get('type') === 'category'
  53832. ) {
  53833. filterMode = 'empty';
  53834. }
  53835. // Process series data
  53836. each(seriesModels, function (seriesModel) {
  53837. var seriesData = seriesModel.getData();
  53838. var dataDims = seriesModel.coordDimToDataDim(axisDim);
  53839. if (filterMode === 'weakFilter') {
  53840. seriesData && seriesData.filterSelf(function (dataIndex) {
  53841. var leftOut;
  53842. var rightOut;
  53843. var hasValue;
  53844. for (var i = 0; i < dataDims.length; i++) {
  53845. var value = seriesData.get(dataDims[i], dataIndex);
  53846. var thisHasValue = !isNaN(value);
  53847. var thisLeftOut = value < valueWindow[0];
  53848. var thisRightOut = value > valueWindow[1];
  53849. if (thisHasValue && !thisLeftOut && !thisRightOut) {
  53850. return true;
  53851. }
  53852. thisHasValue && (hasValue = true);
  53853. thisLeftOut && (leftOut = true);
  53854. thisRightOut && (rightOut = true);
  53855. }
  53856. // If both left out and right out, do not filter.
  53857. return hasValue && leftOut && rightOut;
  53858. });
  53859. }
  53860. else {
  53861. seriesData && each(dataDims, function (dim) {
  53862. if (filterMode === 'empty') {
  53863. seriesModel.setData(
  53864. seriesData.map(dim, function (value) {
  53865. return !isInWindow(value) ? NaN : value;
  53866. })
  53867. );
  53868. }
  53869. else {
  53870. seriesData.filterSelf(dim, isInWindow);
  53871. }
  53872. });
  53873. }
  53874. });
  53875. function isInWindow(value) {
  53876. return value >= valueWindow[0] && value <= valueWindow[1];
  53877. }
  53878. }
  53879. };
  53880. function calculateDataExtent(axisProxy, axisDim, seriesModels) {
  53881. var dataExtent = [Infinity, -Infinity];
  53882. each(seriesModels, function (seriesModel) {
  53883. var seriesData = seriesModel.getData();
  53884. if (seriesData) {
  53885. each(seriesModel.coordDimToDataDim(axisDim), function (dim) {
  53886. var seriesExtent = seriesData.getDataExtent(dim);
  53887. seriesExtent[0] < dataExtent[0] && (dataExtent[0] = seriesExtent[0]);
  53888. seriesExtent[1] > dataExtent[1] && (dataExtent[1] = seriesExtent[1]);
  53889. });
  53890. }
  53891. });
  53892. if (dataExtent[1] < dataExtent[0]) {
  53893. dataExtent = [NaN, NaN];
  53894. }
  53895. // It is important to get "consistent" extent when more then one axes is
  53896. // controlled by a `dataZoom`, otherwise those axes will not be synchronized
  53897. // when zooming. But it is difficult to know what is "consistent", considering
  53898. // axes have different type or even different meanings (For example, two
  53899. // time axes are used to compare data of the same date in different years).
  53900. // So basically dataZoom just obtains extent by series.data (in category axis
  53901. // extent can be obtained from axis.data).
  53902. // Nevertheless, user can set min/max/scale on axes to make extent of axes
  53903. // consistent.
  53904. fixExtentByAxis(axisProxy, dataExtent);
  53905. return dataExtent;
  53906. }
  53907. function fixExtentByAxis(axisProxy, dataExtent) {
  53908. var axisModel = axisProxy.getAxisModel();
  53909. var min = axisModel.getMin(true);
  53910. // For category axis, if min/max/scale are not set, extent is determined
  53911. // by axis.data by default.
  53912. var isCategoryAxis = axisModel.get('type') === 'category';
  53913. var axisDataLen = isCategoryAxis && (axisModel.get('data') || []).length;
  53914. if (min != null && min !== 'dataMin') {
  53915. dataExtent[0] = min;
  53916. }
  53917. else if (isCategoryAxis) {
  53918. dataExtent[0] = axisDataLen > 0 ? 0 : NaN;
  53919. }
  53920. var max = axisModel.getMax(true);
  53921. if (max != null && max !== 'dataMax') {
  53922. dataExtent[1] = max;
  53923. }
  53924. else if (isCategoryAxis) {
  53925. dataExtent[1] = axisDataLen > 0 ? axisDataLen - 1 : NaN;
  53926. }
  53927. if (!axisModel.get('scale', true)) {
  53928. dataExtent[0] > 0 && (dataExtent[0] = 0);
  53929. dataExtent[1] < 0 && (dataExtent[1] = 0);
  53930. }
  53931. // For value axis, if min/max/scale are not set, we just use the extent obtained
  53932. // by series data, which may be a little different from the extent calculated by
  53933. // `axisHelper.getScaleExtent`. But the different just affects the experience a
  53934. // little when zooming. So it will not be fixed until some users require it strongly.
  53935. return dataExtent;
  53936. }
  53937. function setAxisModel(axisProxy, isRestore) {
  53938. var axisModel = axisProxy.getAxisModel();
  53939. var percentWindow = axisProxy._percentWindow;
  53940. var valueWindow = axisProxy._valueWindow;
  53941. if (!percentWindow) {
  53942. return;
  53943. }
  53944. // [0, 500]: arbitrary value, guess axis extent.
  53945. var precision = numberUtil.getPixelPrecision(valueWindow, [0, 500]);
  53946. // isRestore or isFull
  53947. var useOrigin = isRestore || (percentWindow[0] === 0 && percentWindow[1] === 100);
  53948. axisModel.setRange(
  53949. useOrigin ? null : +valueWindow[0].toFixed(precision),
  53950. useOrigin ? null : +valueWindow[1].toFixed(precision)
  53951. );
  53952. }
  53953. function setMinMaxSpan(axisProxy) {
  53954. var minMaxSpan = axisProxy._minMaxSpan = {};
  53955. var dataZoomModel = axisProxy._dataZoomModel;
  53956. each(['min', 'max'], function (minMax) {
  53957. minMaxSpan[minMax + 'Span'] = dataZoomModel.get(minMax + 'Span');
  53958. // minValueSpan and maxValueSpan has higher priority than minSpan and maxSpan
  53959. var valueSpan = dataZoomModel.get(minMax + 'ValueSpan');
  53960. if (valueSpan != null) {
  53961. minMaxSpan[minMax + 'ValueSpan'] = valueSpan;
  53962. valueSpan = axisProxy.getAxisModel().axis.scale.parse(valueSpan);
  53963. if (valueSpan != null) {
  53964. minMaxSpan[minMax + 'Span'] = numberUtil.linearMap(
  53965. valueSpan, axisProxy._dataExtent, [0, 100], true
  53966. );
  53967. }
  53968. }
  53969. });
  53970. }
  53971. module.exports = AxisProxy;
  53972. /***/ },
  53973. /* 367 */
  53974. /***/ function(module, exports, __webpack_require__) {
  53975. var ComponentView = __webpack_require__(79);
  53976. module.exports = ComponentView.extend({
  53977. type: 'dataZoom',
  53978. render: function (dataZoomModel, ecModel, api, payload) {
  53979. this.dataZoomModel = dataZoomModel;
  53980. this.ecModel = ecModel;
  53981. this.api = api;
  53982. },
  53983. /**
  53984. * Find the first target coordinate system.
  53985. *
  53986. * @protected
  53987. * @return {Object} {
  53988. * grid: [
  53989. * {model: coord0, axisModels: [axis1, axis3], coordIndex: 1},
  53990. * {model: coord1, axisModels: [axis0, axis2], coordIndex: 0},
  53991. * ...
  53992. * ], // cartesians must not be null/undefined.
  53993. * polar: [
  53994. * {model: coord0, axisModels: [axis4], coordIndex: 0},
  53995. * ...
  53996. * ], // polars must not be null/undefined.
  53997. * singleAxis: [
  53998. * {model: coord0, axisModels: [], coordIndex: 0}
  53999. * ]
  54000. */
  54001. getTargetCoordInfo: function () {
  54002. var dataZoomModel = this.dataZoomModel;
  54003. var ecModel = this.ecModel;
  54004. var coordSysLists = {};
  54005. dataZoomModel.eachTargetAxis(function (dimNames, axisIndex) {
  54006. var axisModel = ecModel.getComponent(dimNames.axis, axisIndex);
  54007. if (axisModel) {
  54008. var coordModel = axisModel.getCoordSysModel();
  54009. coordModel && save(
  54010. coordModel,
  54011. axisModel,
  54012. coordSysLists[coordModel.mainType] || (coordSysLists[coordModel.mainType] = []),
  54013. coordModel.componentIndex
  54014. );
  54015. }
  54016. }, this);
  54017. function save(coordModel, axisModel, store, coordIndex) {
  54018. var item;
  54019. for (var i = 0; i < store.length; i++) {
  54020. if (store[i].model === coordModel) {
  54021. item = store[i];
  54022. break;
  54023. }
  54024. }
  54025. if (!item) {
  54026. store.push(item = {
  54027. model: coordModel, axisModels: [], coordIndex: coordIndex
  54028. });
  54029. }
  54030. item.axisModels.push(axisModel);
  54031. }
  54032. return coordSysLists;
  54033. }
  54034. });
  54035. /***/ },
  54036. /* 368 */
  54037. /***/ function(module, exports, __webpack_require__) {
  54038. /**
  54039. * @file Data zoom model
  54040. */
  54041. var DataZoomModel = __webpack_require__(364);
  54042. var SliderZoomModel = DataZoomModel.extend({
  54043. type: 'dataZoom.slider',
  54044. layoutMode: 'box',
  54045. /**
  54046. * @protected
  54047. */
  54048. defaultOption: {
  54049. show: true,
  54050. // ph => placeholder. Using placehoder here because
  54051. // deault value can only be drived in view stage.
  54052. right: 'ph', // Default align to grid rect.
  54053. top: 'ph', // Default align to grid rect.
  54054. width: 'ph', // Default align to grid rect.
  54055. height: 'ph', // Default align to grid rect.
  54056. left: null, // Default align to grid rect.
  54057. bottom: null, // Default align to grid rect.
  54058. backgroundColor: 'rgba(47,69,84,0)', // Background of slider zoom component.
  54059. // dataBackgroundColor: '#ddd', // Background coor of data shadow and border of box,
  54060. // highest priority, remain for compatibility of
  54061. // previous version, but not recommended any more.
  54062. dataBackground: {
  54063. lineStyle: {
  54064. color: '#2f4554',
  54065. width: 0.5,
  54066. opacity: 0.3
  54067. },
  54068. areaStyle: {
  54069. color: 'rgba(47,69,84,0.3)',
  54070. opacity: 0.3
  54071. }
  54072. },
  54073. borderColor: '#ddd', // border color of the box. For compatibility,
  54074. // if dataBackgroundColor is set, borderColor
  54075. // is ignored.
  54076. fillerColor: 'rgba(167,183,204,0.4)', // Color of selected area.
  54077. // handleColor: 'rgba(89,170,216,0.95)', // Color of handle.
  54078. // handleIcon: 'path://M4.9,17.8c0-1.4,4.5-10.5,5.5-12.4c0-0.1,0.6-1.1,0.9-1.1c0.4,0,0.9,1,0.9,1.1c1.1,2.2,5.4,11,5.4,12.4v17.8c0,1.5-0.6,2.1-1.3,2.1H6.1c-0.7,0-1.3-0.6-1.3-2.1V17.8z',
  54079. handleIcon: 'M8.2,13.6V3.9H6.3v9.7H3.1v14.9h3.3v9.7h1.8v-9.7h3.3V13.6H8.2z M9.7,24.4H4.8v-1.4h4.9V24.4z M9.7,19.1H4.8v-1.4h4.9V19.1z',
  54080. // Percent of the slider height
  54081. handleSize: '100%',
  54082. handleStyle: {
  54083. color: '#a7b7cc'
  54084. },
  54085. labelPrecision: null,
  54086. labelFormatter: null,
  54087. showDetail: true,
  54088. showDataShadow: 'auto', // Default auto decision.
  54089. realtime: true,
  54090. zoomLock: false, // Whether disable zoom.
  54091. textStyle: {
  54092. color: '#333'
  54093. }
  54094. }
  54095. });
  54096. module.exports = SliderZoomModel;
  54097. /***/ },
  54098. /* 369 */
  54099. /***/ function(module, exports, __webpack_require__) {
  54100. var zrUtil = __webpack_require__(4);
  54101. var graphic = __webpack_require__(18);
  54102. var throttle = __webpack_require__(81);
  54103. var DataZoomView = __webpack_require__(367);
  54104. var Rect = graphic.Rect;
  54105. var numberUtil = __webpack_require__(7);
  54106. var linearMap = numberUtil.linearMap;
  54107. var layout = __webpack_require__(71);
  54108. var sliderMove = __webpack_require__(238);
  54109. var eventTool = __webpack_require__(88);
  54110. var asc = numberUtil.asc;
  54111. var bind = zrUtil.bind;
  54112. // var mathMax = Math.max;
  54113. var each = zrUtil.each;
  54114. // Constants
  54115. var DEFAULT_LOCATION_EDGE_GAP = 7;
  54116. var DEFAULT_FRAME_BORDER_WIDTH = 1;
  54117. var DEFAULT_FILLER_SIZE = 30;
  54118. var HORIZONTAL = 'horizontal';
  54119. var VERTICAL = 'vertical';
  54120. var LABEL_GAP = 5;
  54121. var SHOW_DATA_SHADOW_SERIES_TYPE = ['line', 'bar', 'candlestick', 'scatter'];
  54122. var SliderZoomView = DataZoomView.extend({
  54123. type: 'dataZoom.slider',
  54124. init: function (ecModel, api) {
  54125. /**
  54126. * @private
  54127. * @type {Object}
  54128. */
  54129. this._displayables = {};
  54130. /**
  54131. * @private
  54132. * @type {string}
  54133. */
  54134. this._orient;
  54135. /**
  54136. * [0, 100]
  54137. * @private
  54138. */
  54139. this._range;
  54140. /**
  54141. * [coord of the first handle, coord of the second handle]
  54142. * @private
  54143. */
  54144. this._handleEnds;
  54145. /**
  54146. * [length, thick]
  54147. * @private
  54148. * @type {Array.<number>}
  54149. */
  54150. this._size;
  54151. /**
  54152. * @private
  54153. * @type {number}
  54154. */
  54155. this._handleWidth;
  54156. /**
  54157. * @private
  54158. * @type {number}
  54159. */
  54160. this._handleHeight;
  54161. /**
  54162. * @private
  54163. */
  54164. this._location;
  54165. /**
  54166. * @private
  54167. */
  54168. this._dragging;
  54169. /**
  54170. * @private
  54171. */
  54172. this._dataShadowInfo;
  54173. this.api = api;
  54174. },
  54175. /**
  54176. * @override
  54177. */
  54178. render: function (dataZoomModel, ecModel, api, payload) {
  54179. SliderZoomView.superApply(this, 'render', arguments);
  54180. throttle.createOrUpdate(
  54181. this,
  54182. '_dispatchZoomAction',
  54183. this.dataZoomModel.get('throttle'),
  54184. 'fixRate'
  54185. );
  54186. this._orient = dataZoomModel.get('orient');
  54187. if (this.dataZoomModel.get('show') === false) {
  54188. this.group.removeAll();
  54189. return;
  54190. }
  54191. // Notice: this._resetInterval() should not be executed when payload.type
  54192. // is 'dataZoom', origin this._range should be maintained, otherwise 'pan'
  54193. // or 'zoom' info will be missed because of 'throttle' of this.dispatchAction,
  54194. if (!payload || payload.type !== 'dataZoom' || payload.from !== this.uid) {
  54195. this._buildView();
  54196. }
  54197. this._updateView();
  54198. },
  54199. /**
  54200. * @override
  54201. */
  54202. remove: function () {
  54203. SliderZoomView.superApply(this, 'remove', arguments);
  54204. throttle.clear(this, '_dispatchZoomAction');
  54205. },
  54206. /**
  54207. * @override
  54208. */
  54209. dispose: function () {
  54210. SliderZoomView.superApply(this, 'dispose', arguments);
  54211. throttle.clear(this, '_dispatchZoomAction');
  54212. },
  54213. _buildView: function () {
  54214. var thisGroup = this.group;
  54215. thisGroup.removeAll();
  54216. this._resetLocation();
  54217. this._resetInterval();
  54218. var barGroup = this._displayables.barGroup = new graphic.Group();
  54219. this._renderBackground();
  54220. this._renderHandle();
  54221. this._renderDataShadow();
  54222. thisGroup.add(barGroup);
  54223. this._positionGroup();
  54224. },
  54225. /**
  54226. * @private
  54227. */
  54228. _resetLocation: function () {
  54229. var dataZoomModel = this.dataZoomModel;
  54230. var api = this.api;
  54231. // If some of x/y/width/height are not specified,
  54232. // auto-adapt according to target grid.
  54233. var coordRect = this._findCoordRect();
  54234. var ecSize = {width: api.getWidth(), height: api.getHeight()};
  54235. // Default align by coordinate system rect.
  54236. var positionInfo = this._orient === HORIZONTAL
  54237. ? {
  54238. // Why using 'right', because right should be used in vertical,
  54239. // and it is better to be consistent for dealing with position param merge.
  54240. right: ecSize.width - coordRect.x - coordRect.width,
  54241. top: (ecSize.height - DEFAULT_FILLER_SIZE - DEFAULT_LOCATION_EDGE_GAP),
  54242. width: coordRect.width,
  54243. height: DEFAULT_FILLER_SIZE
  54244. }
  54245. : { // vertical
  54246. right: DEFAULT_LOCATION_EDGE_GAP,
  54247. top: coordRect.y,
  54248. width: DEFAULT_FILLER_SIZE,
  54249. height: coordRect.height
  54250. };
  54251. // Do not write back to option and replace value 'ph', because
  54252. // the 'ph' value should be recalculated when resize.
  54253. var layoutParams = layout.getLayoutParams(dataZoomModel.option);
  54254. // Replace the placeholder value.
  54255. zrUtil.each(['right', 'top', 'width', 'height'], function (name) {
  54256. if (layoutParams[name] === 'ph') {
  54257. layoutParams[name] = positionInfo[name];
  54258. }
  54259. });
  54260. var layoutRect = layout.getLayoutRect(
  54261. layoutParams,
  54262. ecSize,
  54263. dataZoomModel.padding
  54264. );
  54265. this._location = {x: layoutRect.x, y: layoutRect.y};
  54266. this._size = [layoutRect.width, layoutRect.height];
  54267. this._orient === VERTICAL && this._size.reverse();
  54268. },
  54269. /**
  54270. * @private
  54271. */
  54272. _positionGroup: function () {
  54273. var thisGroup = this.group;
  54274. var location = this._location;
  54275. var orient = this._orient;
  54276. // Just use the first axis to determine mapping.
  54277. var targetAxisModel = this.dataZoomModel.getFirstTargetAxisModel();
  54278. var inverse = targetAxisModel && targetAxisModel.get('inverse');
  54279. var barGroup = this._displayables.barGroup;
  54280. var otherAxisInverse = (this._dataShadowInfo || {}).otherAxisInverse;
  54281. // Transform barGroup.
  54282. barGroup.attr(
  54283. (orient === HORIZONTAL && !inverse)
  54284. ? {scale: otherAxisInverse ? [1, 1] : [1, -1]}
  54285. : (orient === HORIZONTAL && inverse)
  54286. ? {scale: otherAxisInverse ? [-1, 1] : [-1, -1]}
  54287. : (orient === VERTICAL && !inverse)
  54288. ? {scale: otherAxisInverse ? [1, -1] : [1, 1], rotation: Math.PI / 2}
  54289. // Dont use Math.PI, considering shadow direction.
  54290. : {scale: otherAxisInverse ? [-1, -1] : [-1, 1], rotation: Math.PI / 2}
  54291. );
  54292. // Position barGroup
  54293. var rect = thisGroup.getBoundingRect([barGroup]);
  54294. thisGroup.attr('position', [location.x - rect.x, location.y - rect.y]);
  54295. },
  54296. /**
  54297. * @private
  54298. */
  54299. _getViewExtent: function () {
  54300. return [0, this._size[0]];
  54301. },
  54302. _renderBackground: function () {
  54303. var dataZoomModel = this.dataZoomModel;
  54304. var size = this._size;
  54305. var barGroup = this._displayables.barGroup;
  54306. barGroup.add(new Rect({
  54307. silent: true,
  54308. shape: {
  54309. x: 0, y: 0, width: size[0], height: size[1]
  54310. },
  54311. style: {
  54312. fill: dataZoomModel.get('backgroundColor')
  54313. },
  54314. z2: -40
  54315. }));
  54316. // Click panel, over shadow, below handles.
  54317. barGroup.add(new Rect({
  54318. shape: {
  54319. x: 0, y: 0, width: size[0], height: size[1]
  54320. },
  54321. style: {
  54322. fill: 'transparent'
  54323. },
  54324. z2: 0,
  54325. onclick: zrUtil.bind(this._onClickPanelClick, this)
  54326. }));
  54327. },
  54328. _renderDataShadow: function () {
  54329. var info = this._dataShadowInfo = this._prepareDataShadowInfo();
  54330. if (!info) {
  54331. return;
  54332. }
  54333. var size = this._size;
  54334. var seriesModel = info.series;
  54335. var data = seriesModel.getRawData();
  54336. var otherDim = seriesModel.getShadowDim
  54337. ? seriesModel.getShadowDim() // @see candlestick
  54338. : info.otherDim;
  54339. if (otherDim == null) {
  54340. return;
  54341. }
  54342. var otherDataExtent = data.getDataExtent(otherDim);
  54343. // Nice extent.
  54344. var otherOffset = (otherDataExtent[1] - otherDataExtent[0]) * 0.3;
  54345. otherDataExtent = [
  54346. otherDataExtent[0] - otherOffset,
  54347. otherDataExtent[1] + otherOffset
  54348. ];
  54349. var otherShadowExtent = [0, size[1]];
  54350. var thisShadowExtent = [0, size[0]];
  54351. var areaPoints = [[size[0], 0], [0, 0]];
  54352. var linePoints = [];
  54353. var step = thisShadowExtent[1] / (data.count() - 1);
  54354. var thisCoord = 0;
  54355. // Optimize for large data shadow
  54356. var stride = Math.round(data.count() / size[0]);
  54357. var lastIsEmpty;
  54358. data.each([otherDim], function (value, index) {
  54359. if (stride > 0 && (index % stride)) {
  54360. thisCoord += step;
  54361. return;
  54362. }
  54363. // FIXME
  54364. // Should consider axis.min/axis.max when drawing dataShadow.
  54365. // FIXME
  54366. // 应该使用统一的空判断?还是在list里进行空判断?
  54367. var isEmpty = value == null || isNaN(value) || value === '';
  54368. // See #4235.
  54369. var otherCoord = isEmpty
  54370. ? 0 : linearMap(value, otherDataExtent, otherShadowExtent, true);
  54371. // Attempt to draw data shadow precisely when there are empty value.
  54372. if (isEmpty && !lastIsEmpty && index) {
  54373. areaPoints.push([areaPoints[areaPoints.length - 1][0], 0]);
  54374. linePoints.push([linePoints[linePoints.length - 1][0], 0]);
  54375. }
  54376. else if (!isEmpty && lastIsEmpty) {
  54377. areaPoints.push([thisCoord, 0]);
  54378. linePoints.push([thisCoord, 0]);
  54379. }
  54380. areaPoints.push([thisCoord, otherCoord]);
  54381. linePoints.push([thisCoord, otherCoord]);
  54382. thisCoord += step;
  54383. lastIsEmpty = isEmpty;
  54384. });
  54385. var dataZoomModel = this.dataZoomModel;
  54386. // var dataBackgroundModel = dataZoomModel.getModel('dataBackground');
  54387. this._displayables.barGroup.add(new graphic.Polygon({
  54388. shape: {points: areaPoints},
  54389. style: zrUtil.defaults(
  54390. {fill: dataZoomModel.get('dataBackgroundColor')},
  54391. dataZoomModel.getModel('dataBackground.areaStyle').getAreaStyle()
  54392. ),
  54393. silent: true,
  54394. z2: -20
  54395. }));
  54396. this._displayables.barGroup.add(new graphic.Polyline({
  54397. shape: {points: linePoints},
  54398. style: dataZoomModel.getModel('dataBackground.lineStyle').getLineStyle(),
  54399. silent: true,
  54400. z2: -19
  54401. }));
  54402. },
  54403. _prepareDataShadowInfo: function () {
  54404. var dataZoomModel = this.dataZoomModel;
  54405. var showDataShadow = dataZoomModel.get('showDataShadow');
  54406. if (showDataShadow === false) {
  54407. return;
  54408. }
  54409. // Find a representative series.
  54410. var result;
  54411. var ecModel = this.ecModel;
  54412. dataZoomModel.eachTargetAxis(function (dimNames, axisIndex) {
  54413. var seriesModels = dataZoomModel
  54414. .getAxisProxy(dimNames.name, axisIndex)
  54415. .getTargetSeriesModels();
  54416. zrUtil.each(seriesModels, function (seriesModel) {
  54417. if (result) {
  54418. return;
  54419. }
  54420. if (showDataShadow !== true && zrUtil.indexOf(
  54421. SHOW_DATA_SHADOW_SERIES_TYPE, seriesModel.get('type')
  54422. ) < 0
  54423. ) {
  54424. return;
  54425. }
  54426. var thisAxis = ecModel.getComponent(dimNames.axis, axisIndex).axis;
  54427. var otherDim = getOtherDim(dimNames.name);
  54428. var otherAxisInverse;
  54429. var coordSys = seriesModel.coordinateSystem;
  54430. if (otherDim != null && coordSys.getOtherAxis) {
  54431. otherAxisInverse = coordSys.getOtherAxis(thisAxis).inverse;
  54432. }
  54433. result = {
  54434. thisAxis: thisAxis,
  54435. series: seriesModel,
  54436. thisDim: dimNames.name,
  54437. otherDim: otherDim,
  54438. otherAxisInverse: otherAxisInverse
  54439. };
  54440. }, this);
  54441. }, this);
  54442. return result;
  54443. },
  54444. _renderHandle: function () {
  54445. var displaybles = this._displayables;
  54446. var handles = displaybles.handles = [];
  54447. var handleLabels = displaybles.handleLabels = [];
  54448. var barGroup = this._displayables.barGroup;
  54449. var size = this._size;
  54450. var dataZoomModel = this.dataZoomModel;
  54451. barGroup.add(displaybles.filler = new Rect({
  54452. draggable: true,
  54453. cursor: 'move',
  54454. drift: bind(this._onDragMove, this, 'all'),
  54455. onmousemove: function (e) {
  54456. // Fot mobile devicem, prevent screen slider on the button.
  54457. eventTool.stop(e.event);
  54458. },
  54459. ondragstart: bind(this._showDataInfo, this, true),
  54460. ondragend: bind(this._onDragEnd, this),
  54461. onmouseover: bind(this._showDataInfo, this, true),
  54462. onmouseout: bind(this._showDataInfo, this, false),
  54463. style: {
  54464. fill: dataZoomModel.get('fillerColor'),
  54465. textPosition : 'inside'
  54466. }
  54467. }));
  54468. // Frame border.
  54469. barGroup.add(new Rect(graphic.subPixelOptimizeRect({
  54470. silent: true,
  54471. shape: {
  54472. x: 0,
  54473. y: 0,
  54474. width: size[0],
  54475. height: size[1]
  54476. },
  54477. style: {
  54478. stroke: dataZoomModel.get('dataBackgroundColor')
  54479. || dataZoomModel.get('borderColor'),
  54480. lineWidth: DEFAULT_FRAME_BORDER_WIDTH,
  54481. fill: 'rgba(0,0,0,0)'
  54482. }
  54483. })));
  54484. var iconStr = dataZoomModel.get('handleIcon');
  54485. each([0, 1], function (handleIndex) {
  54486. var iconOpt = {
  54487. style: {
  54488. strokeNoScale: true
  54489. },
  54490. rectHover: true,
  54491. cursor: this._orient === 'vertical' ? 'ns-resize' : 'ew-resize',
  54492. draggable: true,
  54493. drift: bind(this._onDragMove, this, handleIndex),
  54494. onmousemove: function (e) {
  54495. // Fot mobile devicem, prevent screen slider on the button.
  54496. eventTool.stop(e.event);
  54497. },
  54498. ondragend: bind(this._onDragEnd, this),
  54499. onmouseover: bind(this._showDataInfo, this, true),
  54500. onmouseout: bind(this._showDataInfo, this, false)
  54501. };
  54502. var iconStyle = {x: -1, y: 0, width: 2, height: 2};
  54503. var path = iconStr.indexOf('image://') === 0
  54504. ? (
  54505. iconStyle.image = iconStr.slice(8),
  54506. iconOpt.style = iconStyle,
  54507. new graphic.Image(iconOpt)
  54508. )
  54509. : graphic.makePath(
  54510. iconStr.replace('path://', ''),
  54511. iconOpt,
  54512. iconStyle,
  54513. 'center'
  54514. );
  54515. var bRect = path.getBoundingRect();
  54516. this._handleHeight = numberUtil.parsePercent(dataZoomModel.get('handleSize'), this._size[1]);
  54517. this._handleWidth = bRect.width / bRect.height * this._handleHeight;
  54518. path.setStyle(dataZoomModel.getModel('handleStyle').getItemStyle());
  54519. var handleColor = dataZoomModel.get('handleColor');
  54520. // Compatitable with previous version
  54521. if (handleColor != null) {
  54522. path.style.fill = handleColor;
  54523. }
  54524. barGroup.add(handles[handleIndex] = path);
  54525. var textStyleModel = dataZoomModel.textStyleModel;
  54526. this.group.add(
  54527. handleLabels[handleIndex] = new graphic.Text({
  54528. silent: true,
  54529. invisible: true,
  54530. style: {
  54531. x: 0, y: 0, text: '',
  54532. textVerticalAlign: 'middle',
  54533. textAlign: 'center',
  54534. fill: textStyleModel.getTextColor(),
  54535. textFont: textStyleModel.getFont()
  54536. },
  54537. z2: 10
  54538. }));
  54539. }, this);
  54540. },
  54541. /**
  54542. * @private
  54543. */
  54544. _resetInterval: function () {
  54545. var range = this._range = this.dataZoomModel.getPercentRange();
  54546. var viewExtent = this._getViewExtent();
  54547. this._handleEnds = [
  54548. linearMap(range[0], [0, 100], viewExtent, true),
  54549. linearMap(range[1], [0, 100], viewExtent, true)
  54550. ];
  54551. },
  54552. /**
  54553. * @private
  54554. * @param {(number|string)} handleIndex 0 or 1 or 'all'
  54555. * @param {number} delta
  54556. */
  54557. _updateInterval: function (handleIndex, delta) {
  54558. var dataZoomModel = this.dataZoomModel;
  54559. var handleEnds = this._handleEnds;
  54560. var viewExtend = this._getViewExtent();
  54561. var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan();
  54562. var percentExtent = [0, 100];
  54563. sliderMove(
  54564. delta,
  54565. handleEnds,
  54566. viewExtend,
  54567. dataZoomModel.get('zoomLock') ? 'all' : handleIndex,
  54568. minMaxSpan.minSpan != null
  54569. ? linearMap(minMaxSpan.minSpan, percentExtent, viewExtend, true) : null,
  54570. minMaxSpan.maxSpan != null
  54571. ? linearMap(minMaxSpan.maxSpan, percentExtent, viewExtend, true) : null
  54572. );
  54573. this._range = asc([
  54574. linearMap(handleEnds[0], viewExtend, percentExtent, true),
  54575. linearMap(handleEnds[1], viewExtend, percentExtent, true)
  54576. ]);
  54577. },
  54578. /**
  54579. * @private
  54580. */
  54581. _updateView: function (nonRealtime) {
  54582. var displaybles = this._displayables;
  54583. var handleEnds = this._handleEnds;
  54584. var handleInterval = asc(handleEnds.slice());
  54585. var size = this._size;
  54586. each([0, 1], function (handleIndex) {
  54587. // Handles
  54588. var handle = displaybles.handles[handleIndex];
  54589. var handleHeight = this._handleHeight;
  54590. handle.attr({
  54591. scale: [handleHeight / 2, handleHeight / 2],
  54592. position: [handleEnds[handleIndex], size[1] / 2 - handleHeight / 2]
  54593. });
  54594. }, this);
  54595. // Filler
  54596. displaybles.filler.setShape({
  54597. x: handleInterval[0],
  54598. y: 0,
  54599. width: handleInterval[1] - handleInterval[0],
  54600. height: size[1]
  54601. });
  54602. this._updateDataInfo(nonRealtime);
  54603. },
  54604. /**
  54605. * @private
  54606. */
  54607. _updateDataInfo: function (nonRealtime) {
  54608. var dataZoomModel = this.dataZoomModel;
  54609. var displaybles = this._displayables;
  54610. var handleLabels = displaybles.handleLabels;
  54611. var orient = this._orient;
  54612. var labelTexts = ['', ''];
  54613. // FIXME
  54614. // date型,支持formatter,autoformatter(ec2 date.getAutoFormatter)
  54615. if (dataZoomModel.get('showDetail')) {
  54616. var axisProxy = dataZoomModel.findRepresentativeAxisProxy();
  54617. if (axisProxy) {
  54618. var axis = axisProxy.getAxisModel().axis;
  54619. var range = this._range;
  54620. var dataInterval = nonRealtime
  54621. // See #4434, data and axis are not processed and reset yet in non-realtime mode.
  54622. ? axisProxy.calculateDataWindow({
  54623. start: range[0], end: range[1]
  54624. }).valueWindow
  54625. : axisProxy.getDataValueWindow();
  54626. labelTexts = [
  54627. this._formatLabel(dataInterval[0], axis),
  54628. this._formatLabel(dataInterval[1], axis)
  54629. ];
  54630. }
  54631. }
  54632. var orderedHandleEnds = asc(this._handleEnds.slice());
  54633. setLabel.call(this, 0);
  54634. setLabel.call(this, 1);
  54635. function setLabel(handleIndex) {
  54636. // Label
  54637. // Text should not transform by barGroup.
  54638. // Ignore handlers transform
  54639. var barTransform = graphic.getTransform(
  54640. displaybles.handles[handleIndex].parent, this.group
  54641. );
  54642. var direction = graphic.transformDirection(
  54643. handleIndex === 0 ? 'right' : 'left', barTransform
  54644. );
  54645. var offset = this._handleWidth / 2 + LABEL_GAP;
  54646. var textPoint = graphic.applyTransform(
  54647. [
  54648. orderedHandleEnds[handleIndex] + (handleIndex === 0 ? -offset : offset),
  54649. this._size[1] / 2
  54650. ],
  54651. barTransform
  54652. );
  54653. handleLabels[handleIndex].setStyle({
  54654. x: textPoint[0],
  54655. y: textPoint[1],
  54656. textVerticalAlign: orient === HORIZONTAL ? 'middle' : direction,
  54657. textAlign: orient === HORIZONTAL ? direction : 'center',
  54658. text: labelTexts[handleIndex]
  54659. });
  54660. }
  54661. },
  54662. /**
  54663. * @private
  54664. */
  54665. _formatLabel: function (value, axis) {
  54666. var dataZoomModel = this.dataZoomModel;
  54667. var labelFormatter = dataZoomModel.get('labelFormatter');
  54668. var labelPrecision = dataZoomModel.get('labelPrecision');
  54669. if (labelPrecision == null || labelPrecision === 'auto') {
  54670. labelPrecision = axis.getPixelPrecision();
  54671. }
  54672. var valueStr = (value == null || isNaN(value))
  54673. ? ''
  54674. // FIXME Glue code
  54675. : (axis.type === 'category' || axis.type === 'time')
  54676. ? axis.scale.getLabel(Math.round(value))
  54677. // param of toFixed should less then 20.
  54678. : value.toFixed(Math.min(labelPrecision, 20));
  54679. return zrUtil.isFunction(labelFormatter)
  54680. ? labelFormatter(value, valueStr)
  54681. : zrUtil.isString(labelFormatter)
  54682. ? labelFormatter.replace('{value}', valueStr)
  54683. : valueStr;
  54684. },
  54685. /**
  54686. * @private
  54687. * @param {boolean} showOrHide true: show, false: hide
  54688. */
  54689. _showDataInfo: function (showOrHide) {
  54690. // Always show when drgging.
  54691. showOrHide = this._dragging || showOrHide;
  54692. var handleLabels = this._displayables.handleLabels;
  54693. handleLabels[0].attr('invisible', !showOrHide);
  54694. handleLabels[1].attr('invisible', !showOrHide);
  54695. },
  54696. _onDragMove: function (handleIndex, dx, dy) {
  54697. this._dragging = true;
  54698. // Transform dx, dy to bar coordination.
  54699. var barTransform = this._displayables.barGroup.getLocalTransform();
  54700. var vertex = graphic.applyTransform([dx, dy], barTransform, true);
  54701. this._updateInterval(handleIndex, vertex[0]);
  54702. var realtime = this.dataZoomModel.get('realtime');
  54703. this._updateView(!realtime);
  54704. if (realtime) {
  54705. realtime && this._dispatchZoomAction();
  54706. }
  54707. },
  54708. _onDragEnd: function () {
  54709. this._dragging = false;
  54710. this._showDataInfo(false);
  54711. this._dispatchZoomAction();
  54712. },
  54713. _onClickPanelClick: function (e) {
  54714. var size = this._size;
  54715. var localPoint = this._displayables.barGroup.transformCoordToLocal(e.offsetX, e.offsetY);
  54716. if (localPoint[0] < 0 || localPoint[0] > size[0]
  54717. || localPoint[1] < 0 || localPoint[1] > size[1]
  54718. ) {
  54719. return;
  54720. }
  54721. var handleEnds = this._handleEnds;
  54722. var center = (handleEnds[0] + handleEnds[1]) / 2;
  54723. this._updateInterval('all', localPoint[0] - center);
  54724. this._updateView();
  54725. this._dispatchZoomAction();
  54726. },
  54727. /**
  54728. * This action will be throttled.
  54729. * @private
  54730. */
  54731. _dispatchZoomAction: function () {
  54732. var range = this._range;
  54733. this.api.dispatchAction({
  54734. type: 'dataZoom',
  54735. from: this.uid,
  54736. dataZoomId: this.dataZoomModel.id,
  54737. start: range[0],
  54738. end: range[1]
  54739. });
  54740. },
  54741. /**
  54742. * @private
  54743. */
  54744. _findCoordRect: function () {
  54745. // Find the grid coresponding to the first axis referred by dataZoom.
  54746. var rect;
  54747. each(this.getTargetCoordInfo(), function (coordInfoList) {
  54748. if (!rect && coordInfoList.length) {
  54749. var coordSys = coordInfoList[0].model.coordinateSystem;
  54750. rect = coordSys.getRect && coordSys.getRect();
  54751. }
  54752. });
  54753. if (!rect) {
  54754. var width = this.api.getWidth();
  54755. var height = this.api.getHeight();
  54756. rect = {
  54757. x: width * 0.2,
  54758. y: height * 0.2,
  54759. width: width * 0.6,
  54760. height: height * 0.6
  54761. };
  54762. }
  54763. return rect;
  54764. }
  54765. });
  54766. function getOtherDim(thisDim) {
  54767. // FIXME
  54768. // 这个逻辑和getOtherAxis里一致,但是写在这里是否不好
  54769. var map = {x: 'y', y: 'x', radius: 'angle', angle: 'radius'};
  54770. return map[thisDim];
  54771. }
  54772. module.exports = SliderZoomView;
  54773. /***/ },
  54774. /* 370 */
  54775. /***/ function(module, exports, __webpack_require__) {
  54776. /**
  54777. * @file Data zoom model
  54778. */
  54779. module.exports = __webpack_require__(364).extend({
  54780. type: 'dataZoom.inside',
  54781. /**
  54782. * @protected
  54783. */
  54784. defaultOption: {
  54785. disabled: false, // Whether disable this inside zoom.
  54786. zoomLock: false, // Whether disable zoom but only pan.
  54787. zoomOnMouseWheel: true, // Can be: true / false / 'shift' / 'ctrl' / 'alt'.
  54788. moveOnMouseMove: true, // Can be: true / false / 'shift' / 'ctrl' / 'alt'.
  54789. preventDefaultMouseMove: true
  54790. }
  54791. });
  54792. /***/ },
  54793. /* 371 */
  54794. /***/ function(module, exports, __webpack_require__) {
  54795. var DataZoomView = __webpack_require__(367);
  54796. var zrUtil = __webpack_require__(4);
  54797. var sliderMove = __webpack_require__(238);
  54798. var roams = __webpack_require__(372);
  54799. var bind = zrUtil.bind;
  54800. var InsideZoomView = DataZoomView.extend({
  54801. type: 'dataZoom.inside',
  54802. /**
  54803. * @override
  54804. */
  54805. init: function (ecModel, api) {
  54806. /**
  54807. * 'throttle' is used in this.dispatchAction, so we save range
  54808. * to avoid missing some 'pan' info.
  54809. * @private
  54810. * @type {Array.<number>}
  54811. */
  54812. this._range;
  54813. },
  54814. /**
  54815. * @override
  54816. */
  54817. render: function (dataZoomModel, ecModel, api, payload) {
  54818. InsideZoomView.superApply(this, 'render', arguments);
  54819. // Notice: origin this._range should be maintained, and should not be re-fetched
  54820. // from dataZoomModel when payload.type is 'dataZoom', otherwise 'pan' or 'zoom'
  54821. // info will be missed because of 'throttle' of this.dispatchAction.
  54822. if (roams.shouldRecordRange(payload, dataZoomModel.id)) {
  54823. this._range = dataZoomModel.getPercentRange();
  54824. }
  54825. // Reset controllers.
  54826. zrUtil.each(this.getTargetCoordInfo(), function (coordInfoList, coordSysName) {
  54827. var allCoordIds = zrUtil.map(coordInfoList, function (coordInfo) {
  54828. return roams.generateCoordId(coordInfo.model);
  54829. });
  54830. zrUtil.each(coordInfoList, function (coordInfo) {
  54831. var coordModel = coordInfo.model;
  54832. var dataZoomOption = dataZoomModel.option;
  54833. roams.register(
  54834. api,
  54835. {
  54836. coordId: roams.generateCoordId(coordModel),
  54837. allCoordIds: allCoordIds,
  54838. containsPoint: function (e, x, y) {
  54839. return coordModel.coordinateSystem.containPoint([x, y]);
  54840. },
  54841. dataZoomId: dataZoomModel.id,
  54842. throttleRate: dataZoomModel.get('throttle', true),
  54843. panGetRange: bind(this._onPan, this, coordInfo, coordSysName),
  54844. zoomGetRange: bind(this._onZoom, this, coordInfo, coordSysName),
  54845. zoomLock: dataZoomOption.zoomLock,
  54846. disabled: dataZoomOption.disabled,
  54847. roamControllerOpt: {
  54848. zoomOnMouseWheel: dataZoomOption.zoomOnMouseWheel,
  54849. moveOnMouseMove: dataZoomOption.moveOnMouseMove,
  54850. preventDefaultMouseMove: dataZoomOption.preventDefaultMouseMove
  54851. }
  54852. }
  54853. );
  54854. }, this);
  54855. }, this);
  54856. },
  54857. /**
  54858. * @override
  54859. */
  54860. dispose: function () {
  54861. roams.unregister(this.api, this.dataZoomModel.id);
  54862. InsideZoomView.superApply(this, 'dispose', arguments);
  54863. this._range = null;
  54864. },
  54865. /**
  54866. * @private
  54867. */
  54868. _onPan: function (coordInfo, coordSysName, controller, dx, dy, oldX, oldY, newX, newY) {
  54869. var range = this._range.slice();
  54870. // Calculate transform by the first axis.
  54871. var axisModel = coordInfo.axisModels[0];
  54872. if (!axisModel) {
  54873. return;
  54874. }
  54875. var directionInfo = getDirectionInfo[coordSysName](
  54876. [oldX, oldY], [newX, newY], axisModel, controller, coordInfo
  54877. );
  54878. var percentDelta = directionInfo.signal
  54879. * (range[1] - range[0])
  54880. * directionInfo.pixel / directionInfo.pixelLength;
  54881. sliderMove(percentDelta, range, [0, 100], 'all');
  54882. return (this._range = range);
  54883. },
  54884. /**
  54885. * @private
  54886. */
  54887. _onZoom: function (coordInfo, coordSysName, controller, scale, mouseX, mouseY) {
  54888. var range = this._range.slice();
  54889. // Calculate transform by the first axis.
  54890. var axisModel = coordInfo.axisModels[0];
  54891. if (!axisModel) {
  54892. return;
  54893. }
  54894. var directionInfo = getDirectionInfo[coordSysName](
  54895. null, [mouseX, mouseY], axisModel, controller, coordInfo
  54896. );
  54897. var percentPoint = (directionInfo.pixel - directionInfo.pixelStart) /
  54898. directionInfo.pixelLength * (range[1] - range[0]) + range[0];
  54899. scale = Math.max(1 / scale, 0);
  54900. range[0] = (range[0] - percentPoint) * scale + percentPoint;
  54901. range[1] = (range[1] - percentPoint) * scale + percentPoint;
  54902. // Restrict range.
  54903. var minMaxSpan = this.dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan();
  54904. sliderMove(0, range, [0, 100], 0, minMaxSpan.minSpan, minMaxSpan.maxSpan);
  54905. return (this._range = range);
  54906. }
  54907. });
  54908. var getDirectionInfo = {
  54909. grid: function (oldPoint, newPoint, axisModel, controller, coordInfo) {
  54910. var axis = axisModel.axis;
  54911. var ret = {};
  54912. var rect = coordInfo.model.coordinateSystem.getRect();
  54913. oldPoint = oldPoint || [0, 0];
  54914. if (axis.dim === 'x') {
  54915. ret.pixel = newPoint[0] - oldPoint[0];
  54916. ret.pixelLength = rect.width;
  54917. ret.pixelStart = rect.x;
  54918. ret.signal = axis.inverse ? 1 : -1;
  54919. }
  54920. else { // axis.dim === 'y'
  54921. ret.pixel = newPoint[1] - oldPoint[1];
  54922. ret.pixelLength = rect.height;
  54923. ret.pixelStart = rect.y;
  54924. ret.signal = axis.inverse ? -1 : 1;
  54925. }
  54926. return ret;
  54927. },
  54928. polar: function (oldPoint, newPoint, axisModel, controller, coordInfo) {
  54929. var axis = axisModel.axis;
  54930. var ret = {};
  54931. var polar = coordInfo.model.coordinateSystem;
  54932. var radiusExtent = polar.getRadiusAxis().getExtent();
  54933. var angleExtent = polar.getAngleAxis().getExtent();
  54934. oldPoint = oldPoint ? polar.pointToCoord(oldPoint) : [0, 0];
  54935. newPoint = polar.pointToCoord(newPoint);
  54936. if (axisModel.mainType === 'radiusAxis') {
  54937. ret.pixel = newPoint[0] - oldPoint[0];
  54938. // ret.pixelLength = Math.abs(radiusExtent[1] - radiusExtent[0]);
  54939. // ret.pixelStart = Math.min(radiusExtent[0], radiusExtent[1]);
  54940. ret.pixelLength = radiusExtent[1] - radiusExtent[0];
  54941. ret.pixelStart = radiusExtent[0];
  54942. ret.signal = axis.inverse ? 1 : -1;
  54943. }
  54944. else { // 'angleAxis'
  54945. ret.pixel = newPoint[1] - oldPoint[1];
  54946. // ret.pixelLength = Math.abs(angleExtent[1] - angleExtent[0]);
  54947. // ret.pixelStart = Math.min(angleExtent[0], angleExtent[1]);
  54948. ret.pixelLength = angleExtent[1] - angleExtent[0];
  54949. ret.pixelStart = angleExtent[0];
  54950. ret.signal = axis.inverse ? -1 : 1;
  54951. }
  54952. return ret;
  54953. },
  54954. singleAxis: function (oldPoint, newPoint, axisModel, controller, coordInfo) {
  54955. var axis = axisModel.axis;
  54956. var rect = coordInfo.model.coordinateSystem.getRect();
  54957. var ret = {};
  54958. oldPoint = oldPoint || [0, 0];
  54959. if (axis.orient === 'horizontal') {
  54960. ret.pixel = newPoint[0] - oldPoint[0];
  54961. ret.pixelLength = rect.width;
  54962. ret.pixelStart = rect.x;
  54963. ret.signal = axis.inverse ? 1 : -1;
  54964. }
  54965. else { // 'vertical'
  54966. ret.pixel = newPoint[1] - oldPoint[1];
  54967. ret.pixelLength = rect.height;
  54968. ret.pixelStart = rect.y;
  54969. ret.signal = axis.inverse ? -1 : 1;
  54970. }
  54971. return ret;
  54972. }
  54973. };
  54974. module.exports = InsideZoomView;
  54975. /***/ },
  54976. /* 372 */
  54977. /***/ function(module, exports, __webpack_require__) {
  54978. /**
  54979. * @file Roam controller manager.
  54980. */
  54981. // Only create one roam controller for each coordinate system.
  54982. // one roam controller might be refered by two inside data zoom
  54983. // components (for example, one for x and one for y). When user
  54984. // pan or zoom, only dispatch one action for those data zoom
  54985. // components.
  54986. var zrUtil = __webpack_require__(4);
  54987. var RoamController = __webpack_require__(182);
  54988. var throttle = __webpack_require__(81);
  54989. var curry = zrUtil.curry;
  54990. var ATTR = '\0_ec_dataZoom_roams';
  54991. var roams = {
  54992. /**
  54993. * @public
  54994. * @param {module:echarts/ExtensionAPI} api
  54995. * @param {Object} dataZoomInfo
  54996. * @param {string} dataZoomInfo.coordId
  54997. * @param {Function} dataZoomInfo.containsPoint
  54998. * @param {Array.<string>} dataZoomInfo.allCoordIds
  54999. * @param {string} dataZoomInfo.dataZoomId
  55000. * @param {number} dataZoomInfo.throttleRate
  55001. * @param {Function} dataZoomInfo.panGetRange
  55002. * @param {Function} dataZoomInfo.zoomGetRange
  55003. * @param {boolean} [dataZoomInfo.zoomLock]
  55004. * @param {boolean} [dataZoomInfo.disabled]
  55005. */
  55006. register: function (api, dataZoomInfo) {
  55007. var store = giveStore(api);
  55008. var theDataZoomId = dataZoomInfo.dataZoomId;
  55009. var theCoordId = dataZoomInfo.coordId;
  55010. // Do clean when a dataZoom changes its target coordnate system.
  55011. // Avoid memory leak, dispose all not-used-registered.
  55012. zrUtil.each(store, function (record, coordId) {
  55013. var dataZoomInfos = record.dataZoomInfos;
  55014. if (dataZoomInfos[theDataZoomId]
  55015. && zrUtil.indexOf(dataZoomInfo.allCoordIds, theCoordId) < 0
  55016. ) {
  55017. delete dataZoomInfos[theDataZoomId];
  55018. record.count--;
  55019. }
  55020. });
  55021. cleanStore(store);
  55022. var record = store[theCoordId];
  55023. // Create if needed.
  55024. if (!record) {
  55025. record = store[theCoordId] = {
  55026. coordId: theCoordId,
  55027. dataZoomInfos: {},
  55028. count: 0
  55029. };
  55030. record.controller = createController(api, record);
  55031. record.dispatchAction = zrUtil.curry(dispatchAction, api);
  55032. }
  55033. record.controller.enable(
  55034. dataZoomInfo.disabled ? false : dataZoomInfo.zoomLock ? 'move' : true,
  55035. dataZoomInfo.roamControllerOpt
  55036. );
  55037. // Consider resize, area should be always updated.
  55038. record.controller.setPointerChecker(dataZoomInfo.containsPoint);
  55039. // Update throttle.
  55040. throttle.createOrUpdate(
  55041. record,
  55042. 'dispatchAction',
  55043. dataZoomInfo.throttleRate,
  55044. 'fixRate'
  55045. );
  55046. // Update reference of dataZoom.
  55047. !(record.dataZoomInfos[theDataZoomId]) && record.count++;
  55048. record.dataZoomInfos[theDataZoomId] = dataZoomInfo;
  55049. },
  55050. /**
  55051. * @public
  55052. * @param {module:echarts/ExtensionAPI} api
  55053. * @param {string} dataZoomId
  55054. */
  55055. unregister: function (api, dataZoomId) {
  55056. var store = giveStore(api);
  55057. zrUtil.each(store, function (record) {
  55058. record.controller.dispose();
  55059. var dataZoomInfos = record.dataZoomInfos;
  55060. if (dataZoomInfos[dataZoomId]) {
  55061. delete dataZoomInfos[dataZoomId];
  55062. record.count--;
  55063. }
  55064. });
  55065. cleanStore(store);
  55066. },
  55067. /**
  55068. * @public
  55069. */
  55070. shouldRecordRange: function (payload, dataZoomId) {
  55071. if (payload && payload.type === 'dataZoom' && payload.batch) {
  55072. for (var i = 0, len = payload.batch.length; i < len; i++) {
  55073. if (payload.batch[i].dataZoomId === dataZoomId) {
  55074. return false;
  55075. }
  55076. }
  55077. }
  55078. return true;
  55079. },
  55080. /**
  55081. * @public
  55082. */
  55083. generateCoordId: function (coordModel) {
  55084. return coordModel.type + '\0_' + coordModel.id;
  55085. }
  55086. };
  55087. /**
  55088. * Key: coordId, value: {dataZoomInfos: [], count, controller}
  55089. * @type {Array.<Object>}
  55090. */
  55091. function giveStore(api) {
  55092. // Mount store on zrender instance, so that we do not
  55093. // need to worry about dispose.
  55094. var zr = api.getZr();
  55095. return zr[ATTR] || (zr[ATTR] = {});
  55096. }
  55097. function createController(api, newRecord) {
  55098. var controller = new RoamController(api.getZr());
  55099. controller.on('pan', curry(onPan, newRecord));
  55100. controller.on('zoom', curry(onZoom, newRecord));
  55101. return controller;
  55102. }
  55103. function cleanStore(store) {
  55104. zrUtil.each(store, function (record, coordId) {
  55105. if (!record.count) {
  55106. record.controller.dispose();
  55107. delete store[coordId];
  55108. }
  55109. });
  55110. }
  55111. function onPan(record, dx, dy, oldX, oldY, newX, newY) {
  55112. wrapAndDispatch(record, function (info) {
  55113. return info.panGetRange(record.controller, dx, dy, oldX, oldY, newX, newY);
  55114. });
  55115. }
  55116. function onZoom(record, scale, mouseX, mouseY) {
  55117. wrapAndDispatch(record, function (info) {
  55118. return info.zoomGetRange(record.controller, scale, mouseX, mouseY);
  55119. });
  55120. }
  55121. function wrapAndDispatch(record, getRange) {
  55122. var batch = [];
  55123. zrUtil.each(record.dataZoomInfos, function (info) {
  55124. var range = getRange(info);
  55125. range && batch.push({
  55126. dataZoomId: info.dataZoomId,
  55127. start: range[0],
  55128. end: range[1]
  55129. });
  55130. });
  55131. record.dispatchAction(batch);
  55132. }
  55133. /**
  55134. * This action will be throttled.
  55135. */
  55136. function dispatchAction(api, batch) {
  55137. api.dispatchAction({
  55138. type: 'dataZoom',
  55139. batch: batch
  55140. });
  55141. }
  55142. module.exports = roams;
  55143. /***/ },
  55144. /* 373 */
  55145. /***/ function(module, exports, __webpack_require__) {
  55146. /**
  55147. * @file Data zoom processor
  55148. */
  55149. var echarts = __webpack_require__(1);
  55150. echarts.registerProcessor(function (ecModel, api) {
  55151. ecModel.eachComponent('dataZoom', function (dataZoomModel) {
  55152. // We calculate window and reset axis here but not in model
  55153. // init stage and not after action dispatch handler, because
  55154. // reset should be called after seriesData.restoreData.
  55155. dataZoomModel.eachTargetAxis(resetSingleAxis);
  55156. // Caution: data zoom filtering is order sensitive when using
  55157. // percent range and no min/max/scale set on axis.
  55158. // For example, we have dataZoom definition:
  55159. // [
  55160. // {xAxisIndex: 0, start: 30, end: 70},
  55161. // {yAxisIndex: 0, start: 20, end: 80}
  55162. // ]
  55163. // In this case, [20, 80] of y-dataZoom should be based on data
  55164. // that have filtered by x-dataZoom using range of [30, 70],
  55165. // but should not be based on full raw data. Thus sliding
  55166. // x-dataZoom will change both ranges of xAxis and yAxis,
  55167. // while sliding y-dataZoom will only change the range of yAxis.
  55168. // So we should filter x-axis after reset x-axis immediately,
  55169. // and then reset y-axis and filter y-axis.
  55170. dataZoomModel.eachTargetAxis(filterSingleAxis);
  55171. });
  55172. ecModel.eachComponent('dataZoom', function (dataZoomModel) {
  55173. // Fullfill all of the range props so that user
  55174. // is able to get them from chart.getOption().
  55175. var axisProxy = dataZoomModel.findRepresentativeAxisProxy();
  55176. var percentRange = axisProxy.getDataPercentWindow();
  55177. var valueRange = axisProxy.getDataValueWindow();
  55178. dataZoomModel.setRawRange({
  55179. start: percentRange[0],
  55180. end: percentRange[1],
  55181. startValue: valueRange[0],
  55182. endValue: valueRange[1]
  55183. }, true);
  55184. });
  55185. });
  55186. function resetSingleAxis(dimNames, axisIndex, dataZoomModel) {
  55187. dataZoomModel.getAxisProxy(dimNames.name, axisIndex).reset(dataZoomModel);
  55188. }
  55189. function filterSingleAxis(dimNames, axisIndex, dataZoomModel) {
  55190. dataZoomModel.getAxisProxy(dimNames.name, axisIndex).filterData(dataZoomModel);
  55191. }
  55192. /***/ },
  55193. /* 374 */
  55194. /***/ function(module, exports, __webpack_require__) {
  55195. /**
  55196. * @file Data zoom action
  55197. */
  55198. var zrUtil = __webpack_require__(4);
  55199. var helper = __webpack_require__(365);
  55200. var echarts = __webpack_require__(1);
  55201. echarts.registerAction('dataZoom', function (payload, ecModel) {
  55202. var linkedNodesFinder = helper.createLinkedNodesFinder(
  55203. zrUtil.bind(ecModel.eachComponent, ecModel, 'dataZoom'),
  55204. helper.eachAxisDim,
  55205. function (model, dimNames) {
  55206. return model.get(dimNames.axisIndex);
  55207. }
  55208. );
  55209. var effectedModels = [];
  55210. ecModel.eachComponent(
  55211. {mainType: 'dataZoom', query: payload},
  55212. function (model, index) {
  55213. effectedModels.push.apply(
  55214. effectedModels, linkedNodesFinder(model).nodes
  55215. );
  55216. }
  55217. );
  55218. zrUtil.each(effectedModels, function (dataZoomModel, index) {
  55219. dataZoomModel.setRawRange({
  55220. start: payload.start,
  55221. end: payload.end,
  55222. startValue: payload.startValue,
  55223. endValue: payload.endValue
  55224. });
  55225. });
  55226. });
  55227. /***/ },
  55228. /* 375 */
  55229. /***/ function(module, exports, __webpack_require__) {
  55230. /**
  55231. * visualMap component entry
  55232. */
  55233. __webpack_require__(376);
  55234. __webpack_require__(387);
  55235. /***/ },
  55236. /* 376 */
  55237. /***/ function(module, exports, __webpack_require__) {
  55238. /**
  55239. * DataZoom component entry
  55240. */
  55241. __webpack_require__(1).registerPreprocessor(
  55242. __webpack_require__(377)
  55243. );
  55244. __webpack_require__(378);
  55245. __webpack_require__(379);
  55246. __webpack_require__(380);
  55247. __webpack_require__(383);
  55248. __webpack_require__(386);
  55249. /***/ },
  55250. /* 377 */
  55251. /***/ function(module, exports, __webpack_require__) {
  55252. /**
  55253. * @file VisualMap preprocessor
  55254. */
  55255. var zrUtil = __webpack_require__(4);
  55256. var each = zrUtil.each;
  55257. module.exports = function (option) {
  55258. var visualMap = option && option.visualMap;
  55259. if (!zrUtil.isArray(visualMap)) {
  55260. visualMap = visualMap ? [visualMap] : [];
  55261. }
  55262. each(visualMap, function (opt) {
  55263. if (!opt) {
  55264. return;
  55265. }
  55266. // rename splitList to pieces
  55267. if (has(opt, 'splitList') && !has(opt, 'pieces')) {
  55268. opt.pieces = opt.splitList;
  55269. delete opt.splitList;
  55270. }
  55271. var pieces = opt.pieces;
  55272. if (pieces && zrUtil.isArray(pieces)) {
  55273. each(pieces, function (piece) {
  55274. if (zrUtil.isObject(piece)) {
  55275. if (has(piece, 'start') && !has(piece, 'min')) {
  55276. piece.min = piece.start;
  55277. }
  55278. if (has(piece, 'end') && !has(piece, 'max')) {
  55279. piece.max = piece.end;
  55280. }
  55281. }
  55282. });
  55283. }
  55284. });
  55285. };
  55286. function has(obj, name) {
  55287. return obj && obj.hasOwnProperty && obj.hasOwnProperty(name);
  55288. }
  55289. /***/ },
  55290. /* 378 */
  55291. /***/ function(module, exports, __webpack_require__) {
  55292. __webpack_require__(69).registerSubTypeDefaulter('visualMap', function (option) {
  55293. // Compatible with ec2, when splitNumber === 0, continuous visualMap will be used.
  55294. return (
  55295. !option.categories
  55296. && (
  55297. !(
  55298. option.pieces
  55299. ? option.pieces.length > 0
  55300. : option.splitNumber > 0
  55301. )
  55302. || option.calculable
  55303. )
  55304. )
  55305. ? 'continuous' : 'piecewise';
  55306. });
  55307. /***/ },
  55308. /* 379 */
  55309. /***/ function(module, exports, __webpack_require__) {
  55310. /**
  55311. * @file Data range visual coding.
  55312. */
  55313. var echarts = __webpack_require__(1);
  55314. var visualSolution = __webpack_require__(349);
  55315. var VisualMapping = __webpack_require__(202);
  55316. var zrUtil = __webpack_require__(4);
  55317. echarts.registerVisual(echarts.PRIORITY.VISUAL.COMPONENT, function (ecModel) {
  55318. ecModel.eachComponent('visualMap', function (visualMapModel) {
  55319. processSingleVisualMap(visualMapModel, ecModel);
  55320. });
  55321. prepareVisualMeta(ecModel);
  55322. });
  55323. function processSingleVisualMap(visualMapModel, ecModel) {
  55324. visualMapModel.eachTargetSeries(function (seriesModel) {
  55325. var data = seriesModel.getData();
  55326. visualSolution.applyVisual(
  55327. visualMapModel.stateList,
  55328. visualMapModel.targetVisuals,
  55329. data,
  55330. visualMapModel.getValueState,
  55331. visualMapModel,
  55332. visualMapModel.getDataDimension(data)
  55333. );
  55334. });
  55335. }
  55336. // Only support color.
  55337. function prepareVisualMeta(ecModel) {
  55338. ecModel.eachSeries(function (seriesModel) {
  55339. var data = seriesModel.getData();
  55340. var visualMetaList = [];
  55341. ecModel.eachComponent('visualMap', function (visualMapModel) {
  55342. if (visualMapModel.isTargetSeries(seriesModel)) {
  55343. var visualMeta = visualMapModel.getVisualMeta(
  55344. zrUtil.bind(getColorVisual, null, seriesModel, visualMapModel)
  55345. ) || {stops: [], outerColors: []};
  55346. visualMeta.dimension = visualMapModel.getDataDimension(data);
  55347. visualMetaList.push(visualMeta);
  55348. }
  55349. });
  55350. // console.log(JSON.stringify(visualMetaList.map(a => a.stops)));
  55351. seriesModel.getData().setVisual('visualMeta', visualMetaList);
  55352. });
  55353. }
  55354. // FIXME
  55355. // performance and export for heatmap?
  55356. // value can be Infinity or -Infinity
  55357. function getColorVisual(seriesModel, visualMapModel, value, valueState) {
  55358. var mappings = visualMapModel.targetVisuals[valueState];
  55359. var visualTypes = VisualMapping.prepareVisualTypes(mappings);
  55360. var resultVisual = {
  55361. color: seriesModel.getData().getVisual('color') // default color.
  55362. };
  55363. for (var i = 0, len = visualTypes.length; i < len; i++) {
  55364. var type = visualTypes[i];
  55365. var mapping = mappings[
  55366. type === 'opacity' ? '__alphaForOpacity' : type
  55367. ];
  55368. mapping && mapping.applyVisual(value, getVisual, setVisual);
  55369. }
  55370. return resultVisual.color;
  55371. function getVisual(key) {
  55372. return resultVisual[key];
  55373. }
  55374. function setVisual(key, value) {
  55375. resultVisual[key] = value;
  55376. }
  55377. }
  55378. /***/ },
  55379. /* 380 */
  55380. /***/ function(module, exports, __webpack_require__) {
  55381. /**
  55382. * @file Data zoom model
  55383. */
  55384. var VisualMapModel = __webpack_require__(381);
  55385. var zrUtil = __webpack_require__(4);
  55386. var numberUtil = __webpack_require__(7);
  55387. // Constant
  55388. var DEFAULT_BAR_BOUND = [20, 140];
  55389. var ContinuousModel = VisualMapModel.extend({
  55390. type: 'visualMap.continuous',
  55391. /**
  55392. * @protected
  55393. */
  55394. defaultOption: {
  55395. align: 'auto', // 'auto', 'left', 'right', 'top', 'bottom'
  55396. calculable: false, // This prop effect default component type determine,
  55397. // See echarts/component/visualMap/typeDefaulter.
  55398. range: null, // selected range. In default case `range` is [min, max]
  55399. // and can auto change along with modification of min max,
  55400. // util use specifid a range.
  55401. realtime: true, // Whether realtime update.
  55402. itemHeight: null, // The length of the range control edge.
  55403. itemWidth: null, // The length of the other side.
  55404. hoverLink: true, // Enable hover highlight.
  55405. hoverLinkDataSize: null,// The size of hovered data.
  55406. hoverLinkOnHandle: true // Whether trigger hoverLink when hover handle.
  55407. },
  55408. /**
  55409. * @override
  55410. */
  55411. optionUpdated: function (newOption, isInit) {
  55412. ContinuousModel.superApply(this, 'optionUpdated', arguments);
  55413. this.resetTargetSeries();
  55414. this.resetExtent();
  55415. this.resetVisual(function (mappingOption) {
  55416. mappingOption.mappingMethod = 'linear';
  55417. mappingOption.dataExtent = this.getExtent();
  55418. });
  55419. this._resetRange();
  55420. },
  55421. /**
  55422. * @protected
  55423. * @override
  55424. */
  55425. resetItemSize: function () {
  55426. ContinuousModel.superApply(this, 'resetItemSize', arguments);
  55427. var itemSize = this.itemSize;
  55428. this._orient === 'horizontal' && itemSize.reverse();
  55429. (itemSize[0] == null || isNaN(itemSize[0])) && (itemSize[0] = DEFAULT_BAR_BOUND[0]);
  55430. (itemSize[1] == null || isNaN(itemSize[1])) && (itemSize[1] = DEFAULT_BAR_BOUND[1]);
  55431. },
  55432. /**
  55433. * @private
  55434. */
  55435. _resetRange: function () {
  55436. var dataExtent = this.getExtent();
  55437. var range = this.option.range;
  55438. if (!range || range.auto) {
  55439. // `range` should always be array (so we dont use other
  55440. // value like 'auto') for user-friend. (consider getOption).
  55441. dataExtent.auto = 1;
  55442. this.option.range = dataExtent;
  55443. }
  55444. else if (zrUtil.isArray(range)) {
  55445. if (range[0] > range[1]) {
  55446. range.reverse();
  55447. }
  55448. range[0] = Math.max(range[0], dataExtent[0]);
  55449. range[1] = Math.min(range[1], dataExtent[1]);
  55450. }
  55451. },
  55452. /**
  55453. * @protected
  55454. * @override
  55455. */
  55456. completeVisualOption: function () {
  55457. VisualMapModel.prototype.completeVisualOption.apply(this, arguments);
  55458. zrUtil.each(this.stateList, function (state) {
  55459. var symbolSize = this.option.controller[state].symbolSize;
  55460. if (symbolSize && symbolSize[0] !== symbolSize[1]) {
  55461. symbolSize[0] = 0; // For good looking.
  55462. }
  55463. }, this);
  55464. },
  55465. /**
  55466. * @override
  55467. */
  55468. setSelected: function (selected) {
  55469. this.option.range = selected.slice();
  55470. this._resetRange();
  55471. },
  55472. /**
  55473. * @public
  55474. */
  55475. getSelected: function () {
  55476. var dataExtent = this.getExtent();
  55477. var dataInterval = numberUtil.asc(
  55478. (this.get('range') || []).slice()
  55479. );
  55480. // Clamp
  55481. dataInterval[0] > dataExtent[1] && (dataInterval[0] = dataExtent[1]);
  55482. dataInterval[1] > dataExtent[1] && (dataInterval[1] = dataExtent[1]);
  55483. dataInterval[0] < dataExtent[0] && (dataInterval[0] = dataExtent[0]);
  55484. dataInterval[1] < dataExtent[0] && (dataInterval[1] = dataExtent[0]);
  55485. return dataInterval;
  55486. },
  55487. /**
  55488. * @override
  55489. */
  55490. getValueState: function (value) {
  55491. var range = this.option.range;
  55492. var dataExtent = this.getExtent();
  55493. // When range[0] === dataExtent[0], any value larger than dataExtent[0] maps to 'inRange'.
  55494. // range[1] is processed likewise.
  55495. return (
  55496. (range[0] <= dataExtent[0] || range[0] <= value)
  55497. && (range[1] >= dataExtent[1] || value <= range[1])
  55498. ) ? 'inRange' : 'outOfRange';
  55499. },
  55500. /**
  55501. * @params {Array.<number>} range target value: range[0] <= value && value <= range[1]
  55502. * @return {Array.<Object>} [{seriesId, dataIndices: <Array.<number>>}, ...]
  55503. */
  55504. findTargetDataIndices: function (range) {
  55505. var result = [];
  55506. this.eachTargetSeries(function (seriesModel) {
  55507. var dataIndices = [];
  55508. var data = seriesModel.getData();
  55509. data.each(this.getDataDimension(data), function (value, dataIndex) {
  55510. range[0] <= value && value <= range[1] && dataIndices.push(dataIndex);
  55511. }, true, this);
  55512. result.push({seriesId: seriesModel.id, dataIndex: dataIndices});
  55513. }, this);
  55514. return result;
  55515. },
  55516. /**
  55517. * @implement
  55518. */
  55519. getVisualMeta: function (getColorVisual) {
  55520. var oVals = getColorStopValues(this, 'outOfRange', this.getExtent());
  55521. var iVals = getColorStopValues(this, 'inRange', this.option.range.slice());
  55522. var stops = [];
  55523. function setStop(value, valueState) {
  55524. stops.push({
  55525. value: value,
  55526. color: getColorVisual(value, valueState)
  55527. });
  55528. }
  55529. // Format to: outOfRange -- inRange -- outOfRange.
  55530. var iIdx = 0;
  55531. var oIdx = 0;
  55532. var iLen = iVals.length;
  55533. var oLen = oVals.length;
  55534. for (; oIdx < oLen && (!iVals.length || oVals[oIdx] <= iVals[0]); oIdx++) {
  55535. // If oVal[oIdx] === iVals[iIdx], oVal[oIdx] should be ignored.
  55536. if (oVals[oIdx] < iVals[iIdx]) {
  55537. setStop(oVals[oIdx], 'outOfRange');
  55538. }
  55539. }
  55540. for (var first = 1; iIdx < iLen; iIdx++, first = 0) {
  55541. // If range is full, value beyond min, max will be clamped.
  55542. // make a singularity
  55543. first && stops.length && setStop(iVals[iIdx], 'outOfRange');
  55544. setStop(iVals[iIdx], 'inRange');
  55545. }
  55546. for (var first = 1; oIdx < oLen; oIdx++) {
  55547. if (!iVals.length || iVals[iVals.length - 1] < oVals[oIdx]) {
  55548. // make a singularity
  55549. if (first) {
  55550. stops.length && setStop(stops[stops.length - 1].value, 'outOfRange');
  55551. first = 0;
  55552. }
  55553. setStop(oVals[oIdx], 'outOfRange');
  55554. }
  55555. }
  55556. var stopsLen = stops.length;
  55557. return {
  55558. stops: stops,
  55559. outerColors: [
  55560. stopsLen ? stops[0].color : 'transparent',
  55561. stopsLen ? stops[stopsLen - 1].color : 'transparent'
  55562. ]
  55563. };
  55564. }
  55565. });
  55566. function getColorStopValues(visualMapModel, valueState, dataExtent) {
  55567. if (dataExtent[0] === dataExtent[1]) {
  55568. return dataExtent.slice();
  55569. }
  55570. // When using colorHue mapping, it is not linear color any more.
  55571. // Moreover, canvas gradient seems not to be accurate linear.
  55572. // FIXME
  55573. // Should be arbitrary value 100? or based on pixel size?
  55574. var count = 200;
  55575. var step = (dataExtent[1] - dataExtent[0]) / count;
  55576. var value = dataExtent[0];
  55577. var stopValues = [];
  55578. for (var i = 0; i <= count && value < dataExtent[1]; i++) {
  55579. stopValues.push(value);
  55580. value += step;
  55581. }
  55582. stopValues.push(dataExtent[1]);
  55583. return stopValues;
  55584. }
  55585. module.exports = ContinuousModel;
  55586. /***/ },
  55587. /* 381 */
  55588. /***/ function(module, exports, __webpack_require__) {
  55589. /**
  55590. * @file Controller visual map model
  55591. */
  55592. var echarts = __webpack_require__(1);
  55593. var zrUtil = __webpack_require__(4);
  55594. var env = __webpack_require__(2);
  55595. var visualDefault = __webpack_require__(382);
  55596. var VisualMapping = __webpack_require__(202);
  55597. var visualSolution = __webpack_require__(349);
  55598. var mapVisual = VisualMapping.mapVisual;
  55599. var modelUtil = __webpack_require__(5);
  55600. var eachVisual = VisualMapping.eachVisual;
  55601. var numberUtil = __webpack_require__(7);
  55602. var isArray = zrUtil.isArray;
  55603. var each = zrUtil.each;
  55604. var asc = numberUtil.asc;
  55605. var linearMap = numberUtil.linearMap;
  55606. var noop = zrUtil.noop;
  55607. var DEFAULT_COLOR = ['#f6efa6', '#d88273', '#bf444c'];
  55608. var VisualMapModel = echarts.extendComponentModel({
  55609. type: 'visualMap',
  55610. dependencies: ['series'],
  55611. /**
  55612. * @readOnly
  55613. * @type {Array.<string>}
  55614. */
  55615. stateList: ['inRange', 'outOfRange'],
  55616. /**
  55617. * @readOnly
  55618. * @type {Array.<string>}
  55619. */
  55620. replacableOptionKeys: [
  55621. 'inRange', 'outOfRange', 'target', 'controller', 'color'
  55622. ],
  55623. /**
  55624. * [lowerBound, upperBound]
  55625. *
  55626. * @readOnly
  55627. * @type {Array.<number>}
  55628. */
  55629. dataBound: [-Infinity, Infinity],
  55630. /**
  55631. * @readOnly
  55632. * @type {string|Object}
  55633. */
  55634. layoutMode: {type: 'box', ignoreSize: true},
  55635. /**
  55636. * @protected
  55637. */
  55638. defaultOption: {
  55639. show: true,
  55640. zlevel: 0,
  55641. z: 4,
  55642. seriesIndex: null, // 所控制的series indices,默认所有有value的series.
  55643. // set min: 0, max: 200, only for campatible with ec2.
  55644. // In fact min max should not have default value.
  55645. min: 0, // min value, must specified if pieces is not specified.
  55646. max: 200, // max value, must specified if pieces is not specified.
  55647. dimension: null,
  55648. inRange: null, // 'color', 'colorHue', 'colorSaturation', 'colorLightness', 'colorAlpha',
  55649. // 'symbol', 'symbolSize'
  55650. outOfRange: null, // 'color', 'colorHue', 'colorSaturation',
  55651. // 'colorLightness', 'colorAlpha',
  55652. // 'symbol', 'symbolSize'
  55653. left: 0, // 'center' ¦ 'left' ¦ 'right' ¦ {number} (px)
  55654. right: null, // The same as left.
  55655. top: null, // 'top' ¦ 'bottom' ¦ 'center' ¦ {number} (px)
  55656. bottom: 0, // The same as top.
  55657. itemWidth: null,
  55658. itemHeight: null,
  55659. inverse: false,
  55660. orient: 'vertical', // 'horizontal' ¦ 'vertical'
  55661. backgroundColor: 'rgba(0,0,0,0)',
  55662. borderColor: '#ccc', // 值域边框颜色
  55663. contentColor: '#5793f3',
  55664. inactiveColor: '#aaa',
  55665. borderWidth: 0, // 值域边框线宽,单位px,默认为0(无边框)
  55666. padding: 5, // 值域内边距,单位px,默认各方向内边距为5,
  55667. // 接受数组分别设定上右下左边距,同css
  55668. textGap: 10, //
  55669. precision: 0, // 小数精度,默认为0,无小数点
  55670. color: null, //颜色(deprecated,兼容ec2,顺序同pieces,不同于inRange/outOfRange)
  55671. formatter: null,
  55672. text: null, // 文本,如['高', '低'],兼容ec2,text[0]对应高值,text[1]对应低值
  55673. textStyle: {
  55674. color: '#333' // 值域文字颜色
  55675. }
  55676. },
  55677. /**
  55678. * @protected
  55679. */
  55680. init: function (option, parentModel, ecModel) {
  55681. /**
  55682. * @private
  55683. * @type {Array.<number>}
  55684. */
  55685. this._dataExtent;
  55686. /**
  55687. * @readOnly
  55688. */
  55689. this.targetVisuals = {};
  55690. /**
  55691. * @readOnly
  55692. */
  55693. this.controllerVisuals = {};
  55694. /**
  55695. * @readOnly
  55696. */
  55697. this.textStyleModel;
  55698. /**
  55699. * [width, height]
  55700. * @readOnly
  55701. * @type {Array.<number>}
  55702. */
  55703. this.itemSize;
  55704. this.mergeDefaultAndTheme(option, ecModel);
  55705. },
  55706. /**
  55707. * @protected
  55708. */
  55709. optionUpdated: function (newOption, isInit) {
  55710. var thisOption = this.option;
  55711. // FIXME
  55712. // necessary?
  55713. // Disable realtime view update if canvas is not supported.
  55714. if (!env.canvasSupported) {
  55715. thisOption.realtime = false;
  55716. }
  55717. !isInit && visualSolution.replaceVisualOption(
  55718. thisOption, newOption, this.replacableOptionKeys
  55719. );
  55720. this.textStyleModel = this.getModel('textStyle');
  55721. this.resetItemSize();
  55722. this.completeVisualOption();
  55723. },
  55724. /**
  55725. * @protected
  55726. */
  55727. resetVisual: function (supplementVisualOption) {
  55728. var stateList = this.stateList;
  55729. supplementVisualOption = zrUtil.bind(supplementVisualOption, this);
  55730. this.controllerVisuals = visualSolution.createVisualMappings(
  55731. this.option.controller, stateList, supplementVisualOption
  55732. );
  55733. this.targetVisuals = visualSolution.createVisualMappings(
  55734. this.option.target, stateList, supplementVisualOption
  55735. );
  55736. },
  55737. /**
  55738. * @protected
  55739. */
  55740. resetTargetSeries: function () {
  55741. var thisOption = this.option;
  55742. var allSeriesIndex = thisOption.seriesIndex == null;
  55743. thisOption.seriesIndex = allSeriesIndex
  55744. ? [] : modelUtil.normalizeToArray(thisOption.seriesIndex);
  55745. allSeriesIndex && this.ecModel.eachSeries(function (seriesModel, index) {
  55746. thisOption.seriesIndex.push(index);
  55747. });
  55748. },
  55749. /**
  55750. * @public
  55751. */
  55752. eachTargetSeries: function (callback, context) {
  55753. zrUtil.each(this.option.seriesIndex, function (seriesIndex) {
  55754. callback.call(context, this.ecModel.getSeriesByIndex(seriesIndex));
  55755. }, this);
  55756. },
  55757. /**
  55758. * @pubilc
  55759. */
  55760. isTargetSeries: function (seriesModel) {
  55761. var is = false;
  55762. this.eachTargetSeries(function (model) {
  55763. model === seriesModel && (is = true);
  55764. });
  55765. return is;
  55766. },
  55767. /**
  55768. * @example
  55769. * this.formatValueText(someVal); // format single numeric value to text.
  55770. * this.formatValueText(someVal, true); // format single category value to text.
  55771. * this.formatValueText([min, max]); // format numeric min-max to text.
  55772. * this.formatValueText([this.dataBound[0], max]); // using data lower bound.
  55773. * this.formatValueText([min, this.dataBound[1]]); // using data upper bound.
  55774. *
  55775. * @param {number|Array.<number>} value Real value, or this.dataBound[0 or 1].
  55776. * @param {boolean} [isCategory=false] Only available when value is number.
  55777. * @param {Array.<string>} edgeSymbols Open-close symbol when value is interval.
  55778. * @return {string}
  55779. * @protected
  55780. */
  55781. formatValueText: function(value, isCategory, edgeSymbols) {
  55782. var option = this.option;
  55783. var precision = option.precision;
  55784. var dataBound = this.dataBound;
  55785. var formatter = option.formatter;
  55786. var isMinMax;
  55787. var textValue;
  55788. edgeSymbols = edgeSymbols || ['<', '>'];
  55789. if (zrUtil.isArray(value)) {
  55790. value = value.slice();
  55791. isMinMax = true;
  55792. }
  55793. textValue = isCategory
  55794. ? value
  55795. : (isMinMax
  55796. ? [toFixed(value[0]), toFixed(value[1])]
  55797. : toFixed(value)
  55798. );
  55799. if (zrUtil.isString(formatter)) {
  55800. return formatter
  55801. .replace('{value}', isMinMax ? textValue[0] : textValue)
  55802. .replace('{value2}', isMinMax ? textValue[1] : textValue);
  55803. }
  55804. else if (zrUtil.isFunction(formatter)) {
  55805. return isMinMax
  55806. ? formatter(value[0], value[1])
  55807. : formatter(value);
  55808. }
  55809. if (isMinMax) {
  55810. if (value[0] === dataBound[0]) {
  55811. return edgeSymbols[0] + ' ' + textValue[1];
  55812. }
  55813. else if (value[1] === dataBound[1]) {
  55814. return edgeSymbols[1] + ' ' + textValue[0];
  55815. }
  55816. else {
  55817. return textValue[0] + ' - ' + textValue[1];
  55818. }
  55819. }
  55820. else { // Format single value (includes category case).
  55821. return textValue;
  55822. }
  55823. function toFixed(val) {
  55824. return val === dataBound[0]
  55825. ? 'min'
  55826. : val === dataBound[1]
  55827. ? 'max'
  55828. : (+val).toFixed(precision);
  55829. }
  55830. },
  55831. /**
  55832. * @protected
  55833. */
  55834. resetExtent: function () {
  55835. var thisOption = this.option;
  55836. // Can not calculate data extent by data here.
  55837. // Because series and data may be modified in processing stage.
  55838. // So we do not support the feature "auto min/max".
  55839. var extent = asc([thisOption.min, thisOption.max]);
  55840. this._dataExtent = extent;
  55841. },
  55842. /**
  55843. * @public
  55844. * @param {module:echarts/data/List} list
  55845. * @return {string} Concrete dimention. If return null/undefined,
  55846. * no dimension used.
  55847. */
  55848. getDataDimension: function (list) {
  55849. var optDim = this.option.dimension;
  55850. return optDim != null
  55851. ? optDim : list.dimensions.length - 1;
  55852. },
  55853. /**
  55854. * @public
  55855. * @override
  55856. */
  55857. getExtent: function () {
  55858. return this._dataExtent.slice();
  55859. },
  55860. /**
  55861. * @protected
  55862. */
  55863. completeVisualOption: function () {
  55864. var thisOption = this.option;
  55865. var base = {inRange: thisOption.inRange, outOfRange: thisOption.outOfRange};
  55866. var target = thisOption.target || (thisOption.target = {});
  55867. var controller = thisOption.controller || (thisOption.controller = {});
  55868. zrUtil.merge(target, base); // Do not override
  55869. zrUtil.merge(controller, base); // Do not override
  55870. var isCategory = this.isCategory();
  55871. completeSingle.call(this, target);
  55872. completeSingle.call(this, controller);
  55873. completeInactive.call(this, target, 'inRange', 'outOfRange');
  55874. // completeInactive.call(this, target, 'outOfRange', 'inRange');
  55875. completeController.call(this, controller);
  55876. function completeSingle(base) {
  55877. // Compatible with ec2 dataRange.color.
  55878. // The mapping order of dataRange.color is: [high value, ..., low value]
  55879. // whereas inRange.color and outOfRange.color is [low value, ..., high value]
  55880. // Notice: ec2 has no inverse.
  55881. if (isArray(thisOption.color)
  55882. // If there has been inRange: {symbol: ...}, adding color is a mistake.
  55883. // So adding color only when no inRange defined.
  55884. && !base.inRange
  55885. ) {
  55886. base.inRange = {color: thisOption.color.slice().reverse()};
  55887. }
  55888. // Compatible with previous logic, always give a defautl color, otherwise
  55889. // simple config with no inRange and outOfRange will not work.
  55890. // Originally we use visualMap.color as the default color, but setOption at
  55891. // the second time the default color will be erased. So we change to use
  55892. // constant DEFAULT_COLOR.
  55893. // If user do not want the defualt color, set inRange: {color: null}.
  55894. base.inRange = base.inRange || {color: DEFAULT_COLOR};
  55895. // If using shortcut like: {inRange: 'symbol'}, complete default value.
  55896. each(this.stateList, function (state) {
  55897. var visualType = base[state];
  55898. if (zrUtil.isString(visualType)) {
  55899. var defa = visualDefault.get(visualType, 'active', isCategory);
  55900. if (defa) {
  55901. base[state] = {};
  55902. base[state][visualType] = defa;
  55903. }
  55904. else {
  55905. // Mark as not specified.
  55906. delete base[state];
  55907. }
  55908. }
  55909. }, this);
  55910. }
  55911. function completeInactive(base, stateExist, stateAbsent) {
  55912. var optExist = base[stateExist];
  55913. var optAbsent = base[stateAbsent];
  55914. if (optExist && !optAbsent) {
  55915. optAbsent = base[stateAbsent] = {};
  55916. each(optExist, function (visualData, visualType) {
  55917. if (!VisualMapping.isValidType(visualType)) {
  55918. return;
  55919. }
  55920. var defa = visualDefault.get(visualType, 'inactive', isCategory);
  55921. if (defa != null) {
  55922. optAbsent[visualType] = defa;
  55923. // Compatibable with ec2:
  55924. // Only inactive color to rgba(0,0,0,0) can not
  55925. // make label transparent, so use opacity also.
  55926. if (visualType === 'color'
  55927. && !optAbsent.hasOwnProperty('opacity')
  55928. && !optAbsent.hasOwnProperty('colorAlpha')
  55929. ) {
  55930. optAbsent.opacity = [0, 0];
  55931. }
  55932. }
  55933. });
  55934. }
  55935. }
  55936. function completeController(controller) {
  55937. var symbolExists = (controller.inRange || {}).symbol
  55938. || (controller.outOfRange || {}).symbol;
  55939. var symbolSizeExists = (controller.inRange || {}).symbolSize
  55940. || (controller.outOfRange || {}).symbolSize;
  55941. var inactiveColor = this.get('inactiveColor');
  55942. each(this.stateList, function (state) {
  55943. var itemSize = this.itemSize;
  55944. var visuals = controller[state];
  55945. // Set inactive color for controller if no other color
  55946. // attr (like colorAlpha) specified.
  55947. if (!visuals) {
  55948. visuals = controller[state] = {
  55949. color: isCategory ? inactiveColor : [inactiveColor]
  55950. };
  55951. }
  55952. // Consistent symbol and symbolSize if not specified.
  55953. if (visuals.symbol == null) {
  55954. visuals.symbol = symbolExists
  55955. && zrUtil.clone(symbolExists)
  55956. || (isCategory ? 'roundRect' : ['roundRect']);
  55957. }
  55958. if (visuals.symbolSize == null) {
  55959. visuals.symbolSize = symbolSizeExists
  55960. && zrUtil.clone(symbolSizeExists)
  55961. || (isCategory ? itemSize[0] : [itemSize[0], itemSize[0]]);
  55962. }
  55963. // Filter square and none.
  55964. visuals.symbol = mapVisual(visuals.symbol, function (symbol) {
  55965. return (symbol === 'none' || symbol === 'square') ? 'roundRect' : symbol;
  55966. });
  55967. // Normalize symbolSize
  55968. var symbolSize = visuals.symbolSize;
  55969. if (symbolSize != null) {
  55970. var max = -Infinity;
  55971. // symbolSize can be object when categories defined.
  55972. eachVisual(symbolSize, function (value) {
  55973. value > max && (max = value);
  55974. });
  55975. visuals.symbolSize = mapVisual(symbolSize, function (value) {
  55976. return linearMap(value, [0, max], [0, itemSize[0]], true);
  55977. });
  55978. }
  55979. }, this);
  55980. }
  55981. },
  55982. /**
  55983. * @protected
  55984. */
  55985. resetItemSize: function () {
  55986. this.itemSize = [
  55987. parseFloat(this.get('itemWidth')),
  55988. parseFloat(this.get('itemHeight'))
  55989. ];
  55990. },
  55991. /**
  55992. * @public
  55993. */
  55994. isCategory: function () {
  55995. return !!this.option.categories;
  55996. },
  55997. /**
  55998. * @public
  55999. * @abstract
  56000. */
  56001. setSelected: noop,
  56002. /**
  56003. * @public
  56004. * @abstract
  56005. * @param {*|module:echarts/data/List} valueOrData
  56006. * @param {number} dataIndex
  56007. * @return {string} state See this.stateList
  56008. */
  56009. getValueState: noop,
  56010. /**
  56011. * FIXME
  56012. * Do not publish to thirt-part-dev temporarily
  56013. * util the interface is stable. (Should it return
  56014. * a function but not visual meta?)
  56015. *
  56016. * @pubilc
  56017. * @abstract
  56018. * @param {Function} getColorVisual
  56019. * params: value, valueState
  56020. * return: color
  56021. * @return {Object} visualMeta
  56022. * should includes {stops, outerColors}
  56023. * outerColor means [colorBeyondMinValue, colorBeyondMaxValue]
  56024. */
  56025. getVisualMeta: noop
  56026. });
  56027. module.exports = VisualMapModel;
  56028. /***/ },
  56029. /* 382 */
  56030. /***/ function(module, exports, __webpack_require__) {
  56031. /**
  56032. * @file Visual mapping.
  56033. */
  56034. var zrUtil = __webpack_require__(4);
  56035. var visualDefault = {
  56036. /**
  56037. * @public
  56038. */
  56039. get: function (visualType, key, isCategory) {
  56040. var value = zrUtil.clone(
  56041. (defaultOption[visualType] || {})[key]
  56042. );
  56043. return isCategory
  56044. ? (zrUtil.isArray(value) ? value[value.length - 1] : value)
  56045. : value;
  56046. }
  56047. };
  56048. var defaultOption = {
  56049. color: {
  56050. active: ['#006edd', '#e0ffff'],
  56051. inactive: ['rgba(0,0,0,0)']
  56052. },
  56053. colorHue: {
  56054. active: [0, 360],
  56055. inactive: [0, 0]
  56056. },
  56057. colorSaturation: {
  56058. active: [0.3, 1],
  56059. inactive: [0, 0]
  56060. },
  56061. colorLightness: {
  56062. active: [0.9, 0.5],
  56063. inactive: [0, 0]
  56064. },
  56065. colorAlpha: {
  56066. active: [0.3, 1],
  56067. inactive: [0, 0]
  56068. },
  56069. opacity: {
  56070. active: [0.3, 1],
  56071. inactive: [0, 0]
  56072. },
  56073. symbol: {
  56074. active: ['circle', 'roundRect', 'diamond'],
  56075. inactive: ['none']
  56076. },
  56077. symbolSize: {
  56078. active: [10, 50],
  56079. inactive: [0, 0]
  56080. }
  56081. };
  56082. module.exports = visualDefault;
  56083. /***/ },
  56084. /* 383 */
  56085. /***/ function(module, exports, __webpack_require__) {
  56086. var VisualMapView = __webpack_require__(384);
  56087. var graphic = __webpack_require__(18);
  56088. var zrUtil = __webpack_require__(4);
  56089. var numberUtil = __webpack_require__(7);
  56090. var sliderMove = __webpack_require__(238);
  56091. var LinearGradient = __webpack_require__(65);
  56092. var helper = __webpack_require__(385);
  56093. var modelUtil = __webpack_require__(5);
  56094. var eventTool = __webpack_require__(88);
  56095. var linearMap = numberUtil.linearMap;
  56096. var each = zrUtil.each;
  56097. var mathMin = Math.min;
  56098. var mathMax = Math.max;
  56099. // Arbitrary value
  56100. var HOVER_LINK_SIZE = 12;
  56101. var HOVER_LINK_OUT = 6;
  56102. // Notice:
  56103. // Any "interval" should be by the order of [low, high].
  56104. // "handle0" (handleIndex === 0) maps to
  56105. // low data value: this._dataInterval[0] and has low coord.
  56106. // "handle1" (handleIndex === 1) maps to
  56107. // high data value: this._dataInterval[1] and has high coord.
  56108. // The logic of transform is implemented in this._createBarGroup.
  56109. var ContinuousView = VisualMapView.extend({
  56110. type: 'visualMap.continuous',
  56111. /**
  56112. * @override
  56113. */
  56114. init: function () {
  56115. ContinuousView.superApply(this, 'init', arguments);
  56116. /**
  56117. * @private
  56118. */
  56119. this._shapes = {};
  56120. /**
  56121. * @private
  56122. */
  56123. this._dataInterval = [];
  56124. /**
  56125. * @private
  56126. */
  56127. this._handleEnds = [];
  56128. /**
  56129. * @private
  56130. */
  56131. this._orient;
  56132. /**
  56133. * @private
  56134. */
  56135. this._useHandle;
  56136. /**
  56137. * @private
  56138. */
  56139. this._hoverLinkDataIndices = [];
  56140. /**
  56141. * @private
  56142. */
  56143. this._dragging;
  56144. /**
  56145. * @private
  56146. */
  56147. this._hovering;
  56148. },
  56149. /**
  56150. * @protected
  56151. * @override
  56152. */
  56153. doRender: function (visualMapModel, ecModel, api, payload) {
  56154. if (!payload || payload.type !== 'selectDataRange' || payload.from !== this.uid) {
  56155. this._buildView();
  56156. }
  56157. },
  56158. /**
  56159. * @private
  56160. */
  56161. _buildView: function () {
  56162. this.group.removeAll();
  56163. var visualMapModel = this.visualMapModel;
  56164. var thisGroup = this.group;
  56165. this._orient = visualMapModel.get('orient');
  56166. this._useHandle = visualMapModel.get('calculable');
  56167. this._resetInterval();
  56168. this._renderBar(thisGroup);
  56169. var dataRangeText = visualMapModel.get('text');
  56170. this._renderEndsText(thisGroup, dataRangeText, 0);
  56171. this._renderEndsText(thisGroup, dataRangeText, 1);
  56172. // Do this for background size calculation.
  56173. this._updateView(true);
  56174. // After updating view, inner shapes is built completely,
  56175. // and then background can be rendered.
  56176. this.renderBackground(thisGroup);
  56177. // Real update view
  56178. this._updateView();
  56179. this._enableHoverLinkToSeries();
  56180. this._enableHoverLinkFromSeries();
  56181. this.positionGroup(thisGroup);
  56182. },
  56183. /**
  56184. * @private
  56185. */
  56186. _renderEndsText: function (group, dataRangeText, endsIndex) {
  56187. if (!dataRangeText) {
  56188. return;
  56189. }
  56190. // Compatible with ec2, text[0] map to high value, text[1] map low value.
  56191. var text = dataRangeText[1 - endsIndex];
  56192. text = text != null ? text + '' : '';
  56193. var visualMapModel = this.visualMapModel;
  56194. var textGap = visualMapModel.get('textGap');
  56195. var itemSize = visualMapModel.itemSize;
  56196. var barGroup = this._shapes.barGroup;
  56197. var position = this._applyTransform(
  56198. [
  56199. itemSize[0] / 2,
  56200. endsIndex === 0 ? -textGap : itemSize[1] + textGap
  56201. ],
  56202. barGroup
  56203. );
  56204. var align = this._applyTransform(
  56205. endsIndex === 0 ? 'bottom' : 'top',
  56206. barGroup
  56207. );
  56208. var orient = this._orient;
  56209. var textStyleModel = this.visualMapModel.textStyleModel;
  56210. this.group.add(new graphic.Text({
  56211. style: {
  56212. x: position[0],
  56213. y: position[1],
  56214. textVerticalAlign: orient === 'horizontal' ? 'middle' : align,
  56215. textAlign: orient === 'horizontal' ? align : 'center',
  56216. text: text,
  56217. textFont: textStyleModel.getFont(),
  56218. fill: textStyleModel.getTextColor()
  56219. }
  56220. }));
  56221. },
  56222. /**
  56223. * @private
  56224. */
  56225. _renderBar: function (targetGroup) {
  56226. var visualMapModel = this.visualMapModel;
  56227. var shapes = this._shapes;
  56228. var itemSize = visualMapModel.itemSize;
  56229. var orient = this._orient;
  56230. var useHandle = this._useHandle;
  56231. var itemAlign = helper.getItemAlign(visualMapModel, this.api, itemSize);
  56232. var barGroup = shapes.barGroup = this._createBarGroup(itemAlign);
  56233. // Bar
  56234. barGroup.add(shapes.outOfRange = createPolygon());
  56235. barGroup.add(shapes.inRange = createPolygon(
  56236. null,
  56237. useHandle ? 'move' : null,
  56238. zrUtil.bind(this._dragHandle, this, 'all', false),
  56239. zrUtil.bind(this._dragHandle, this, 'all', true)
  56240. ));
  56241. var textRect = visualMapModel.textStyleModel.getTextRect('国');
  56242. var textSize = mathMax(textRect.width, textRect.height);
  56243. // Handle
  56244. if (useHandle) {
  56245. shapes.handleThumbs = [];
  56246. shapes.handleLabels = [];
  56247. shapes.handleLabelPoints = [];
  56248. this._createHandle(barGroup, 0, itemSize, textSize, orient, itemAlign);
  56249. this._createHandle(barGroup, 1, itemSize, textSize, orient, itemAlign);
  56250. }
  56251. this._createIndicator(barGroup, itemSize, textSize, orient);
  56252. targetGroup.add(barGroup);
  56253. },
  56254. /**
  56255. * @private
  56256. */
  56257. _createHandle: function (barGroup, handleIndex, itemSize, textSize, orient) {
  56258. var onDrift = zrUtil.bind(this._dragHandle, this, handleIndex, false);
  56259. var onDragEnd = zrUtil.bind(this._dragHandle, this, handleIndex, true);
  56260. var handleThumb = createPolygon(
  56261. createHandlePoints(handleIndex, textSize),
  56262. 'move',
  56263. onDrift,
  56264. onDragEnd
  56265. );
  56266. handleThumb.position[0] = itemSize[0];
  56267. barGroup.add(handleThumb);
  56268. // Text is always horizontal layout but should not be effected by
  56269. // transform (orient/inverse). So label is built separately but not
  56270. // use zrender/graphic/helper/RectText, and is located based on view
  56271. // group (according to handleLabelPoint) but not barGroup.
  56272. var textStyleModel = this.visualMapModel.textStyleModel;
  56273. var handleLabel = new graphic.Text({
  56274. draggable: true,
  56275. drift: onDrift,
  56276. onmousemove: function (e) {
  56277. // Fot mobile devicem, prevent screen slider on the button.
  56278. eventTool.stop(e.event);
  56279. },
  56280. ondragend: onDragEnd,
  56281. style: {
  56282. x: 0, y: 0, text: '',
  56283. textFont: textStyleModel.getFont(),
  56284. fill: textStyleModel.getTextColor()
  56285. }
  56286. });
  56287. this.group.add(handleLabel);
  56288. var handleLabelPoint = [
  56289. orient === 'horizontal'
  56290. ? textSize / 2
  56291. : textSize * 1.5,
  56292. orient === 'horizontal'
  56293. ? (handleIndex === 0 ? -(textSize * 1.5) : (textSize * 1.5))
  56294. : (handleIndex === 0 ? -textSize / 2 : textSize / 2)
  56295. ];
  56296. var shapes = this._shapes;
  56297. shapes.handleThumbs[handleIndex] = handleThumb;
  56298. shapes.handleLabelPoints[handleIndex] = handleLabelPoint;
  56299. shapes.handleLabels[handleIndex] = handleLabel;
  56300. },
  56301. /**
  56302. * @private
  56303. */
  56304. _createIndicator: function (barGroup, itemSize, textSize, orient) {
  56305. var indicator = createPolygon([[0, 0]], 'move');
  56306. indicator.position[0] = itemSize[0];
  56307. indicator.attr({invisible: true, silent: true});
  56308. barGroup.add(indicator);
  56309. var textStyleModel = this.visualMapModel.textStyleModel;
  56310. var indicatorLabel = new graphic.Text({
  56311. silent: true,
  56312. invisible: true,
  56313. style: {
  56314. x: 0, y: 0, text: '',
  56315. textFont: textStyleModel.getFont(),
  56316. fill: textStyleModel.getTextColor()
  56317. }
  56318. });
  56319. this.group.add(indicatorLabel);
  56320. var indicatorLabelPoint = [
  56321. orient === 'horizontal' ? textSize / 2 : HOVER_LINK_OUT + 3,
  56322. 0
  56323. ];
  56324. var shapes = this._shapes;
  56325. shapes.indicator = indicator;
  56326. shapes.indicatorLabel = indicatorLabel;
  56327. shapes.indicatorLabelPoint = indicatorLabelPoint;
  56328. },
  56329. /**
  56330. * @private
  56331. */
  56332. _dragHandle: function (handleIndex, isEnd, dx, dy) {
  56333. if (!this._useHandle) {
  56334. return;
  56335. }
  56336. this._dragging = !isEnd;
  56337. if (!isEnd) {
  56338. // Transform dx, dy to bar coordination.
  56339. var vertex = this._applyTransform([dx, dy], this._shapes.barGroup, true);
  56340. this._updateInterval(handleIndex, vertex[1]);
  56341. // Considering realtime, update view should be executed
  56342. // before dispatch action.
  56343. this._updateView();
  56344. }
  56345. // dragEnd do not dispatch action when realtime.
  56346. if (isEnd === !this.visualMapModel.get('realtime')) { // jshint ignore:line
  56347. this.api.dispatchAction({
  56348. type: 'selectDataRange',
  56349. from: this.uid,
  56350. visualMapId: this.visualMapModel.id,
  56351. selected: this._dataInterval.slice()
  56352. });
  56353. }
  56354. if (isEnd) {
  56355. !this._hovering && this._clearHoverLinkToSeries();
  56356. }
  56357. else if (useHoverLinkOnHandle(this.visualMapModel)) {
  56358. this._doHoverLinkToSeries(this._handleEnds[handleIndex], false);
  56359. }
  56360. },
  56361. /**
  56362. * @private
  56363. */
  56364. _resetInterval: function () {
  56365. var visualMapModel = this.visualMapModel;
  56366. var dataInterval = this._dataInterval = visualMapModel.getSelected();
  56367. var dataExtent = visualMapModel.getExtent();
  56368. var sizeExtent = [0, visualMapModel.itemSize[1]];
  56369. this._handleEnds = [
  56370. linearMap(dataInterval[0], dataExtent, sizeExtent, true),
  56371. linearMap(dataInterval[1], dataExtent, sizeExtent, true)
  56372. ];
  56373. },
  56374. /**
  56375. * @private
  56376. * @param {(number|string)} handleIndex 0 or 1 or 'all'
  56377. * @param {number} dx
  56378. * @param {number} dy
  56379. */
  56380. _updateInterval: function (handleIndex, delta) {
  56381. delta = delta || 0;
  56382. var visualMapModel = this.visualMapModel;
  56383. var handleEnds = this._handleEnds;
  56384. var sizeExtent = [0, visualMapModel.itemSize[1]];
  56385. sliderMove(
  56386. delta,
  56387. handleEnds,
  56388. sizeExtent,
  56389. handleIndex,
  56390. // cross is forbiden
  56391. 0
  56392. );
  56393. var dataExtent = visualMapModel.getExtent();
  56394. // Update data interval.
  56395. this._dataInterval = [
  56396. linearMap(handleEnds[0], sizeExtent, dataExtent, true),
  56397. linearMap(handleEnds[1], sizeExtent, dataExtent, true)
  56398. ];
  56399. },
  56400. /**
  56401. * @private
  56402. */
  56403. _updateView: function (forSketch) {
  56404. var visualMapModel = this.visualMapModel;
  56405. var dataExtent = visualMapModel.getExtent();
  56406. var shapes = this._shapes;
  56407. var outOfRangeHandleEnds = [0, visualMapModel.itemSize[1]];
  56408. var inRangeHandleEnds = forSketch ? outOfRangeHandleEnds : this._handleEnds;
  56409. var visualInRange = this._createBarVisual(
  56410. this._dataInterval, dataExtent, inRangeHandleEnds, 'inRange'
  56411. );
  56412. var visualOutOfRange = this._createBarVisual(
  56413. dataExtent, dataExtent, outOfRangeHandleEnds, 'outOfRange'
  56414. );
  56415. shapes.inRange
  56416. .setStyle({
  56417. fill: visualInRange.barColor,
  56418. opacity: visualInRange.opacity
  56419. })
  56420. .setShape('points', visualInRange.barPoints);
  56421. shapes.outOfRange
  56422. .setStyle({
  56423. fill: visualOutOfRange.barColor,
  56424. opacity: visualOutOfRange.opacity
  56425. })
  56426. .setShape('points', visualOutOfRange.barPoints);
  56427. this._updateHandle(inRangeHandleEnds, visualInRange);
  56428. },
  56429. /**
  56430. * @private
  56431. */
  56432. _createBarVisual: function (dataInterval, dataExtent, handleEnds, forceState) {
  56433. var opts = {
  56434. forceState: forceState,
  56435. convertOpacityToAlpha: true
  56436. };
  56437. var colorStops = this._makeColorGradient(dataInterval, opts);
  56438. var symbolSizes = [
  56439. this.getControllerVisual(dataInterval[0], 'symbolSize', opts),
  56440. this.getControllerVisual(dataInterval[1], 'symbolSize', opts)
  56441. ];
  56442. var barPoints = this._createBarPoints(handleEnds, symbolSizes);
  56443. return {
  56444. barColor: new LinearGradient(0, 0, 0, 1, colorStops),
  56445. barPoints: barPoints,
  56446. handlesColor: [
  56447. colorStops[0].color,
  56448. colorStops[colorStops.length - 1].color
  56449. ]
  56450. };
  56451. },
  56452. /**
  56453. * @private
  56454. */
  56455. _makeColorGradient: function (dataInterval, opts) {
  56456. // Considering colorHue, which is not linear, so we have to sample
  56457. // to calculate gradient color stops, but not only caculate head
  56458. // and tail.
  56459. var sampleNumber = 100; // Arbitrary value.
  56460. var colorStops = [];
  56461. var step = (dataInterval[1] - dataInterval[0]) / sampleNumber;
  56462. colorStops.push({
  56463. color: this.getControllerVisual(dataInterval[0], 'color', opts),
  56464. offset: 0
  56465. });
  56466. for (var i = 1; i < sampleNumber; i++) {
  56467. var currValue = dataInterval[0] + step * i;
  56468. if (currValue > dataInterval[1]) {
  56469. break;
  56470. }
  56471. colorStops.push({
  56472. color: this.getControllerVisual(currValue, 'color', opts),
  56473. offset: i / sampleNumber
  56474. });
  56475. }
  56476. colorStops.push({
  56477. color: this.getControllerVisual(dataInterval[1], 'color', opts),
  56478. offset: 1
  56479. });
  56480. return colorStops;
  56481. },
  56482. /**
  56483. * @private
  56484. */
  56485. _createBarPoints: function (handleEnds, symbolSizes) {
  56486. var itemSize = this.visualMapModel.itemSize;
  56487. return [
  56488. [itemSize[0] - symbolSizes[0], handleEnds[0]],
  56489. [itemSize[0], handleEnds[0]],
  56490. [itemSize[0], handleEnds[1]],
  56491. [itemSize[0] - symbolSizes[1], handleEnds[1]]
  56492. ];
  56493. },
  56494. /**
  56495. * @private
  56496. */
  56497. _createBarGroup: function (itemAlign) {
  56498. var orient = this._orient;
  56499. var inverse = this.visualMapModel.get('inverse');
  56500. return new graphic.Group(
  56501. (orient === 'horizontal' && !inverse)
  56502. ? {scale: itemAlign === 'bottom' ? [1, 1] : [-1, 1], rotation: Math.PI / 2}
  56503. : (orient === 'horizontal' && inverse)
  56504. ? {scale: itemAlign === 'bottom' ? [-1, 1] : [1, 1], rotation: -Math.PI / 2}
  56505. : (orient === 'vertical' && !inverse)
  56506. ? {scale: itemAlign === 'left' ? [1, -1] : [-1, -1]}
  56507. : {scale: itemAlign === 'left' ? [1, 1] : [-1, 1]}
  56508. );
  56509. },
  56510. /**
  56511. * @private
  56512. */
  56513. _updateHandle: function (handleEnds, visualInRange) {
  56514. if (!this._useHandle) {
  56515. return;
  56516. }
  56517. var shapes = this._shapes;
  56518. var visualMapModel = this.visualMapModel;
  56519. var handleThumbs = shapes.handleThumbs;
  56520. var handleLabels = shapes.handleLabels;
  56521. each([0, 1], function (handleIndex) {
  56522. var handleThumb = handleThumbs[handleIndex];
  56523. handleThumb.setStyle('fill', visualInRange.handlesColor[handleIndex]);
  56524. handleThumb.position[1] = handleEnds[handleIndex];
  56525. // Update handle label position.
  56526. var textPoint = graphic.applyTransform(
  56527. shapes.handleLabelPoints[handleIndex],
  56528. graphic.getTransform(handleThumb, this.group)
  56529. );
  56530. handleLabels[handleIndex].setStyle({
  56531. x: textPoint[0],
  56532. y: textPoint[1],
  56533. text: visualMapModel.formatValueText(this._dataInterval[handleIndex]),
  56534. textVerticalAlign: 'middle',
  56535. textAlign: this._applyTransform(
  56536. this._orient === 'horizontal'
  56537. ? (handleIndex === 0 ? 'bottom' : 'top')
  56538. : 'left',
  56539. shapes.barGroup
  56540. )
  56541. });
  56542. }, this);
  56543. },
  56544. /**
  56545. * @private
  56546. * @param {number} cursorValue
  56547. * @param {number} textValue
  56548. * @param {string} [rangeSymbol]
  56549. * @param {number} [halfHoverLinkSize]
  56550. */
  56551. _showIndicator: function (cursorValue, textValue, rangeSymbol, halfHoverLinkSize) {
  56552. var visualMapModel = this.visualMapModel;
  56553. var dataExtent = visualMapModel.getExtent();
  56554. var itemSize = visualMapModel.itemSize;
  56555. var sizeExtent = [0, itemSize[1]];
  56556. var pos = linearMap(cursorValue, dataExtent, sizeExtent, true);
  56557. var shapes = this._shapes;
  56558. var indicator = shapes.indicator;
  56559. if (!indicator) {
  56560. return;
  56561. }
  56562. indicator.position[1] = pos;
  56563. indicator.attr('invisible', false);
  56564. indicator.setShape('points', createIndicatorPoints(
  56565. !!rangeSymbol, halfHoverLinkSize, pos, itemSize[1]
  56566. ));
  56567. var opts = {convertOpacityToAlpha: true};
  56568. var color = this.getControllerVisual(cursorValue, 'color', opts);
  56569. indicator.setStyle('fill', color);
  56570. // Update handle label position.
  56571. var textPoint = graphic.applyTransform(
  56572. shapes.indicatorLabelPoint,
  56573. graphic.getTransform(indicator, this.group)
  56574. );
  56575. var indicatorLabel = shapes.indicatorLabel;
  56576. indicatorLabel.attr('invisible', false);
  56577. var align = this._applyTransform('left', shapes.barGroup);
  56578. var orient = this._orient;
  56579. indicatorLabel.setStyle({
  56580. text: (rangeSymbol ? rangeSymbol : '') + visualMapModel.formatValueText(textValue),
  56581. textVerticalAlign: orient === 'horizontal' ? align : 'middle',
  56582. textAlign: orient === 'horizontal' ? 'center' : align,
  56583. x: textPoint[0],
  56584. y: textPoint[1]
  56585. });
  56586. },
  56587. /**
  56588. * @private
  56589. */
  56590. _enableHoverLinkToSeries: function () {
  56591. var self = this;
  56592. this._shapes.barGroup
  56593. .on('mousemove', function (e) {
  56594. self._hovering = true;
  56595. if (!self._dragging) {
  56596. var itemSize = self.visualMapModel.itemSize;
  56597. var pos = self._applyTransform(
  56598. [e.offsetX, e.offsetY], self._shapes.barGroup, true, true
  56599. );
  56600. // For hover link show when hover handle, which might be
  56601. // below or upper than sizeExtent.
  56602. pos[1] = mathMin(mathMax(0, pos[1]), itemSize[1]);
  56603. self._doHoverLinkToSeries(
  56604. pos[1],
  56605. 0 <= pos[0] && pos[0] <= itemSize[0]
  56606. );
  56607. }
  56608. })
  56609. .on('mouseout', function () {
  56610. // When mouse is out of handle, hoverLink still need
  56611. // to be displayed when realtime is set as false.
  56612. self._hovering = false;
  56613. !self._dragging && self._clearHoverLinkToSeries();
  56614. });
  56615. },
  56616. /**
  56617. * @private
  56618. */
  56619. _enableHoverLinkFromSeries: function () {
  56620. var zr = this.api.getZr();
  56621. if (this.visualMapModel.option.hoverLink) {
  56622. zr.on('mouseover', this._hoverLinkFromSeriesMouseOver, this);
  56623. zr.on('mouseout', this._hideIndicator, this);
  56624. }
  56625. else {
  56626. this._clearHoverLinkFromSeries();
  56627. }
  56628. },
  56629. /**
  56630. * @private
  56631. */
  56632. _doHoverLinkToSeries: function (cursorPos, hoverOnBar) {
  56633. var visualMapModel = this.visualMapModel;
  56634. var itemSize = visualMapModel.itemSize;
  56635. if (!visualMapModel.option.hoverLink) {
  56636. return;
  56637. }
  56638. var sizeExtent = [0, itemSize[1]];
  56639. var dataExtent = visualMapModel.getExtent();
  56640. // For hover link show when hover handle, which might be below or upper than sizeExtent.
  56641. cursorPos = mathMin(mathMax(sizeExtent[0], cursorPos), sizeExtent[1]);
  56642. var halfHoverLinkSize = getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent);
  56643. var hoverRange = [cursorPos - halfHoverLinkSize, cursorPos + halfHoverLinkSize];
  56644. var cursorValue = linearMap(cursorPos, sizeExtent, dataExtent, true);
  56645. var valueRange = [
  56646. linearMap(hoverRange[0], sizeExtent, dataExtent, true),
  56647. linearMap(hoverRange[1], sizeExtent, dataExtent, true)
  56648. ];
  56649. // Consider data range is out of visualMap range, see test/visualMap-continuous.html,
  56650. // where china and india has very large population.
  56651. hoverRange[0] < sizeExtent[0] && (valueRange[0] = -Infinity);
  56652. hoverRange[1] > sizeExtent[1] && (valueRange[1] = Infinity);
  56653. // Do not show indicator when mouse is over handle,
  56654. // otherwise labels overlap, especially when dragging.
  56655. if (hoverOnBar) {
  56656. if (valueRange[0] === -Infinity) {
  56657. this._showIndicator(cursorValue, valueRange[1], '< ', halfHoverLinkSize);
  56658. }
  56659. else if (valueRange[1] === Infinity) {
  56660. this._showIndicator(cursorValue, valueRange[0], '> ', halfHoverLinkSize);
  56661. }
  56662. else {
  56663. this._showIndicator(cursorValue, cursorValue, '≈ ', halfHoverLinkSize);
  56664. }
  56665. }
  56666. // When realtime is set as false, handles, which are in barGroup,
  56667. // also trigger hoverLink, which help user to realize where they
  56668. // focus on when dragging. (see test/heatmap-large.html)
  56669. // When realtime is set as true, highlight will not show when hover
  56670. // handle, because the label on handle, which displays a exact value
  56671. // but not range, might mislead users.
  56672. var oldBatch = this._hoverLinkDataIndices;
  56673. var newBatch = [];
  56674. if (hoverOnBar || useHoverLinkOnHandle(visualMapModel)) {
  56675. newBatch = this._hoverLinkDataIndices = visualMapModel.findTargetDataIndices(valueRange);
  56676. }
  56677. var resultBatches = modelUtil.compressBatches(oldBatch, newBatch);
  56678. this._dispatchHighDown('downplay', helper.convertDataIndex(resultBatches[0]));
  56679. this._dispatchHighDown('highlight', helper.convertDataIndex(resultBatches[1]));
  56680. },
  56681. /**
  56682. * @private
  56683. */
  56684. _hoverLinkFromSeriesMouseOver: function (e) {
  56685. var el = e.target;
  56686. var visualMapModel = this.visualMapModel;
  56687. if (!el || el.dataIndex == null) {
  56688. return;
  56689. }
  56690. var dataModel = this.ecModel.getSeriesByIndex(el.seriesIndex);
  56691. if (!visualMapModel.isTargetSeries(dataModel)) {
  56692. return;
  56693. }
  56694. var data = dataModel.getData(el.dataType);
  56695. var dim = data.getDimension(visualMapModel.getDataDimension(data));
  56696. var value = data.get(dim, el.dataIndex, true);
  56697. if (!isNaN(value)) {
  56698. this._showIndicator(value, value);
  56699. }
  56700. },
  56701. /**
  56702. * @private
  56703. */
  56704. _hideIndicator: function () {
  56705. var shapes = this._shapes;
  56706. shapes.indicator && shapes.indicator.attr('invisible', true);
  56707. shapes.indicatorLabel && shapes.indicatorLabel.attr('invisible', true);
  56708. },
  56709. /**
  56710. * @private
  56711. */
  56712. _clearHoverLinkToSeries: function () {
  56713. this._hideIndicator();
  56714. var indices = this._hoverLinkDataIndices;
  56715. this._dispatchHighDown('downplay', helper.convertDataIndex(indices));
  56716. indices.length = 0;
  56717. },
  56718. /**
  56719. * @private
  56720. */
  56721. _clearHoverLinkFromSeries: function () {
  56722. this._hideIndicator();
  56723. var zr = this.api.getZr();
  56724. zr.off('mouseover', this._hoverLinkFromSeriesMouseOver);
  56725. zr.off('mouseout', this._hideIndicator);
  56726. },
  56727. /**
  56728. * @private
  56729. */
  56730. _applyTransform: function (vertex, element, inverse, global) {
  56731. var transform = graphic.getTransform(element, global ? null : this.group);
  56732. return graphic[
  56733. zrUtil.isArray(vertex) ? 'applyTransform' : 'transformDirection'
  56734. ](vertex, transform, inverse);
  56735. },
  56736. /**
  56737. * @private
  56738. */
  56739. _dispatchHighDown: function (type, batch) {
  56740. batch && batch.length && this.api.dispatchAction({
  56741. type: type,
  56742. batch: batch
  56743. });
  56744. },
  56745. /**
  56746. * @override
  56747. */
  56748. dispose: function () {
  56749. this._clearHoverLinkFromSeries();
  56750. this._clearHoverLinkToSeries();
  56751. },
  56752. /**
  56753. * @override
  56754. */
  56755. remove: function () {
  56756. this._clearHoverLinkFromSeries();
  56757. this._clearHoverLinkToSeries();
  56758. }
  56759. });
  56760. function createPolygon(points, cursor, onDrift, onDragEnd) {
  56761. return new graphic.Polygon({
  56762. shape: {points: points},
  56763. draggable: !!onDrift,
  56764. cursor: cursor,
  56765. drift: onDrift,
  56766. onmousemove: function (e) {
  56767. // Fot mobile devicem, prevent screen slider on the button.
  56768. eventTool.stop(e.event);
  56769. },
  56770. ondragend: onDragEnd
  56771. });
  56772. }
  56773. function createHandlePoints(handleIndex, textSize) {
  56774. return handleIndex === 0
  56775. ? [[0, 0], [textSize, 0], [textSize, -textSize]]
  56776. : [[0, 0], [textSize, 0], [textSize, textSize]];
  56777. }
  56778. function createIndicatorPoints(isRange, halfHoverLinkSize, pos, extentMax) {
  56779. return isRange
  56780. ? [ // indicate range
  56781. [0, -mathMin(halfHoverLinkSize, mathMax(pos, 0))],
  56782. [HOVER_LINK_OUT, 0],
  56783. [0, mathMin(halfHoverLinkSize, mathMax(extentMax - pos, 0))]
  56784. ]
  56785. : [ // indicate single value
  56786. [0, 0], [5, -5], [5, 5]
  56787. ];
  56788. }
  56789. function getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent) {
  56790. var halfHoverLinkSize = HOVER_LINK_SIZE / 2;
  56791. var hoverLinkDataSize = visualMapModel.get('hoverLinkDataSize');
  56792. if (hoverLinkDataSize) {
  56793. halfHoverLinkSize = linearMap(hoverLinkDataSize, dataExtent, sizeExtent, true) / 2;
  56794. }
  56795. return halfHoverLinkSize;
  56796. }
  56797. function useHoverLinkOnHandle(visualMapModel) {
  56798. return !visualMapModel.get('realtime') && visualMapModel.get('hoverLinkOnHandle');
  56799. }
  56800. module.exports = ContinuousView;
  56801. /***/ },
  56802. /* 384 */
  56803. /***/ function(module, exports, __webpack_require__) {
  56804. var zrUtil = __webpack_require__(4);
  56805. var graphic = __webpack_require__(18);
  56806. var formatUtil = __webpack_require__(6);
  56807. var layout = __webpack_require__(71);
  56808. var echarts = __webpack_require__(1);
  56809. var VisualMapping = __webpack_require__(202);
  56810. module.exports = echarts.extendComponentView({
  56811. type: 'visualMap',
  56812. /**
  56813. * @readOnly
  56814. * @type {Object}
  56815. */
  56816. autoPositionValues: {left: 1, right: 1, top: 1, bottom: 1},
  56817. init: function (ecModel, api) {
  56818. /**
  56819. * @readOnly
  56820. * @type {module:echarts/model/Global}
  56821. */
  56822. this.ecModel = ecModel;
  56823. /**
  56824. * @readOnly
  56825. * @type {module:echarts/ExtensionAPI}
  56826. */
  56827. this.api = api;
  56828. /**
  56829. * @readOnly
  56830. * @type {module:echarts/component/visualMap/visualMapModel}
  56831. */
  56832. this.visualMapModel;
  56833. },
  56834. /**
  56835. * @protected
  56836. */
  56837. render: function (visualMapModel, ecModel, api, payload) {
  56838. this.visualMapModel = visualMapModel;
  56839. if (visualMapModel.get('show') === false) {
  56840. this.group.removeAll();
  56841. return;
  56842. }
  56843. this.doRender.apply(this, arguments);
  56844. },
  56845. /**
  56846. * @protected
  56847. */
  56848. renderBackground: function (group) {
  56849. var visualMapModel = this.visualMapModel;
  56850. var padding = formatUtil.normalizeCssArray(visualMapModel.get('padding') || 0);
  56851. var rect = group.getBoundingRect();
  56852. group.add(new graphic.Rect({
  56853. z2: -1, // Lay background rect on the lowest layer.
  56854. silent: true,
  56855. shape: {
  56856. x: rect.x - padding[3],
  56857. y: rect.y - padding[0],
  56858. width: rect.width + padding[3] + padding[1],
  56859. height: rect.height + padding[0] + padding[2]
  56860. },
  56861. style: {
  56862. fill: visualMapModel.get('backgroundColor'),
  56863. stroke: visualMapModel.get('borderColor'),
  56864. lineWidth: visualMapModel.get('borderWidth')
  56865. }
  56866. }));
  56867. },
  56868. /**
  56869. * @protected
  56870. * @param {number} targetValue can be Infinity or -Infinity
  56871. * @param {string=} visualCluster Only can be 'color' 'opacity' 'symbol' 'symbolSize'
  56872. * @param {Object} [opts]
  56873. * @param {string=} [opts.forceState] Specify state, instead of using getValueState method.
  56874. * @param {string=} [opts.convertOpacityToAlpha=false] For color gradient in controller widget.
  56875. * @return {*} Visual value.
  56876. */
  56877. getControllerVisual: function (targetValue, visualCluster, opts) {
  56878. opts = opts || {};
  56879. var forceState = opts.forceState;
  56880. var visualMapModel = this.visualMapModel;
  56881. var visualObj = {};
  56882. // Default values.
  56883. if (visualCluster === 'symbol') {
  56884. visualObj.symbol = visualMapModel.get('itemSymbol');
  56885. }
  56886. if (visualCluster === 'color') {
  56887. var defaultColor = visualMapModel.get('contentColor');
  56888. visualObj.color = defaultColor;
  56889. }
  56890. function getter(key) {
  56891. return visualObj[key];
  56892. }
  56893. function setter(key, value) {
  56894. visualObj[key] = value;
  56895. }
  56896. var mappings = visualMapModel.controllerVisuals[
  56897. forceState || visualMapModel.getValueState(targetValue)
  56898. ];
  56899. var visualTypes = VisualMapping.prepareVisualTypes(mappings);
  56900. zrUtil.each(visualTypes, function (type) {
  56901. var visualMapping = mappings[type];
  56902. if (opts.convertOpacityToAlpha && type === 'opacity') {
  56903. type = 'colorAlpha';
  56904. visualMapping = mappings.__alphaForOpacity;
  56905. }
  56906. if (VisualMapping.dependsOn(type, visualCluster)) {
  56907. visualMapping && visualMapping.applyVisual(
  56908. targetValue, getter, setter
  56909. );
  56910. }
  56911. });
  56912. return visualObj[visualCluster];
  56913. },
  56914. /**
  56915. * @protected
  56916. */
  56917. positionGroup: function (group) {
  56918. var model = this.visualMapModel;
  56919. var api = this.api;
  56920. layout.positionElement(
  56921. group,
  56922. model.getBoxLayoutParams(),
  56923. {width: api.getWidth(), height: api.getHeight()}
  56924. );
  56925. },
  56926. /**
  56927. * @protected
  56928. * @abstract
  56929. */
  56930. doRender: zrUtil.noop
  56931. });
  56932. /***/ },
  56933. /* 385 */
  56934. /***/ function(module, exports, __webpack_require__) {
  56935. var zrUtil = __webpack_require__(4);
  56936. var layout = __webpack_require__(71);
  56937. var helper = {
  56938. /**
  56939. * @param {module:echarts/component/visualMap/VisualMapModel} visualMapModel\
  56940. * @param {module:echarts/ExtensionAPI} api
  56941. * @param {Array.<number>} itemSize always [short, long]
  56942. * @return {string} 'left' or 'right' or 'top' or 'bottom'
  56943. */
  56944. getItemAlign: function (visualMapModel, api, itemSize) {
  56945. var modelOption = visualMapModel.option;
  56946. var itemAlign = modelOption.align;
  56947. if (itemAlign != null && itemAlign !== 'auto') {
  56948. return itemAlign;
  56949. }
  56950. // Auto decision align.
  56951. var ecSize = {width: api.getWidth(), height: api.getHeight()};
  56952. var realIndex = modelOption.orient === 'horizontal' ? 1 : 0;
  56953. var paramsSet = [
  56954. ['left', 'right', 'width'],
  56955. ['top', 'bottom', 'height']
  56956. ];
  56957. var reals = paramsSet[realIndex];
  56958. var fakeValue = [0, null, 10];
  56959. var layoutInput = {};
  56960. for (var i = 0; i < 3; i++) {
  56961. layoutInput[paramsSet[1 - realIndex][i]] = fakeValue[i];
  56962. layoutInput[reals[i]] = i === 2 ? itemSize[0] : modelOption[reals[i]];
  56963. }
  56964. var rParam = [['x', 'width', 3], ['y', 'height', 0]][realIndex];
  56965. var rect = layout.getLayoutRect(layoutInput, ecSize, modelOption.padding);
  56966. return reals[
  56967. (rect.margin[rParam[2]] || 0) + rect[rParam[0]] + rect[rParam[1]] * 0.5
  56968. < ecSize[rParam[1]] * 0.5 ? 0 : 1
  56969. ];
  56970. },
  56971. /**
  56972. * Prepare dataIndex for outside usage, where dataIndex means rawIndex, and
  56973. * dataIndexInside means filtered index.
  56974. */
  56975. convertDataIndex: function (batch) {
  56976. zrUtil.each(batch || [], function (batchItem) {
  56977. if (batch.dataIndex != null) {
  56978. batch.dataIndexInside = batch.dataIndex;
  56979. batch.dataIndex = null;
  56980. }
  56981. });
  56982. return batch;
  56983. }
  56984. };
  56985. module.exports = helper;
  56986. /***/ },
  56987. /* 386 */
  56988. /***/ function(module, exports, __webpack_require__) {
  56989. /**
  56990. * @file Data range action
  56991. */
  56992. var echarts = __webpack_require__(1);
  56993. var actionInfo = {
  56994. type: 'selectDataRange',
  56995. event: 'dataRangeSelected',
  56996. // FIXME use updateView appears wrong
  56997. update: 'update'
  56998. };
  56999. echarts.registerAction(actionInfo, function (payload, ecModel) {
  57000. ecModel.eachComponent({mainType: 'visualMap', query: payload}, function (model) {
  57001. model.setSelected(payload.selected);
  57002. });
  57003. });
  57004. /***/ },
  57005. /* 387 */
  57006. /***/ function(module, exports, __webpack_require__) {
  57007. /**
  57008. * DataZoom component entry
  57009. */
  57010. __webpack_require__(1).registerPreprocessor(
  57011. __webpack_require__(377)
  57012. );
  57013. __webpack_require__(378);
  57014. __webpack_require__(379);
  57015. __webpack_require__(388);
  57016. __webpack_require__(389);
  57017. __webpack_require__(386);
  57018. /***/ },
  57019. /* 388 */
  57020. /***/ function(module, exports, __webpack_require__) {
  57021. var VisualMapModel = __webpack_require__(381);
  57022. var zrUtil = __webpack_require__(4);
  57023. var VisualMapping = __webpack_require__(202);
  57024. var visualDefault = __webpack_require__(382);
  57025. var reformIntervals = __webpack_require__(7).reformIntervals;
  57026. var PiecewiseModel = VisualMapModel.extend({
  57027. type: 'visualMap.piecewise',
  57028. /**
  57029. * Order Rule:
  57030. *
  57031. * option.categories / option.pieces / option.text / option.selected:
  57032. * If !option.inverse,
  57033. * Order when vertical: ['top', ..., 'bottom'].
  57034. * Order when horizontal: ['left', ..., 'right'].
  57035. * If option.inverse, the meaning of
  57036. * the order should be reversed.
  57037. *
  57038. * this._pieceList:
  57039. * The order is always [low, ..., high].
  57040. *
  57041. * Mapping from location to low-high:
  57042. * If !option.inverse
  57043. * When vertical, top is high.
  57044. * When horizontal, right is high.
  57045. * If option.inverse, reverse.
  57046. */
  57047. /**
  57048. * @protected
  57049. */
  57050. defaultOption: {
  57051. selected: null, // Object. If not specified, means selected.
  57052. // When pieces and splitNumber: {'0': true, '5': true}
  57053. // When categories: {'cate1': false, 'cate3': true}
  57054. // When selected === false, means all unselected.
  57055. minOpen: false, // Whether include values that smaller than `min`.
  57056. maxOpen: false, // Whether include values that bigger than `max`.
  57057. align: 'auto', // 'auto', 'left', 'right'
  57058. itemWidth: 20, // When put the controller vertically, it is the length of
  57059. // horizontal side of each item. Otherwise, vertical side.
  57060. itemHeight: 14, // When put the controller vertically, it is the length of
  57061. // vertical side of each item. Otherwise, horizontal side.
  57062. itemSymbol: 'roundRect',
  57063. pieceList: null, // Each item is Object, with some of those attrs:
  57064. // {min, max, lt, gt, lte, gte, value,
  57065. // color, colorSaturation, colorAlpha, opacity,
  57066. // symbol, symbolSize}, which customize the range or visual
  57067. // coding of the certain piece. Besides, see "Order Rule".
  57068. categories: null, // category names, like: ['some1', 'some2', 'some3'].
  57069. // Attr min/max are ignored when categories set. See "Order Rule"
  57070. splitNumber: 5, // If set to 5, auto split five pieces equally.
  57071. // If set to 0 and component type not set, component type will be
  57072. // determined as "continuous". (It is less reasonable but for ec2
  57073. // compatibility, see echarts/component/visualMap/typeDefaulter)
  57074. selectedMode: 'multiple', // Can be 'multiple' or 'single'.
  57075. itemGap: 10, // The gap between two items, in px.
  57076. hoverLink: true, // Enable hover highlight.
  57077. showLabel: null // By default, when text is used, label will hide (the logic
  57078. // is remained for compatibility reason)
  57079. },
  57080. /**
  57081. * @override
  57082. */
  57083. optionUpdated: function (newOption, isInit) {
  57084. PiecewiseModel.superApply(this, 'optionUpdated', arguments);
  57085. /**
  57086. * The order is always [low, ..., high].
  57087. * [{text: string, interval: Array.<number>}, ...]
  57088. * @private
  57089. * @type {Array.<Object>}
  57090. */
  57091. this._pieceList = [];
  57092. this.resetTargetSeries();
  57093. this.resetExtent();
  57094. /**
  57095. * 'pieces', 'categories', 'splitNumber'
  57096. * @type {string}
  57097. */
  57098. var mode = this._mode = this._determineMode();
  57099. resetMethods[this._mode].call(this);
  57100. this._resetSelected(newOption, isInit);
  57101. var categories = this.option.categories;
  57102. this.resetVisual(function (mappingOption, state) {
  57103. if (mode === 'categories') {
  57104. mappingOption.mappingMethod = 'category';
  57105. mappingOption.categories = zrUtil.clone(categories);
  57106. }
  57107. else {
  57108. mappingOption.dataExtent = this.getExtent();
  57109. mappingOption.mappingMethod = 'piecewise';
  57110. mappingOption.pieceList = zrUtil.map(this._pieceList, function (piece) {
  57111. var piece = zrUtil.clone(piece);
  57112. if (state !== 'inRange') {
  57113. // FIXME
  57114. // outOfRange do not support special visual in pieces.
  57115. piece.visual = null;
  57116. }
  57117. return piece;
  57118. });
  57119. }
  57120. });
  57121. },
  57122. /**
  57123. * @protected
  57124. * @override
  57125. */
  57126. completeVisualOption: function () {
  57127. // Consider this case:
  57128. // visualMap: {
  57129. // pieces: [{symbol: 'circle', lt: 0}, {symbol: 'rect', gte: 0}]
  57130. // }
  57131. // where no inRange/outOfRange set but only pieces. So we should make
  57132. // default inRange/outOfRange for this case, otherwise visuals that only
  57133. // appear in `pieces` will not be taken into account in visual encoding.
  57134. var option = this.option;
  57135. var visualTypesInPieces = {};
  57136. var visualTypes = VisualMapping.listVisualTypes();
  57137. var isCategory = this.isCategory();
  57138. zrUtil.each(option.pieces, function (piece) {
  57139. zrUtil.each(visualTypes, function (visualType) {
  57140. if (piece.hasOwnProperty(visualType)) {
  57141. visualTypesInPieces[visualType] = 1;
  57142. }
  57143. });
  57144. });
  57145. zrUtil.each(visualTypesInPieces, function (v, visualType) {
  57146. var exists = 0;
  57147. zrUtil.each(this.stateList, function (state) {
  57148. exists |= has(option, state, visualType)
  57149. || has(option.target, state, visualType);
  57150. }, this);
  57151. !exists && zrUtil.each(this.stateList, function (state) {
  57152. (option[state] || (option[state] = {}))[visualType] = visualDefault.get(
  57153. visualType, state === 'inRange' ? 'active' : 'inactive', isCategory
  57154. );
  57155. });
  57156. }, this);
  57157. function has(obj, state, visualType) {
  57158. return obj && obj[state] && (
  57159. zrUtil.isObject(obj[state])
  57160. ? obj[state].hasOwnProperty(visualType)
  57161. : obj[state] === visualType // e.g., inRange: 'symbol'
  57162. );
  57163. }
  57164. VisualMapModel.prototype.completeVisualOption.apply(this, arguments);
  57165. },
  57166. _resetSelected: function (newOption, isInit) {
  57167. var thisOption = this.option;
  57168. var pieceList = this._pieceList;
  57169. // Selected do not merge but all override.
  57170. var selected = (isInit ? thisOption : newOption).selected || {};
  57171. thisOption.selected = selected;
  57172. // Consider 'not specified' means true.
  57173. zrUtil.each(pieceList, function (piece, index) {
  57174. var key = this.getSelectedMapKey(piece);
  57175. if (!selected.hasOwnProperty(key)) {
  57176. selected[key] = true;
  57177. }
  57178. }, this);
  57179. if (thisOption.selectedMode === 'single') {
  57180. // Ensure there is only one selected.
  57181. var hasSel = false;
  57182. zrUtil.each(pieceList, function (piece, index) {
  57183. var key = this.getSelectedMapKey(piece);
  57184. if (selected[key]) {
  57185. hasSel
  57186. ? (selected[key] = false)
  57187. : (hasSel = true);
  57188. }
  57189. }, this);
  57190. }
  57191. // thisOption.selectedMode === 'multiple', default: all selected.
  57192. },
  57193. /**
  57194. * @public
  57195. */
  57196. getSelectedMapKey: function (piece) {
  57197. return this._mode === 'categories'
  57198. ? piece.value + '' : piece.index + '';
  57199. },
  57200. /**
  57201. * @public
  57202. */
  57203. getPieceList: function () {
  57204. return this._pieceList;
  57205. },
  57206. /**
  57207. * @private
  57208. * @return {string}
  57209. */
  57210. _determineMode: function () {
  57211. var option = this.option;
  57212. return option.pieces && option.pieces.length > 0
  57213. ? 'pieces'
  57214. : this.option.categories
  57215. ? 'categories'
  57216. : 'splitNumber';
  57217. },
  57218. /**
  57219. * @public
  57220. * @override
  57221. */
  57222. setSelected: function (selected) {
  57223. this.option.selected = zrUtil.clone(selected);
  57224. },
  57225. /**
  57226. * @public
  57227. * @override
  57228. */
  57229. getValueState: function (value) {
  57230. var index = VisualMapping.findPieceIndex(value, this._pieceList);
  57231. return index != null
  57232. ? (this.option.selected[this.getSelectedMapKey(this._pieceList[index])]
  57233. ? 'inRange' : 'outOfRange'
  57234. )
  57235. : 'outOfRange';
  57236. },
  57237. /**
  57238. * @public
  57239. * @params {number} pieceIndex piece index in visualMapModel.getPieceList()
  57240. * @return {Array.<Object>} [{seriesId, dataIndices: <Array.<number>>}, ...]
  57241. */
  57242. findTargetDataIndices: function (pieceIndex) {
  57243. var result = [];
  57244. this.eachTargetSeries(function (seriesModel) {
  57245. var dataIndices = [];
  57246. var data = seriesModel.getData();
  57247. data.each(this.getDataDimension(data), function (value, dataIndex) {
  57248. // Should always base on model pieceList, because it is order sensitive.
  57249. var pIdx = VisualMapping.findPieceIndex(value, this._pieceList);
  57250. pIdx === pieceIndex && dataIndices.push(dataIndex);
  57251. }, true, this);
  57252. result.push({seriesId: seriesModel.id, dataIndex: dataIndices});
  57253. }, this);
  57254. return result;
  57255. },
  57256. /**
  57257. * @private
  57258. * @param {Object} piece piece.value or piece.interval is required.
  57259. * @return {number} Can be Infinity or -Infinity
  57260. */
  57261. getRepresentValue: function (piece) {
  57262. var representValue;
  57263. if (this.isCategory()) {
  57264. representValue = piece.value;
  57265. }
  57266. else {
  57267. if (piece.value != null) {
  57268. representValue = piece.value;
  57269. }
  57270. else {
  57271. var pieceInterval = piece.interval || [];
  57272. representValue = (pieceInterval[0] === -Infinity && pieceInterval[1] === Infinity)
  57273. ? 0
  57274. : (pieceInterval[0] + pieceInterval[1]) / 2;
  57275. }
  57276. }
  57277. return representValue;
  57278. },
  57279. getVisualMeta: function (getColorVisual) {
  57280. // Do not support category. (category axis is ordinal, numerical)
  57281. if (this.isCategory()) {
  57282. return;
  57283. }
  57284. var stops = [];
  57285. var outerColors = [];
  57286. var visualMapModel = this;
  57287. function setStop(interval, valueState) {
  57288. var representValue = visualMapModel.getRepresentValue({interval: interval});
  57289. if (!valueState) {
  57290. valueState = visualMapModel.getValueState(representValue);
  57291. }
  57292. var color = getColorVisual(representValue, valueState);
  57293. if (interval[0] === -Infinity) {
  57294. outerColors[0] = color;
  57295. }
  57296. else if (interval[1] === Infinity) {
  57297. outerColors[1] = color;
  57298. }
  57299. else {
  57300. stops.push(
  57301. {value: interval[0], color: color},
  57302. {value: interval[1], color: color}
  57303. );
  57304. }
  57305. }
  57306. // Suplement
  57307. var pieceList = this._pieceList.slice();
  57308. if (!pieceList.length) {
  57309. pieceList.push({interval: [-Infinity, Infinity]});
  57310. }
  57311. else {
  57312. var edge = pieceList[0].interval[0];
  57313. edge !== -Infinity && pieceList.unshift({interval: [-Infinity, edge]});
  57314. edge = pieceList[pieceList.length - 1].interval[1];
  57315. edge !== Infinity && pieceList.push({interval: [edge, Infinity]});
  57316. }
  57317. var curr = -Infinity;
  57318. zrUtil.each(pieceList, function (piece) {
  57319. var interval = piece.interval;
  57320. if (interval) {
  57321. // Fulfill gap.
  57322. interval[0] > curr && setStop([curr, interval[0]], 'outOfRange');
  57323. setStop(interval.slice());
  57324. curr = interval[1];
  57325. }
  57326. }, this);
  57327. return {stops: stops, outerColors: outerColors};
  57328. }
  57329. });
  57330. /**
  57331. * Key is this._mode
  57332. * @type {Object}
  57333. * @this {module:echarts/component/viusalMap/PiecewiseMode}
  57334. */
  57335. var resetMethods = {
  57336. splitNumber: function () {
  57337. var thisOption = this.option;
  57338. var pieceList = this._pieceList;
  57339. var precision = thisOption.precision;
  57340. var dataExtent = this.getExtent();
  57341. var splitNumber = thisOption.splitNumber;
  57342. splitNumber = Math.max(parseInt(splitNumber, 10), 1);
  57343. thisOption.splitNumber = splitNumber;
  57344. var splitStep = (dataExtent[1] - dataExtent[0]) / splitNumber;
  57345. // Precision auto-adaption
  57346. while (+splitStep.toFixed(precision) !== splitStep && precision < 5) {
  57347. precision++;
  57348. }
  57349. thisOption.precision = precision;
  57350. splitStep = +splitStep.toFixed(precision);
  57351. var index = 0;
  57352. if (thisOption.minOpen) {
  57353. pieceList.push({
  57354. index: index++,
  57355. interval: [-Infinity, dataExtent[0]],
  57356. close: [0, 0]
  57357. });
  57358. }
  57359. for (
  57360. var curr = dataExtent[0], len = index + splitNumber;
  57361. index < len;
  57362. curr += splitStep
  57363. ) {
  57364. var max = index === splitNumber - 1 ? dataExtent[1] : (curr + splitStep);
  57365. pieceList.push({
  57366. index: index++,
  57367. interval: [curr, max],
  57368. close: [1, 1]
  57369. });
  57370. }
  57371. if (thisOption.maxOpen) {
  57372. pieceList.push({
  57373. index: index++,
  57374. interval: [dataExtent[1], Infinity],
  57375. close: [0, 0]
  57376. });
  57377. }
  57378. reformIntervals(pieceList);
  57379. zrUtil.each(pieceList, function (piece) {
  57380. piece.text = this.formatValueText(piece.interval);
  57381. }, this);
  57382. },
  57383. categories: function () {
  57384. var thisOption = this.option;
  57385. zrUtil.each(thisOption.categories, function (cate) {
  57386. // FIXME category模式也使用pieceList,但在visualMapping中不是使用pieceList。
  57387. // 是否改一致。
  57388. this._pieceList.push({
  57389. text: this.formatValueText(cate, true),
  57390. value: cate
  57391. });
  57392. }, this);
  57393. // See "Order Rule".
  57394. normalizeReverse(thisOption, this._pieceList);
  57395. },
  57396. pieces: function () {
  57397. var thisOption = this.option;
  57398. var pieceList = this._pieceList;
  57399. zrUtil.each(thisOption.pieces, function (pieceListItem, index) {
  57400. if (!zrUtil.isObject(pieceListItem)) {
  57401. pieceListItem = {value: pieceListItem};
  57402. }
  57403. var item = {text: '', index: index};
  57404. if (pieceListItem.label != null) {
  57405. item.text = pieceListItem.label;
  57406. }
  57407. if (pieceListItem.hasOwnProperty('value')) {
  57408. var value = item.value = pieceListItem.value;
  57409. item.interval = [value, value];
  57410. item.close = [1, 1];
  57411. }
  57412. else {
  57413. // `min` `max` is legacy option.
  57414. // `lt` `gt` `lte` `gte` is recommanded.
  57415. var interval = item.interval = [];
  57416. var close = item.close = [0, 0];
  57417. var closeList = [1, 0, 1];
  57418. var infinityList = [-Infinity, Infinity];
  57419. var useMinMax = [];
  57420. for (var lg = 0; lg < 2; lg++) {
  57421. var names = [['gte', 'gt', 'min'], ['lte', 'lt', 'max']][lg];
  57422. for (var i = 0; i < 3 && interval[lg] == null; i++) {
  57423. interval[lg] = pieceListItem[names[i]];
  57424. close[lg] = closeList[i];
  57425. useMinMax[lg] = i === 2;
  57426. }
  57427. interval[lg] == null && (interval[lg] = infinityList[lg]);
  57428. }
  57429. useMinMax[0] && interval[1] === Infinity && (close[0] = 0);
  57430. useMinMax[1] && interval[0] === -Infinity && (close[1] = 0);
  57431. if (true) {
  57432. if (interval[0] > interval[1]) {
  57433. console.warn(
  57434. 'Piece ' + index + 'is illegal: ' + interval
  57435. + ' lower bound should not greater then uppper bound.'
  57436. );
  57437. }
  57438. }
  57439. if (interval[0] === interval[1] && close[0] && close[1]) {
  57440. // Consider: [{min: 5, max: 5, visual: {...}}, {min: 0, max: 5}],
  57441. // we use value to lift the priority when min === max
  57442. item.value = interval[0];
  57443. }
  57444. }
  57445. item.visual = VisualMapping.retrieveVisuals(pieceListItem);
  57446. pieceList.push(item);
  57447. }, this);
  57448. // See "Order Rule".
  57449. normalizeReverse(thisOption, pieceList);
  57450. // Only pieces
  57451. reformIntervals(pieceList);
  57452. zrUtil.each(pieceList, function (piece) {
  57453. var close = piece.close;
  57454. var edgeSymbols = [['<', '≤'][close[1]], ['>', '≥'][close[0]]];
  57455. piece.text = piece.text || this.formatValueText(
  57456. piece.value != null ? piece.value : piece.interval,
  57457. false,
  57458. edgeSymbols
  57459. );
  57460. }, this);
  57461. }
  57462. };
  57463. function normalizeReverse(thisOption, pieceList) {
  57464. var inverse = thisOption.inverse;
  57465. if (thisOption.orient === 'vertical' ? !inverse : inverse) {
  57466. pieceList.reverse();
  57467. }
  57468. }
  57469. module.exports = PiecewiseModel;
  57470. /***/ },
  57471. /* 389 */
  57472. /***/ function(module, exports, __webpack_require__) {
  57473. var VisualMapView = __webpack_require__(384);
  57474. var zrUtil = __webpack_require__(4);
  57475. var graphic = __webpack_require__(18);
  57476. var symbolCreators = __webpack_require__(111);
  57477. var layout = __webpack_require__(71);
  57478. var helper = __webpack_require__(385);
  57479. var PiecewiseVisualMapView = VisualMapView.extend({
  57480. type: 'visualMap.piecewise',
  57481. /**
  57482. * @protected
  57483. * @override
  57484. */
  57485. doRender: function () {
  57486. var thisGroup = this.group;
  57487. thisGroup.removeAll();
  57488. var visualMapModel = this.visualMapModel;
  57489. var textGap = visualMapModel.get('textGap');
  57490. var textStyleModel = visualMapModel.textStyleModel;
  57491. var textFont = textStyleModel.getFont();
  57492. var textFill = textStyleModel.getTextColor();
  57493. var itemAlign = this._getItemAlign();
  57494. var itemSize = visualMapModel.itemSize;
  57495. var viewData = this._getViewData();
  57496. var endsText = viewData.endsText;
  57497. var showLabel = zrUtil.retrieve(visualMapModel.get('showLabel', true), !endsText);
  57498. endsText && this._renderEndsText(
  57499. thisGroup, endsText[0], itemSize, showLabel, itemAlign
  57500. );
  57501. zrUtil.each(viewData.viewPieceList, renderItem, this);
  57502. endsText && this._renderEndsText(
  57503. thisGroup, endsText[1], itemSize, showLabel, itemAlign
  57504. );
  57505. layout.box(
  57506. visualMapModel.get('orient'), thisGroup, visualMapModel.get('itemGap')
  57507. );
  57508. this.renderBackground(thisGroup);
  57509. this.positionGroup(thisGroup);
  57510. function renderItem(item) {
  57511. var piece = item.piece;
  57512. var itemGroup = new graphic.Group();
  57513. itemGroup.onclick = zrUtil.bind(this._onItemClick, this, piece);
  57514. this._enableHoverLink(itemGroup, item.indexInModelPieceList);
  57515. var representValue = visualMapModel.getRepresentValue(piece);
  57516. this._createItemSymbol(
  57517. itemGroup, representValue, [0, 0, itemSize[0], itemSize[1]]
  57518. );
  57519. if (showLabel) {
  57520. var visualState = this.visualMapModel.getValueState(representValue);
  57521. itemGroup.add(new graphic.Text({
  57522. style: {
  57523. x: itemAlign === 'right' ? -textGap : itemSize[0] + textGap,
  57524. y: itemSize[1] / 2,
  57525. text: piece.text,
  57526. textVerticalAlign: 'middle',
  57527. textAlign: itemAlign,
  57528. textFont: textFont,
  57529. fill: textFill,
  57530. opacity: visualState === 'outOfRange' ? 0.5 : 1
  57531. }
  57532. }));
  57533. }
  57534. thisGroup.add(itemGroup);
  57535. }
  57536. },
  57537. /**
  57538. * @private
  57539. */
  57540. _enableHoverLink: function (itemGroup, pieceIndex) {
  57541. itemGroup
  57542. .on('mouseover', zrUtil.bind(onHoverLink, this, 'highlight'))
  57543. .on('mouseout', zrUtil.bind(onHoverLink, this, 'downplay'));
  57544. function onHoverLink(method) {
  57545. var visualMapModel = this.visualMapModel;
  57546. visualMapModel.option.hoverLink && this.api.dispatchAction({
  57547. type: method,
  57548. batch: helper.convertDataIndex(
  57549. visualMapModel.findTargetDataIndices(pieceIndex)
  57550. )
  57551. });
  57552. }
  57553. },
  57554. /**
  57555. * @private
  57556. */
  57557. _getItemAlign: function () {
  57558. var visualMapModel = this.visualMapModel;
  57559. var modelOption = visualMapModel.option;
  57560. if (modelOption.orient === 'vertical') {
  57561. return helper.getItemAlign(
  57562. visualMapModel, this.api, visualMapModel.itemSize
  57563. );
  57564. }
  57565. else { // horizontal, most case left unless specifying right.
  57566. var align = modelOption.align;
  57567. if (!align || align === 'auto') {
  57568. align = 'left';
  57569. }
  57570. return align;
  57571. }
  57572. },
  57573. /**
  57574. * @private
  57575. */
  57576. _renderEndsText: function (group, text, itemSize, showLabel, itemAlign) {
  57577. if (!text) {
  57578. return;
  57579. }
  57580. var itemGroup = new graphic.Group();
  57581. var textStyleModel = this.visualMapModel.textStyleModel;
  57582. itemGroup.add(new graphic.Text({
  57583. style: {
  57584. x: showLabel ? (itemAlign === 'right' ? itemSize[0] : 0) : itemSize[0] / 2,
  57585. y: itemSize[1] / 2,
  57586. textVerticalAlign: 'middle',
  57587. textAlign: showLabel ? itemAlign : 'center',
  57588. text: text,
  57589. textFont: textStyleModel.getFont(),
  57590. fill: textStyleModel.getTextColor()
  57591. }
  57592. }));
  57593. group.add(itemGroup);
  57594. },
  57595. /**
  57596. * @private
  57597. * @return {Object} {peiceList, endsText} The order is the same as screen pixel order.
  57598. */
  57599. _getViewData: function () {
  57600. var visualMapModel = this.visualMapModel;
  57601. var viewPieceList = zrUtil.map(visualMapModel.getPieceList(), function (piece, index) {
  57602. return {piece: piece, indexInModelPieceList: index};
  57603. });
  57604. var endsText = visualMapModel.get('text');
  57605. // Consider orient and inverse.
  57606. var orient = visualMapModel.get('orient');
  57607. var inverse = visualMapModel.get('inverse');
  57608. // Order of model pieceList is always [low, ..., high]
  57609. if (orient === 'horizontal' ? inverse : !inverse) {
  57610. viewPieceList.reverse();
  57611. }
  57612. // Origin order of endsText is [high, low]
  57613. else if (endsText) {
  57614. endsText = endsText.slice().reverse();
  57615. }
  57616. return {viewPieceList: viewPieceList, endsText: endsText};
  57617. },
  57618. /**
  57619. * @private
  57620. */
  57621. _createItemSymbol: function (group, representValue, shapeParam) {
  57622. group.add(symbolCreators.createSymbol(
  57623. this.getControllerVisual(representValue, 'symbol'),
  57624. shapeParam[0], shapeParam[1], shapeParam[2], shapeParam[3],
  57625. this.getControllerVisual(representValue, 'color')
  57626. ));
  57627. },
  57628. /**
  57629. * @private
  57630. */
  57631. _onItemClick: function (piece) {
  57632. var visualMapModel = this.visualMapModel;
  57633. var option = visualMapModel.option;
  57634. var selected = zrUtil.clone(option.selected);
  57635. var newKey = visualMapModel.getSelectedMapKey(piece);
  57636. if (option.selectedMode === 'single') {
  57637. selected[newKey] = true;
  57638. zrUtil.each(selected, function (o, key) {
  57639. selected[key] = key === newKey;
  57640. });
  57641. }
  57642. else {
  57643. selected[newKey] = !selected[newKey];
  57644. }
  57645. this.api.dispatchAction({
  57646. type: 'selectDataRange',
  57647. from: this.uid,
  57648. visualMapId: this.visualMapModel.id,
  57649. selected: selected
  57650. });
  57651. }
  57652. });
  57653. module.exports = PiecewiseVisualMapView;
  57654. /***/ },
  57655. /* 390 */
  57656. /***/ function(module, exports, __webpack_require__) {
  57657. // HINT Markpoint can't be used too much
  57658. __webpack_require__(391);
  57659. __webpack_require__(393);
  57660. __webpack_require__(1).registerPreprocessor(function (opt) {
  57661. // Make sure markPoint component is enabled
  57662. opt.markPoint = opt.markPoint || {};
  57663. });
  57664. /***/ },
  57665. /* 391 */
  57666. /***/ function(module, exports, __webpack_require__) {
  57667. module.exports = __webpack_require__(392).extend({
  57668. type: 'markPoint',
  57669. defaultOption: {
  57670. zlevel: 0,
  57671. z: 5,
  57672. symbol: 'pin',
  57673. symbolSize: 50,
  57674. //symbolRotate: 0,
  57675. //symbolOffset: [0, 0]
  57676. tooltip: {
  57677. trigger: 'item'
  57678. },
  57679. label: {
  57680. normal: {
  57681. show: true,
  57682. position: 'inside'
  57683. },
  57684. emphasis: {
  57685. show: true
  57686. }
  57687. },
  57688. itemStyle: {
  57689. normal: {
  57690. borderWidth: 2
  57691. }
  57692. }
  57693. }
  57694. });
  57695. /***/ },
  57696. /* 392 */
  57697. /***/ function(module, exports, __webpack_require__) {
  57698. var modelUtil = __webpack_require__(5);
  57699. var zrUtil = __webpack_require__(4);
  57700. var env = __webpack_require__(2);
  57701. var formatUtil = __webpack_require__(6);
  57702. var addCommas = formatUtil.addCommas;
  57703. var encodeHTML = formatUtil.encodeHTML;
  57704. function fillLabel(opt) {
  57705. modelUtil.defaultEmphasis(
  57706. opt.label,
  57707. modelUtil.LABEL_OPTIONS
  57708. );
  57709. }
  57710. var MarkerModel = __webpack_require__(1).extendComponentModel({
  57711. type: 'marker',
  57712. dependencies: ['series', 'grid', 'polar', 'geo'],
  57713. /**
  57714. * @overrite
  57715. */
  57716. init: function (option, parentModel, ecModel, extraOpt) {
  57717. if (true) {
  57718. if (this.type === 'marker') {
  57719. throw new Error('Marker component is abstract component. Use markLine, markPoint, markArea instead.');
  57720. }
  57721. }
  57722. this.mergeDefaultAndTheme(option, ecModel);
  57723. this.mergeOption(option, ecModel, extraOpt.createdBySelf, true);
  57724. },
  57725. /**
  57726. * @return {boolean}
  57727. */
  57728. isAnimationEnabled: function () {
  57729. if (env.node) {
  57730. return false;
  57731. }
  57732. var hostSeries = this.__hostSeries;
  57733. return this.getShallow('animation') && hostSeries && hostSeries.isAnimationEnabled();
  57734. },
  57735. mergeOption: function (newOpt, ecModel, createdBySelf, isInit) {
  57736. var MarkerModel = this.constructor;
  57737. var modelPropName = this.mainType + 'Model';
  57738. if (!createdBySelf) {
  57739. ecModel.eachSeries(function (seriesModel) {
  57740. var markerOpt = seriesModel.get(this.mainType);
  57741. var markerModel = seriesModel[modelPropName];
  57742. if (!markerOpt || !markerOpt.data) {
  57743. seriesModel[modelPropName] = null;
  57744. return;
  57745. }
  57746. if (!markerModel) {
  57747. if (isInit) {
  57748. // Default label emphasis `position` and `show`
  57749. fillLabel(markerOpt);
  57750. }
  57751. zrUtil.each(markerOpt.data, function (item) {
  57752. // FIXME Overwrite fillLabel method ?
  57753. if (item instanceof Array) {
  57754. fillLabel(item[0]);
  57755. fillLabel(item[1]);
  57756. }
  57757. else {
  57758. fillLabel(item);
  57759. }
  57760. });
  57761. markerModel = new MarkerModel(
  57762. markerOpt, this, ecModel
  57763. );
  57764. zrUtil.extend(markerModel, {
  57765. mainType: this.mainType,
  57766. // Use the same series index and name
  57767. seriesIndex: seriesModel.seriesIndex,
  57768. name: seriesModel.name,
  57769. createdBySelf: true
  57770. });
  57771. markerModel.__hostSeries = seriesModel;
  57772. }
  57773. else {
  57774. markerModel.mergeOption(markerOpt, ecModel, true);
  57775. }
  57776. seriesModel[modelPropName] = markerModel;
  57777. }, this);
  57778. }
  57779. },
  57780. formatTooltip: function (dataIndex) {
  57781. var data = this.getData();
  57782. var value = this.getRawValue(dataIndex);
  57783. var formattedValue = zrUtil.isArray(value)
  57784. ? zrUtil.map(value, addCommas).join(', ') : addCommas(value);
  57785. var name = data.getName(dataIndex);
  57786. var html = encodeHTML(this.name);
  57787. if (value != null || name) {
  57788. html += '<br />';
  57789. }
  57790. if (name) {
  57791. html += encodeHTML(name);
  57792. if (value != null) {
  57793. html += ' : ';
  57794. }
  57795. }
  57796. if (value != null) {
  57797. html += encodeHTML(formattedValue);
  57798. }
  57799. return html;
  57800. },
  57801. getData: function () {
  57802. return this._data;
  57803. },
  57804. setData: function (data) {
  57805. this._data = data;
  57806. }
  57807. });
  57808. zrUtil.mixin(MarkerModel, modelUtil.dataFormatMixin);
  57809. module.exports = MarkerModel;
  57810. /***/ },
  57811. /* 393 */
  57812. /***/ function(module, exports, __webpack_require__) {
  57813. var SymbolDraw = __webpack_require__(116);
  57814. var zrUtil = __webpack_require__(4);
  57815. var numberUtil = __webpack_require__(7);
  57816. var List = __webpack_require__(98);
  57817. var markerHelper = __webpack_require__(394);
  57818. function updateMarkerLayout(mpData, seriesModel, api) {
  57819. var coordSys = seriesModel.coordinateSystem;
  57820. mpData.each(function (idx) {
  57821. var itemModel = mpData.getItemModel(idx);
  57822. var point;
  57823. var xPx = numberUtil.parsePercent(itemModel.get('x'), api.getWidth());
  57824. var yPx = numberUtil.parsePercent(itemModel.get('y'), api.getHeight());
  57825. if (!isNaN(xPx) && !isNaN(yPx)) {
  57826. point = [xPx, yPx];
  57827. }
  57828. // Chart like bar may have there own marker positioning logic
  57829. else if (seriesModel.getMarkerPosition) {
  57830. // Use the getMarkerPoisition
  57831. point = seriesModel.getMarkerPosition(
  57832. mpData.getValues(mpData.dimensions, idx)
  57833. );
  57834. }
  57835. else if (coordSys) {
  57836. var x = mpData.get(coordSys.dimensions[0], idx);
  57837. var y = mpData.get(coordSys.dimensions[1], idx);
  57838. point = coordSys.dataToPoint([x, y]);
  57839. }
  57840. // Use x, y if has any
  57841. if (!isNaN(xPx)) {
  57842. point[0] = xPx;
  57843. }
  57844. if (!isNaN(yPx)) {
  57845. point[1] = yPx;
  57846. }
  57847. mpData.setItemLayout(idx, point);
  57848. });
  57849. }
  57850. __webpack_require__(395).extend({
  57851. type: 'markPoint',
  57852. updateLayout: function (markPointModel, ecModel, api) {
  57853. ecModel.eachSeries(function (seriesModel) {
  57854. var mpModel = seriesModel.markPointModel;
  57855. if (mpModel) {
  57856. updateMarkerLayout(mpModel.getData(), seriesModel, api);
  57857. this.markerGroupMap.get(seriesModel.name).updateLayout(mpModel);
  57858. }
  57859. }, this);
  57860. },
  57861. renderSeries: function (seriesModel, mpModel, ecModel, api) {
  57862. var coordSys = seriesModel.coordinateSystem;
  57863. var seriesName = seriesModel.name;
  57864. var seriesData = seriesModel.getData();
  57865. var symbolDrawMap = this.markerGroupMap;
  57866. var symbolDraw = symbolDrawMap.get(seriesName)
  57867. || symbolDrawMap.set(seriesName, new SymbolDraw());
  57868. var mpData = createList(coordSys, seriesModel, mpModel);
  57869. // FIXME
  57870. mpModel.setData(mpData);
  57871. updateMarkerLayout(mpModel.getData(), seriesModel, api);
  57872. mpData.each(function (idx) {
  57873. var itemModel = mpData.getItemModel(idx);
  57874. var symbolSize = itemModel.getShallow('symbolSize');
  57875. if (typeof symbolSize === 'function') {
  57876. // FIXME 这里不兼容 ECharts 2.x,2.x 貌似参数是整个数据?
  57877. symbolSize = symbolSize(
  57878. mpModel.getRawValue(idx), mpModel.getDataParams(idx)
  57879. );
  57880. }
  57881. mpData.setItemVisual(idx, {
  57882. symbolSize: symbolSize,
  57883. color: itemModel.get('itemStyle.normal.color')
  57884. || seriesData.getVisual('color'),
  57885. symbol: itemModel.getShallow('symbol')
  57886. });
  57887. });
  57888. // TODO Text are wrong
  57889. symbolDraw.updateData(mpData);
  57890. this.group.add(symbolDraw.group);
  57891. // Set host model for tooltip
  57892. // FIXME
  57893. mpData.eachItemGraphicEl(function (el) {
  57894. el.traverse(function (child) {
  57895. child.dataModel = mpModel;
  57896. });
  57897. });
  57898. symbolDraw.__keep = true;
  57899. symbolDraw.group.silent = mpModel.get('silent') || seriesModel.get('silent');
  57900. }
  57901. });
  57902. /**
  57903. * @inner
  57904. * @param {module:echarts/coord/*} [coordSys]
  57905. * @param {module:echarts/model/Series} seriesModel
  57906. * @param {module:echarts/model/Model} mpModel
  57907. */
  57908. function createList(coordSys, seriesModel, mpModel) {
  57909. var coordDimsInfos;
  57910. if (coordSys) {
  57911. coordDimsInfos = zrUtil.map(coordSys && coordSys.dimensions, function (coordDim) {
  57912. var info = seriesModel.getData().getDimensionInfo(
  57913. seriesModel.coordDimToDataDim(coordDim)[0]
  57914. ) || {}; // In map series data don't have lng and lat dimension. Fallback to same with coordSys
  57915. info.name = coordDim;
  57916. return info;
  57917. });
  57918. }
  57919. else {
  57920. coordDimsInfos =[{
  57921. name: 'value',
  57922. type: 'float'
  57923. }];
  57924. }
  57925. var mpData = new List(coordDimsInfos, mpModel);
  57926. var dataOpt = zrUtil.map(mpModel.get('data'), zrUtil.curry(
  57927. markerHelper.dataTransform, seriesModel
  57928. ));
  57929. if (coordSys) {
  57930. dataOpt = zrUtil.filter(
  57931. dataOpt, zrUtil.curry(markerHelper.dataFilter, coordSys)
  57932. );
  57933. }
  57934. mpData.initData(dataOpt, null,
  57935. coordSys ? markerHelper.dimValueGetter : function (item) {
  57936. return item.value;
  57937. }
  57938. );
  57939. return mpData;
  57940. }
  57941. /***/ },
  57942. /* 394 */
  57943. /***/ function(module, exports, __webpack_require__) {
  57944. var zrUtil = __webpack_require__(4);
  57945. var numberUtil = __webpack_require__(7);
  57946. var indexOf = zrUtil.indexOf;
  57947. function hasXOrY(item) {
  57948. return !(isNaN(parseFloat(item.x)) && isNaN(parseFloat(item.y)));
  57949. }
  57950. function hasXAndY(item) {
  57951. return !isNaN(parseFloat(item.x)) && !isNaN(parseFloat(item.y));
  57952. }
  57953. function getPrecision(data, valueAxisDim, dataIndex) {
  57954. var precision = -1;
  57955. do {
  57956. precision = Math.max(
  57957. numberUtil.getPrecision(data.get(
  57958. valueAxisDim, dataIndex
  57959. )),
  57960. precision
  57961. );
  57962. data = data.stackedOn;
  57963. } while (data);
  57964. return precision;
  57965. }
  57966. function markerTypeCalculatorWithExtent(
  57967. mlType, data, otherDataDim, targetDataDim, otherCoordIndex, targetCoordIndex
  57968. ) {
  57969. var coordArr = [];
  57970. var value = numCalculate(data, targetDataDim, mlType);
  57971. var dataIndex = data.indicesOfNearest(targetDataDim, value, true)[0];
  57972. coordArr[otherCoordIndex] = data.get(otherDataDim, dataIndex, true);
  57973. coordArr[targetCoordIndex] = data.get(targetDataDim, dataIndex, true);
  57974. var precision = getPrecision(data, targetDataDim, dataIndex);
  57975. if (precision >= 0) {
  57976. coordArr[targetCoordIndex] = +coordArr[targetCoordIndex].toFixed(precision);
  57977. }
  57978. return coordArr;
  57979. }
  57980. var curry = zrUtil.curry;
  57981. // TODO Specified percent
  57982. var markerTypeCalculator = {
  57983. /**
  57984. * @method
  57985. * @param {module:echarts/data/List} data
  57986. * @param {string} baseAxisDim
  57987. * @param {string} valueAxisDim
  57988. */
  57989. min: curry(markerTypeCalculatorWithExtent, 'min'),
  57990. /**
  57991. * @method
  57992. * @param {module:echarts/data/List} data
  57993. * @param {string} baseAxisDim
  57994. * @param {string} valueAxisDim
  57995. */
  57996. max: curry(markerTypeCalculatorWithExtent, 'max'),
  57997. /**
  57998. * @method
  57999. * @param {module:echarts/data/List} data
  58000. * @param {string} baseAxisDim
  58001. * @param {string} valueAxisDim
  58002. */
  58003. average: curry(markerTypeCalculatorWithExtent, 'average')
  58004. };
  58005. /**
  58006. * Transform markPoint data item to format used in List by do the following
  58007. * 1. Calculate statistic like `max`, `min`, `average`
  58008. * 2. Convert `item.xAxis`, `item.yAxis` to `item.coord` array
  58009. * @param {module:echarts/model/Series} seriesModel
  58010. * @param {module:echarts/coord/*} [coordSys]
  58011. * @param {Object} item
  58012. * @return {Object}
  58013. */
  58014. var dataTransform = function (seriesModel, item) {
  58015. var data = seriesModel.getData();
  58016. var coordSys = seriesModel.coordinateSystem;
  58017. // 1. If not specify the position with pixel directly
  58018. // 2. If `coord` is not a data array. Which uses `xAxis`,
  58019. // `yAxis` to specify the coord on each dimension
  58020. // parseFloat first because item.x and item.y can be percent string like '20%'
  58021. if (item && !hasXAndY(item) && !zrUtil.isArray(item.coord) && coordSys) {
  58022. var dims = coordSys.dimensions;
  58023. var axisInfo = getAxisInfo(item, data, coordSys, seriesModel);
  58024. // Clone the option
  58025. // Transform the properties xAxis, yAxis, radiusAxis, angleAxis, geoCoord to value
  58026. item = zrUtil.clone(item);
  58027. if (item.type
  58028. && markerTypeCalculator[item.type]
  58029. && axisInfo.baseAxis && axisInfo.valueAxis
  58030. ) {
  58031. var otherCoordIndex = indexOf(dims, axisInfo.baseAxis.dim);
  58032. var targetCoordIndex = indexOf(dims, axisInfo.valueAxis.dim);
  58033. item.coord = markerTypeCalculator[item.type](
  58034. data, axisInfo.baseDataDim, axisInfo.valueDataDim,
  58035. otherCoordIndex, targetCoordIndex
  58036. );
  58037. // Force to use the value of calculated value.
  58038. item.value = item.coord[targetCoordIndex];
  58039. }
  58040. else {
  58041. // FIXME Only has one of xAxis and yAxis.
  58042. var coord = [
  58043. item.xAxis != null ? item.xAxis : item.radiusAxis,
  58044. item.yAxis != null ? item.yAxis : item.angleAxis
  58045. ];
  58046. // Each coord support max, min, average
  58047. for (var i = 0; i < 2; i++) {
  58048. if (markerTypeCalculator[coord[i]]) {
  58049. var dataDim = seriesModel.coordDimToDataDim(dims[i])[0];
  58050. coord[i] = numCalculate(data, dataDim, coord[i]);
  58051. }
  58052. }
  58053. item.coord = coord;
  58054. }
  58055. }
  58056. return item;
  58057. };
  58058. var getAxisInfo = function (item, data, coordSys, seriesModel) {
  58059. var ret = {};
  58060. if (item.valueIndex != null || item.valueDim != null) {
  58061. ret.valueDataDim = item.valueIndex != null
  58062. ? data.getDimension(item.valueIndex) : item.valueDim;
  58063. ret.valueAxis = coordSys.getAxis(seriesModel.dataDimToCoordDim(ret.valueDataDim));
  58064. ret.baseAxis = coordSys.getOtherAxis(ret.valueAxis);
  58065. ret.baseDataDim = seriesModel.coordDimToDataDim(ret.baseAxis.dim)[0];
  58066. }
  58067. else {
  58068. ret.baseAxis = seriesModel.getBaseAxis();
  58069. ret.valueAxis = coordSys.getOtherAxis(ret.baseAxis);
  58070. ret.baseDataDim = seriesModel.coordDimToDataDim(ret.baseAxis.dim)[0];
  58071. ret.valueDataDim = seriesModel.coordDimToDataDim(ret.valueAxis.dim)[0];
  58072. }
  58073. return ret;
  58074. };
  58075. /**
  58076. * Filter data which is out of coordinateSystem range
  58077. * [dataFilter description]
  58078. * @param {module:echarts/coord/*} [coordSys]
  58079. * @param {Object} item
  58080. * @return {boolean}
  58081. */
  58082. var dataFilter = function (coordSys, item) {
  58083. // Alwalys return true if there is no coordSys
  58084. return (coordSys && coordSys.containData && item.coord && !hasXOrY(item))
  58085. ? coordSys.containData(item.coord) : true;
  58086. };
  58087. var dimValueGetter = function (item, dimName, dataIndex, dimIndex) {
  58088. // x, y, radius, angle
  58089. if (dimIndex < 2) {
  58090. return item.coord && item.coord[dimIndex];
  58091. }
  58092. return item.value;
  58093. };
  58094. var numCalculate = function (data, valueDataDim, type) {
  58095. if (type === 'average') {
  58096. var sum = 0;
  58097. var count = 0;
  58098. data.each(valueDataDim, function (val, idx) {
  58099. if (!isNaN(val)) {
  58100. sum += val;
  58101. count++;
  58102. }
  58103. }, true);
  58104. return sum / count;
  58105. }
  58106. else {
  58107. return data.getDataExtent(valueDataDim, true)[type === 'max' ? 1 : 0];
  58108. }
  58109. };
  58110. module.exports = {
  58111. dataTransform: dataTransform,
  58112. dataFilter: dataFilter,
  58113. dimValueGetter: dimValueGetter,
  58114. getAxisInfo: getAxisInfo,
  58115. numCalculate: numCalculate
  58116. };
  58117. /***/ },
  58118. /* 395 */
  58119. /***/ function(module, exports, __webpack_require__) {
  58120. var zrUtil = __webpack_require__(4);
  58121. module.exports = __webpack_require__(1).extendComponentView({
  58122. type: 'marker',
  58123. init: function () {
  58124. /**
  58125. * Markline grouped by series
  58126. * @private
  58127. * @type {module:zrender/core/util.HashMap}
  58128. */
  58129. this.markerGroupMap = zrUtil.createHashMap();
  58130. },
  58131. render: function (markerModel, ecModel, api) {
  58132. var markerGroupMap = this.markerGroupMap;
  58133. markerGroupMap.each(function (item) {
  58134. item.__keep = false;
  58135. });
  58136. var markerModelKey = this.type + 'Model';
  58137. ecModel.eachSeries(function (seriesModel) {
  58138. var markerModel = seriesModel[markerModelKey];
  58139. markerModel && this.renderSeries(seriesModel, markerModel, ecModel, api);
  58140. }, this);
  58141. markerGroupMap.each(function (item) {
  58142. !item.__keep && this.group.remove(item.group);
  58143. }, this);
  58144. },
  58145. renderSeries: function () {}
  58146. });
  58147. /***/ },
  58148. /* 396 */
  58149. /***/ function(module, exports, __webpack_require__) {
  58150. __webpack_require__(397);
  58151. __webpack_require__(398);
  58152. __webpack_require__(1).registerPreprocessor(function (opt) {
  58153. // Make sure markLine component is enabled
  58154. opt.markLine = opt.markLine || {};
  58155. });
  58156. /***/ },
  58157. /* 397 */
  58158. /***/ function(module, exports, __webpack_require__) {
  58159. module.exports = __webpack_require__(392).extend({
  58160. type: 'markLine',
  58161. defaultOption: {
  58162. zlevel: 0,
  58163. z: 5,
  58164. symbol: ['circle', 'arrow'],
  58165. symbolSize: [8, 16],
  58166. //symbolRotate: 0,
  58167. precision: 2,
  58168. tooltip: {
  58169. trigger: 'item'
  58170. },
  58171. label: {
  58172. normal: {
  58173. show: true,
  58174. position: 'end'
  58175. },
  58176. emphasis: {
  58177. show: true
  58178. }
  58179. },
  58180. lineStyle: {
  58181. normal: {
  58182. type: 'dashed'
  58183. },
  58184. emphasis: {
  58185. width: 3
  58186. }
  58187. },
  58188. animationEasing: 'linear'
  58189. }
  58190. });
  58191. /***/ },
  58192. /* 398 */
  58193. /***/ function(module, exports, __webpack_require__) {
  58194. var zrUtil = __webpack_require__(4);
  58195. var List = __webpack_require__(98);
  58196. var numberUtil = __webpack_require__(7);
  58197. var markerHelper = __webpack_require__(394);
  58198. var LineDraw = __webpack_require__(209);
  58199. var markLineTransform = function (seriesModel, coordSys, mlModel, item) {
  58200. var data = seriesModel.getData();
  58201. // Special type markLine like 'min', 'max', 'average'
  58202. var mlType = item.type;
  58203. if (!zrUtil.isArray(item)
  58204. && (
  58205. mlType === 'min' || mlType === 'max' || mlType === 'average'
  58206. // In case
  58207. // data: [{
  58208. // yAxis: 10
  58209. // }]
  58210. || (item.xAxis != null || item.yAxis != null)
  58211. )
  58212. ) {
  58213. var valueAxis;
  58214. var valueDataDim;
  58215. var value;
  58216. if (item.yAxis != null || item.xAxis != null) {
  58217. valueDataDim = item.yAxis != null ? 'y' : 'x';
  58218. valueAxis = coordSys.getAxis(valueDataDim);
  58219. value = zrUtil.retrieve(item.yAxis, item.xAxis);
  58220. }
  58221. else {
  58222. var axisInfo = markerHelper.getAxisInfo(item, data, coordSys, seriesModel);
  58223. valueDataDim = axisInfo.valueDataDim;
  58224. valueAxis = axisInfo.valueAxis;
  58225. value = markerHelper.numCalculate(data, valueDataDim, mlType);
  58226. }
  58227. var valueIndex = valueDataDim === 'x' ? 0 : 1;
  58228. var baseIndex = 1 - valueIndex;
  58229. var mlFrom = zrUtil.clone(item);
  58230. var mlTo = {};
  58231. mlFrom.type = null;
  58232. mlFrom.coord = [];
  58233. mlTo.coord = [];
  58234. mlFrom.coord[baseIndex] = -Infinity;
  58235. mlTo.coord[baseIndex] = Infinity;
  58236. var precision = mlModel.get('precision');
  58237. if (precision >= 0 && typeof value === 'number') {
  58238. value = +value.toFixed(precision);
  58239. }
  58240. mlFrom.coord[valueIndex] = mlTo.coord[valueIndex] = value;
  58241. item = [mlFrom, mlTo, { // Extra option for tooltip and label
  58242. type: mlType,
  58243. valueIndex: item.valueIndex,
  58244. // Force to use the value of calculated value.
  58245. value: value
  58246. }];
  58247. }
  58248. item = [
  58249. markerHelper.dataTransform(seriesModel, item[0]),
  58250. markerHelper.dataTransform(seriesModel, item[1]),
  58251. zrUtil.extend({}, item[2])
  58252. ];
  58253. // Avoid line data type is extended by from(to) data type
  58254. item[2].type = item[2].type || '';
  58255. // Merge from option and to option into line option
  58256. zrUtil.merge(item[2], item[0]);
  58257. zrUtil.merge(item[2], item[1]);
  58258. return item;
  58259. };
  58260. function isInifinity(val) {
  58261. return !isNaN(val) && !isFinite(val);
  58262. }
  58263. // If a markLine has one dim
  58264. function ifMarkLineHasOnlyDim(dimIndex, fromCoord, toCoord, coordSys) {
  58265. var otherDimIndex = 1 - dimIndex;
  58266. var dimName = coordSys.dimensions[dimIndex];
  58267. return isInifinity(fromCoord[otherDimIndex]) && isInifinity(toCoord[otherDimIndex])
  58268. && fromCoord[dimIndex] === toCoord[dimIndex] && coordSys.getAxis(dimName).containData(fromCoord[dimIndex]);
  58269. }
  58270. function markLineFilter(coordSys, item) {
  58271. if (coordSys.type === 'cartesian2d') {
  58272. var fromCoord = item[0].coord;
  58273. var toCoord = item[1].coord;
  58274. // In case
  58275. // {
  58276. // markLine: {
  58277. // data: [{ yAxis: 2 }]
  58278. // }
  58279. // }
  58280. if (
  58281. fromCoord && toCoord &&
  58282. (ifMarkLineHasOnlyDim(1, fromCoord, toCoord, coordSys)
  58283. || ifMarkLineHasOnlyDim(0, fromCoord, toCoord, coordSys))
  58284. ) {
  58285. return true;
  58286. }
  58287. }
  58288. return markerHelper.dataFilter(coordSys, item[0])
  58289. && markerHelper.dataFilter(coordSys, item[1]);
  58290. }
  58291. function updateSingleMarkerEndLayout(
  58292. data, idx, isFrom, seriesModel, api
  58293. ) {
  58294. var coordSys = seriesModel.coordinateSystem;
  58295. var itemModel = data.getItemModel(idx);
  58296. var point;
  58297. var xPx = numberUtil.parsePercent(itemModel.get('x'), api.getWidth());
  58298. var yPx = numberUtil.parsePercent(itemModel.get('y'), api.getHeight());
  58299. if (!isNaN(xPx) && !isNaN(yPx)) {
  58300. point = [xPx, yPx];
  58301. }
  58302. else {
  58303. // Chart like bar may have there own marker positioning logic
  58304. if (seriesModel.getMarkerPosition) {
  58305. // Use the getMarkerPoisition
  58306. point = seriesModel.getMarkerPosition(
  58307. data.getValues(data.dimensions, idx)
  58308. );
  58309. }
  58310. else {
  58311. var dims = coordSys.dimensions;
  58312. var x = data.get(dims[0], idx);
  58313. var y = data.get(dims[1], idx);
  58314. point = coordSys.dataToPoint([x, y]);
  58315. }
  58316. // Expand line to the edge of grid if value on one axis is Inifnity
  58317. // In case
  58318. // markLine: {
  58319. // data: [{
  58320. // yAxis: 2
  58321. // // or
  58322. // type: 'average'
  58323. // }]
  58324. // }
  58325. if (coordSys.type === 'cartesian2d') {
  58326. var xAxis = coordSys.getAxis('x');
  58327. var yAxis = coordSys.getAxis('y');
  58328. var dims = coordSys.dimensions;
  58329. if (isInifinity(data.get(dims[0], idx))) {
  58330. point[0] = xAxis.toGlobalCoord(xAxis.getExtent()[isFrom ? 0 : 1]);
  58331. }
  58332. else if (isInifinity(data.get(dims[1], idx))) {
  58333. point[1] = yAxis.toGlobalCoord(yAxis.getExtent()[isFrom ? 0 : 1]);
  58334. }
  58335. }
  58336. // Use x, y if has any
  58337. if (!isNaN(xPx)) {
  58338. point[0] = xPx;
  58339. }
  58340. if (!isNaN(yPx)) {
  58341. point[1] = yPx;
  58342. }
  58343. }
  58344. data.setItemLayout(idx, point);
  58345. }
  58346. __webpack_require__(395).extend({
  58347. type: 'markLine',
  58348. updateLayout: function (markLineModel, ecModel, api) {
  58349. ecModel.eachSeries(function (seriesModel) {
  58350. var mlModel = seriesModel.markLineModel;
  58351. if (mlModel) {
  58352. var mlData = mlModel.getData();
  58353. var fromData = mlModel.__from;
  58354. var toData = mlModel.__to;
  58355. // Update visual and layout of from symbol and to symbol
  58356. fromData.each(function (idx) {
  58357. updateSingleMarkerEndLayout(fromData, idx, true, seriesModel, api);
  58358. updateSingleMarkerEndLayout(toData, idx, false, seriesModel, api);
  58359. });
  58360. // Update layout of line
  58361. mlData.each(function (idx) {
  58362. mlData.setItemLayout(idx, [
  58363. fromData.getItemLayout(idx),
  58364. toData.getItemLayout(idx)
  58365. ]);
  58366. });
  58367. this.markerGroupMap.get(seriesModel.name).updateLayout();
  58368. }
  58369. }, this);
  58370. },
  58371. renderSeries: function (seriesModel, mlModel, ecModel, api) {
  58372. var coordSys = seriesModel.coordinateSystem;
  58373. var seriesName = seriesModel.name;
  58374. var seriesData = seriesModel.getData();
  58375. var lineDrawMap = this.markerGroupMap;
  58376. var lineDraw = lineDrawMap.get(seriesName)
  58377. || lineDrawMap.set(seriesName, new LineDraw());
  58378. this.group.add(lineDraw.group);
  58379. var mlData = createList(coordSys, seriesModel, mlModel);
  58380. var fromData = mlData.from;
  58381. var toData = mlData.to;
  58382. var lineData = mlData.line;
  58383. mlModel.__from = fromData;
  58384. mlModel.__to = toData;
  58385. // Line data for tooltip and formatter
  58386. mlModel.setData(lineData);
  58387. var symbolType = mlModel.get('symbol');
  58388. var symbolSize = mlModel.get('symbolSize');
  58389. if (!zrUtil.isArray(symbolType)) {
  58390. symbolType = [symbolType, symbolType];
  58391. }
  58392. if (typeof symbolSize === 'number') {
  58393. symbolSize = [symbolSize, symbolSize];
  58394. }
  58395. // Update visual and layout of from symbol and to symbol
  58396. mlData.from.each(function (idx) {
  58397. updateDataVisualAndLayout(fromData, idx, true);
  58398. updateDataVisualAndLayout(toData, idx, false);
  58399. });
  58400. // Update visual and layout of line
  58401. lineData.each(function (idx) {
  58402. var lineColor = lineData.getItemModel(idx).get('lineStyle.normal.color');
  58403. lineData.setItemVisual(idx, {
  58404. color: lineColor || fromData.getItemVisual(idx, 'color')
  58405. });
  58406. lineData.setItemLayout(idx, [
  58407. fromData.getItemLayout(idx),
  58408. toData.getItemLayout(idx)
  58409. ]);
  58410. lineData.setItemVisual(idx, {
  58411. 'fromSymbolSize': fromData.getItemVisual(idx, 'symbolSize'),
  58412. 'fromSymbol': fromData.getItemVisual(idx, 'symbol'),
  58413. 'toSymbolSize': toData.getItemVisual(idx, 'symbolSize'),
  58414. 'toSymbol': toData.getItemVisual(idx, 'symbol')
  58415. });
  58416. });
  58417. lineDraw.updateData(lineData);
  58418. // Set host model for tooltip
  58419. // FIXME
  58420. mlData.line.eachItemGraphicEl(function (el, idx) {
  58421. el.traverse(function (child) {
  58422. child.dataModel = mlModel;
  58423. });
  58424. });
  58425. function updateDataVisualAndLayout(data, idx, isFrom) {
  58426. var itemModel = data.getItemModel(idx);
  58427. updateSingleMarkerEndLayout(
  58428. data, idx, isFrom, seriesModel, api
  58429. );
  58430. data.setItemVisual(idx, {
  58431. symbolSize: itemModel.get('symbolSize') || symbolSize[isFrom ? 0 : 1],
  58432. symbol: itemModel.get('symbol', true) || symbolType[isFrom ? 0 : 1],
  58433. color: itemModel.get('itemStyle.normal.color') || seriesData.getVisual('color')
  58434. });
  58435. }
  58436. lineDraw.__keep = true;
  58437. lineDraw.group.silent = mlModel.get('silent') || seriesModel.get('silent');
  58438. }
  58439. });
  58440. /**
  58441. * @inner
  58442. * @param {module:echarts/coord/*} coordSys
  58443. * @param {module:echarts/model/Series} seriesModel
  58444. * @param {module:echarts/model/Model} mpModel
  58445. */
  58446. function createList(coordSys, seriesModel, mlModel) {
  58447. var coordDimsInfos;
  58448. if (coordSys) {
  58449. coordDimsInfos = zrUtil.map(coordSys && coordSys.dimensions, function (coordDim) {
  58450. var info = seriesModel.getData().getDimensionInfo(
  58451. seriesModel.coordDimToDataDim(coordDim)[0]
  58452. ) || {}; // In map series data don't have lng and lat dimension. Fallback to same with coordSys
  58453. info.name = coordDim;
  58454. return info;
  58455. });
  58456. }
  58457. else {
  58458. coordDimsInfos =[{
  58459. name: 'value',
  58460. type: 'float'
  58461. }];
  58462. }
  58463. var fromData = new List(coordDimsInfos, mlModel);
  58464. var toData = new List(coordDimsInfos, mlModel);
  58465. // No dimensions
  58466. var lineData = new List([], mlModel);
  58467. var optData = zrUtil.map(mlModel.get('data'), zrUtil.curry(
  58468. markLineTransform, seriesModel, coordSys, mlModel
  58469. ));
  58470. if (coordSys) {
  58471. optData = zrUtil.filter(
  58472. optData, zrUtil.curry(markLineFilter, coordSys)
  58473. );
  58474. }
  58475. var dimValueGetter = coordSys ? markerHelper.dimValueGetter : function (item) {
  58476. return item.value;
  58477. };
  58478. fromData.initData(
  58479. zrUtil.map(optData, function (item) { return item[0]; }),
  58480. null, dimValueGetter
  58481. );
  58482. toData.initData(
  58483. zrUtil.map(optData, function (item) { return item[1]; }),
  58484. null, dimValueGetter
  58485. );
  58486. lineData.initData(
  58487. zrUtil.map(optData, function (item) { return item[2]; })
  58488. );
  58489. lineData.hasItemOption = true;
  58490. return {
  58491. from: fromData,
  58492. to: toData,
  58493. line: lineData
  58494. };
  58495. }
  58496. /***/ },
  58497. /* 399 */
  58498. /***/ function(module, exports, __webpack_require__) {
  58499. __webpack_require__(400);
  58500. __webpack_require__(401);
  58501. __webpack_require__(1).registerPreprocessor(function (opt) {
  58502. // Make sure markArea component is enabled
  58503. opt.markArea = opt.markArea || {};
  58504. });
  58505. /***/ },
  58506. /* 400 */
  58507. /***/ function(module, exports, __webpack_require__) {
  58508. module.exports = __webpack_require__(392).extend({
  58509. type: 'markArea',
  58510. defaultOption: {
  58511. zlevel: 0,
  58512. // PENDING
  58513. z: 1,
  58514. tooltip: {
  58515. trigger: 'item'
  58516. },
  58517. // markArea should fixed on the coordinate system
  58518. animation: false,
  58519. label: {
  58520. normal: {
  58521. show: true,
  58522. position: 'top'
  58523. },
  58524. emphasis: {
  58525. show: true,
  58526. position: 'top'
  58527. }
  58528. },
  58529. itemStyle: {
  58530. normal: {
  58531. // color and borderColor default to use color from series
  58532. // color: 'auto'
  58533. // borderColor: 'auto'
  58534. borderWidth: 0
  58535. }
  58536. }
  58537. }
  58538. });
  58539. /***/ },
  58540. /* 401 */
  58541. /***/ function(module, exports, __webpack_require__) {
  58542. // TODO Better on polar
  58543. var zrUtil = __webpack_require__(4);
  58544. var List = __webpack_require__(98);
  58545. var numberUtil = __webpack_require__(7);
  58546. var graphic = __webpack_require__(18);
  58547. var colorUtil = __webpack_require__(31);
  58548. var markerHelper = __webpack_require__(394);
  58549. var markAreaTransform = function (seriesModel, coordSys, maModel, item) {
  58550. var lt = markerHelper.dataTransform(seriesModel, item[0]);
  58551. var rb = markerHelper.dataTransform(seriesModel, item[1]);
  58552. var retrieve = zrUtil.retrieve;
  58553. // FIXME make sure lt is less than rb
  58554. var ltCoord = lt.coord;
  58555. var rbCoord = rb.coord;
  58556. ltCoord[0] = retrieve(ltCoord[0], -Infinity);
  58557. ltCoord[1] = retrieve(ltCoord[1], -Infinity);
  58558. rbCoord[0] = retrieve(rbCoord[0], Infinity);
  58559. rbCoord[1] = retrieve(rbCoord[1], Infinity);
  58560. // Merge option into one
  58561. var result = zrUtil.mergeAll([{}, lt, rb]);
  58562. result.coord = [
  58563. lt.coord, rb.coord
  58564. ];
  58565. result.x0 = lt.x;
  58566. result.y0 = lt.y;
  58567. result.x1 = rb.x;
  58568. result.y1 = rb.y;
  58569. return result;
  58570. };
  58571. function isInifinity(val) {
  58572. return !isNaN(val) && !isFinite(val);
  58573. }
  58574. // If a markArea has one dim
  58575. function ifMarkLineHasOnlyDim(dimIndex, fromCoord, toCoord, coordSys) {
  58576. var otherDimIndex = 1 - dimIndex;
  58577. return isInifinity(fromCoord[otherDimIndex]) && isInifinity(toCoord[otherDimIndex]);
  58578. }
  58579. function markAreaFilter(coordSys, item) {
  58580. var fromCoord = item.coord[0];
  58581. var toCoord = item.coord[1];
  58582. if (coordSys.type === 'cartesian2d') {
  58583. // In case
  58584. // {
  58585. // markArea: {
  58586. // data: [{ yAxis: 2 }]
  58587. // }
  58588. // }
  58589. if (
  58590. fromCoord && toCoord &&
  58591. (ifMarkLineHasOnlyDim(1, fromCoord, toCoord, coordSys)
  58592. || ifMarkLineHasOnlyDim(0, fromCoord, toCoord, coordSys))
  58593. ) {
  58594. return true;
  58595. }
  58596. }
  58597. return markerHelper.dataFilter(coordSys, {
  58598. coord: fromCoord,
  58599. x: item.x0,
  58600. y: item.y0
  58601. })
  58602. || markerHelper.dataFilter(coordSys, {
  58603. coord: toCoord,
  58604. x: item.x1,
  58605. y: item.y1
  58606. });
  58607. }
  58608. // dims can be ['x0', 'y0'], ['x1', 'y1'], ['x0', 'y1'], ['x1', 'y0']
  58609. function getSingleMarkerEndPoint(data, idx, dims, seriesModel, api) {
  58610. var coordSys = seriesModel.coordinateSystem;
  58611. var itemModel = data.getItemModel(idx);
  58612. var point;
  58613. var xPx = numberUtil.parsePercent(itemModel.get(dims[0]), api.getWidth());
  58614. var yPx = numberUtil.parsePercent(itemModel.get(dims[1]), api.getHeight());
  58615. if (!isNaN(xPx) && !isNaN(yPx)) {
  58616. point = [xPx, yPx];
  58617. }
  58618. else {
  58619. // Chart like bar may have there own marker positioning logic
  58620. if (seriesModel.getMarkerPosition) {
  58621. // Use the getMarkerPoisition
  58622. point = seriesModel.getMarkerPosition(
  58623. data.getValues(dims, idx)
  58624. );
  58625. }
  58626. else {
  58627. var x = data.get(dims[0], idx);
  58628. var y = data.get(dims[1], idx);
  58629. point = coordSys.dataToPoint([x, y], true);
  58630. }
  58631. if (coordSys.type === 'cartesian2d') {
  58632. var xAxis = coordSys.getAxis('x');
  58633. var yAxis = coordSys.getAxis('y');
  58634. var x = data.get(dims[0], idx);
  58635. var y = data.get(dims[1], idx);
  58636. if (isInifinity(x)) {
  58637. point[0] = xAxis.toGlobalCoord(xAxis.getExtent()[dims[0] === 'x0' ? 0 : 1]);
  58638. }
  58639. else if (isInifinity(y)) {
  58640. point[1] = yAxis.toGlobalCoord(yAxis.getExtent()[dims[1] === 'y0' ? 0 : 1]);
  58641. }
  58642. }
  58643. // Use x, y if has any
  58644. if (!isNaN(xPx)) {
  58645. point[0] = xPx;
  58646. }
  58647. if (!isNaN(yPx)) {
  58648. point[1] = yPx;
  58649. }
  58650. }
  58651. return point;
  58652. }
  58653. var dimPermutations = [['x0', 'y0'], ['x1', 'y0'], ['x1', 'y1'], ['x0', 'y1']];
  58654. __webpack_require__(395).extend({
  58655. type: 'markArea',
  58656. updateLayout: function (markAreaModel, ecModel, api) {
  58657. ecModel.eachSeries(function (seriesModel) {
  58658. var maModel = seriesModel.markAreaModel;
  58659. if (maModel) {
  58660. var areaData = maModel.getData();
  58661. areaData.each(function (idx) {
  58662. var points = zrUtil.map(dimPermutations, function (dim) {
  58663. return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api);
  58664. });
  58665. // Layout
  58666. areaData.setItemLayout(idx, points);
  58667. var el = areaData.getItemGraphicEl(idx);
  58668. el.setShape('points', points);
  58669. });
  58670. }
  58671. }, this);
  58672. },
  58673. renderSeries: function (seriesModel, maModel, ecModel, api) {
  58674. var coordSys = seriesModel.coordinateSystem;
  58675. var seriesName = seriesModel.name;
  58676. var seriesData = seriesModel.getData();
  58677. var areaGroupMap = this.markerGroupMap;
  58678. var polygonGroup = areaGroupMap.get(seriesName)
  58679. || areaGroupMap.set(seriesName, {group: new graphic.Group()});
  58680. this.group.add(polygonGroup.group);
  58681. polygonGroup.__keep = true;
  58682. var areaData = createList(coordSys, seriesModel, maModel);
  58683. // Line data for tooltip and formatter
  58684. maModel.setData(areaData);
  58685. // Update visual and layout of line
  58686. areaData.each(function (idx) {
  58687. // Layout
  58688. areaData.setItemLayout(idx, zrUtil.map(dimPermutations, function (dim) {
  58689. return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api);
  58690. }));
  58691. // Visual
  58692. areaData.setItemVisual(idx, {
  58693. color: seriesData.getVisual('color')
  58694. });
  58695. });
  58696. areaData.diff(polygonGroup.__data)
  58697. .add(function (idx) {
  58698. var polygon = new graphic.Polygon({
  58699. shape: {
  58700. points: areaData.getItemLayout(idx)
  58701. }
  58702. });
  58703. areaData.setItemGraphicEl(idx, polygon);
  58704. polygonGroup.group.add(polygon);
  58705. })
  58706. .update(function (newIdx, oldIdx) {
  58707. var polygon = polygonGroup.__data.getItemGraphicEl(oldIdx);
  58708. graphic.updateProps(polygon, {
  58709. shape: {
  58710. points: areaData.getItemLayout(newIdx)
  58711. }
  58712. }, maModel, newIdx);
  58713. polygonGroup.group.add(polygon);
  58714. areaData.setItemGraphicEl(newIdx, polygon);
  58715. })
  58716. .remove(function (idx) {
  58717. var polygon = polygonGroup.__data.getItemGraphicEl(idx);
  58718. polygonGroup.group.remove(polygon);
  58719. })
  58720. .execute();
  58721. areaData.eachItemGraphicEl(function (polygon, idx) {
  58722. var itemModel = areaData.getItemModel(idx);
  58723. var labelModel = itemModel.getModel('label.normal');
  58724. var labelHoverModel = itemModel.getModel('label.emphasis');
  58725. var color = areaData.getItemVisual(idx, 'color');
  58726. polygon.useStyle(
  58727. zrUtil.defaults(
  58728. itemModel.getModel('itemStyle.normal').getItemStyle(),
  58729. {
  58730. fill: colorUtil.modifyAlpha(color, 0.4),
  58731. stroke: color
  58732. }
  58733. )
  58734. );
  58735. polygon.hoverStyle = itemModel.getModel('itemStyle.normal').getItemStyle();
  58736. var defaultValue = areaData.getName(idx) || '';
  58737. var textColor = color || polygon.style.fill;
  58738. if (labelModel.getShallow('show')) {
  58739. graphic.setText(polygon.style, labelModel, textColor);
  58740. polygon.style.text = zrUtil.retrieve(
  58741. maModel.getFormattedLabel(idx, 'normal'),
  58742. defaultValue
  58743. );
  58744. }
  58745. else {
  58746. polygon.style.text = '';
  58747. }
  58748. if (labelHoverModel.getShallow('show')) {
  58749. graphic.setText(polygon.hoverStyle, labelHoverModel, textColor);
  58750. polygon.hoverStyle.text = zrUtil.retrieve(
  58751. maModel.getFormattedLabel(idx, 'emphasis'),
  58752. defaultValue
  58753. );
  58754. }
  58755. else {
  58756. polygon.hoverStyle.text = '';
  58757. }
  58758. graphic.setHoverStyle(polygon, {});
  58759. polygon.dataModel = maModel;
  58760. });
  58761. polygonGroup.__data = areaData;
  58762. polygonGroup.group.silent = maModel.get('silent') || seriesModel.get('silent');
  58763. }
  58764. });
  58765. /**
  58766. * @inner
  58767. * @param {module:echarts/coord/*} coordSys
  58768. * @param {module:echarts/model/Series} seriesModel
  58769. * @param {module:echarts/model/Model} mpModel
  58770. */
  58771. function createList(coordSys, seriesModel, maModel) {
  58772. var coordDimsInfos;
  58773. var areaData;
  58774. var dims = ['x0', 'y0', 'x1', 'y1'];
  58775. if (coordSys) {
  58776. coordDimsInfos = zrUtil.map(coordSys && coordSys.dimensions, function (coordDim) {
  58777. var info = seriesModel.getData().getDimensionInfo(
  58778. seriesModel.coordDimToDataDim(coordDim)[0]
  58779. ) || {}; // In map series data don't have lng and lat dimension. Fallback to same with coordSys
  58780. info.name = coordDim;
  58781. return info;
  58782. });
  58783. areaData = new List(zrUtil.map(dims, function (dim, idx) {
  58784. return {
  58785. name: dim,
  58786. type: coordDimsInfos[idx % 2].type
  58787. };
  58788. }), maModel);
  58789. }
  58790. else {
  58791. coordDimsInfos =[{
  58792. name: 'value',
  58793. type: 'float'
  58794. }];
  58795. areaData = new List(coordDimsInfos, maModel);
  58796. }
  58797. var optData = zrUtil.map(maModel.get('data'), zrUtil.curry(
  58798. markAreaTransform, seriesModel, coordSys, maModel
  58799. ));
  58800. if (coordSys) {
  58801. optData = zrUtil.filter(
  58802. optData, zrUtil.curry(markAreaFilter, coordSys)
  58803. );
  58804. }
  58805. var dimValueGetter = coordSys ? function (item, dimName, dataIndex, dimIndex) {
  58806. return item.coord[Math.floor(dimIndex / 2)][dimIndex % 2];
  58807. } : function (item) {
  58808. return item.value;
  58809. };
  58810. areaData.initData(optData, null, dimValueGetter);
  58811. areaData.hasItemOption = true;
  58812. return areaData;
  58813. }
  58814. /***/ },
  58815. /* 402 */
  58816. /***/ function(module, exports, __webpack_require__) {
  58817. /**
  58818. * DataZoom component entry
  58819. */
  58820. var echarts = __webpack_require__(1);
  58821. echarts.registerPreprocessor(__webpack_require__(403));
  58822. __webpack_require__(404);
  58823. __webpack_require__(405);
  58824. __webpack_require__(406);
  58825. __webpack_require__(408);
  58826. /***/ },
  58827. /* 403 */
  58828. /***/ function(module, exports, __webpack_require__) {
  58829. /**
  58830. * @file Timeline preprocessor
  58831. */
  58832. var zrUtil = __webpack_require__(4);
  58833. module.exports = function (option) {
  58834. var timelineOpt = option && option.timeline;
  58835. if (!zrUtil.isArray(timelineOpt)) {
  58836. timelineOpt = timelineOpt ? [timelineOpt] : [];
  58837. }
  58838. zrUtil.each(timelineOpt, function (opt) {
  58839. if (!opt) {
  58840. return;
  58841. }
  58842. compatibleEC2(opt);
  58843. });
  58844. };
  58845. function compatibleEC2(opt) {
  58846. var type = opt.type;
  58847. var ec2Types = {'number': 'value', 'time': 'time'};
  58848. // Compatible with ec2
  58849. if (ec2Types[type]) {
  58850. opt.axisType = ec2Types[type];
  58851. delete opt.type;
  58852. }
  58853. transferItem(opt);
  58854. if (has(opt, 'controlPosition')) {
  58855. var controlStyle = opt.controlStyle || (opt.controlStyle = {});
  58856. if (!has(controlStyle, 'position')) {
  58857. controlStyle.position = opt.controlPosition;
  58858. }
  58859. if (controlStyle.position === 'none' && !has(controlStyle, 'show')) {
  58860. controlStyle.show = false;
  58861. delete controlStyle.position;
  58862. }
  58863. delete opt.controlPosition;
  58864. }
  58865. zrUtil.each(opt.data || [], function (dataItem) {
  58866. if (zrUtil.isObject(dataItem) && !zrUtil.isArray(dataItem)) {
  58867. if (!has(dataItem, 'value') && has(dataItem, 'name')) {
  58868. // In ec2, using name as value.
  58869. dataItem.value = dataItem.name;
  58870. }
  58871. transferItem(dataItem);
  58872. }
  58873. });
  58874. }
  58875. function transferItem(opt) {
  58876. var itemStyle = opt.itemStyle || (opt.itemStyle = {});
  58877. var itemStyleEmphasis = itemStyle.emphasis || (itemStyle.emphasis = {});
  58878. // Transfer label out
  58879. var label = opt.label || (opt.label || {});
  58880. var labelNormal = label.normal || (label.normal = {});
  58881. var excludeLabelAttr = {normal: 1, emphasis: 1};
  58882. zrUtil.each(label, function (value, name) {
  58883. if (!excludeLabelAttr[name] && !has(labelNormal, name)) {
  58884. labelNormal[name] = value;
  58885. }
  58886. });
  58887. if (itemStyleEmphasis.label && !has(label, 'emphasis')) {
  58888. label.emphasis = itemStyleEmphasis.label;
  58889. delete itemStyleEmphasis.label;
  58890. }
  58891. }
  58892. function has(obj, attr) {
  58893. return obj.hasOwnProperty(attr);
  58894. }
  58895. /***/ },
  58896. /* 404 */
  58897. /***/ function(module, exports, __webpack_require__) {
  58898. __webpack_require__(69).registerSubTypeDefaulter('timeline', function () {
  58899. // Only slider now.
  58900. return 'slider';
  58901. });
  58902. /***/ },
  58903. /* 405 */
  58904. /***/ function(module, exports, __webpack_require__) {
  58905. /**
  58906. * @file Timeilne action
  58907. */
  58908. var echarts = __webpack_require__(1);
  58909. var zrUtil = __webpack_require__(4);
  58910. echarts.registerAction(
  58911. {type: 'timelineChange', event: 'timelineChanged', update: 'prepareAndUpdate'},
  58912. function (payload, ecModel) {
  58913. var timelineModel = ecModel.getComponent('timeline');
  58914. if (timelineModel && payload.currentIndex != null) {
  58915. timelineModel.setCurrentIndex(payload.currentIndex);
  58916. if (!timelineModel.get('loop', true) && timelineModel.isIndexMax()) {
  58917. timelineModel.setPlayState(false);
  58918. }
  58919. }
  58920. // Set normalized currentIndex to payload.
  58921. ecModel.resetOption('timeline');
  58922. return zrUtil.defaults({
  58923. currentIndex: timelineModel.option.currentIndex
  58924. }, payload);
  58925. }
  58926. );
  58927. echarts.registerAction(
  58928. {type: 'timelinePlayChange', event: 'timelinePlayChanged', update: 'update'},
  58929. function (payload, ecModel) {
  58930. var timelineModel = ecModel.getComponent('timeline');
  58931. if (timelineModel && payload.playState != null) {
  58932. timelineModel.setPlayState(payload.playState);
  58933. }
  58934. }
  58935. );
  58936. /***/ },
  58937. /* 406 */
  58938. /***/ function(module, exports, __webpack_require__) {
  58939. /**
  58940. * @file Silder timeline model
  58941. */
  58942. var TimelineModel = __webpack_require__(407);
  58943. var zrUtil = __webpack_require__(4);
  58944. var modelUtil = __webpack_require__(5);
  58945. var SliderTimelineModel = TimelineModel.extend({
  58946. type: 'timeline.slider',
  58947. /**
  58948. * @protected
  58949. */
  58950. defaultOption: {
  58951. backgroundColor: 'rgba(0,0,0,0)', // 时间轴背景颜色
  58952. borderColor: '#ccc', // 时间轴边框颜色
  58953. borderWidth: 0, // 时间轴边框线宽,单位px,默认为0(无边框)
  58954. orient: 'horizontal', // 'vertical'
  58955. inverse: false,
  58956. tooltip: { // boolean or Object
  58957. trigger: 'item' // data item may also have tootip attr.
  58958. },
  58959. symbol: 'emptyCircle',
  58960. symbolSize: 10,
  58961. lineStyle: {
  58962. show: true,
  58963. width: 2,
  58964. color: '#304654'
  58965. },
  58966. label: { // 文本标签
  58967. position: 'auto', // auto left right top bottom
  58968. // When using number, label position is not
  58969. // restricted by viewRect.
  58970. // positive: right/bottom, negative: left/top
  58971. normal: {
  58972. show: true,
  58973. interval: 'auto',
  58974. rotate: 0,
  58975. // formatter: null,
  58976. textStyle: { // 其余属性默认使用全局文本样式,详见TEXTSTYLE
  58977. color: '#304654'
  58978. }
  58979. },
  58980. emphasis: {
  58981. show: true,
  58982. textStyle: { // 其余属性默认使用全局文本样式,详见TEXTSTYLE
  58983. color: '#c23531'
  58984. }
  58985. }
  58986. },
  58987. itemStyle: {
  58988. normal: {
  58989. color: '#304654',
  58990. borderWidth: 1
  58991. },
  58992. emphasis: {
  58993. color: '#c23531'
  58994. }
  58995. },
  58996. checkpointStyle: {
  58997. symbol: 'circle',
  58998. symbolSize: 13,
  58999. color: '#c23531',
  59000. borderWidth: 5,
  59001. borderColor: 'rgba(194,53,49, 0.5)',
  59002. animation: true,
  59003. animationDuration: 300,
  59004. animationEasing: 'quinticInOut'
  59005. },
  59006. controlStyle: {
  59007. show: true,
  59008. showPlayBtn: true,
  59009. showPrevBtn: true,
  59010. showNextBtn: true,
  59011. itemSize: 22,
  59012. itemGap: 12,
  59013. position: 'left', // 'left' 'right' 'top' 'bottom'
  59014. playIcon: 'path://M31.6,53C17.5,53,6,41.5,6,27.4S17.5,1.8,31.6,1.8C45.7,1.8,57.2,13.3,57.2,27.4S45.7,53,31.6,53z M31.6,3.3 C18.4,3.3,7.5,14.1,7.5,27.4c0,13.3,10.8,24.1,24.1,24.1C44.9,51.5,55.7,40.7,55.7,27.4C55.7,14.1,44.9,3.3,31.6,3.3z M24.9,21.3 c0-2.2,1.6-3.1,3.5-2l10.5,6.1c1.899,1.1,1.899,2.9,0,4l-10.5,6.1c-1.9,1.1-3.5,0.2-3.5-2V21.3z', // jshint ignore:line
  59015. stopIcon: 'path://M30.9,53.2C16.8,53.2,5.3,41.7,5.3,27.6S16.8,2,30.9,2C45,2,56.4,13.5,56.4,27.6S45,53.2,30.9,53.2z M30.9,3.5C17.6,3.5,6.8,14.4,6.8,27.6c0,13.3,10.8,24.1,24.101,24.1C44.2,51.7,55,40.9,55,27.6C54.9,14.4,44.1,3.5,30.9,3.5z M36.9,35.8c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H36c0.5,0,0.9,0.4,0.9,1V35.8z M27.8,35.8 c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H27c0.5,0,0.9,0.4,0.9,1L27.8,35.8L27.8,35.8z', // jshint ignore:line
  59016. nextIcon: 'path://M18.6,50.8l22.5-22.5c0.2-0.2,0.3-0.4,0.3-0.7c0-0.3-0.1-0.5-0.3-0.7L18.7,4.4c-0.1-0.1-0.2-0.3-0.2-0.5 c0-0.4,0.3-0.8,0.8-0.8c0.2,0,0.5,0.1,0.6,0.3l23.5,23.5l0,0c0.2,0.2,0.3,0.4,0.3,0.7c0,0.3-0.1,0.5-0.3,0.7l-0.1,0.1L19.7,52 c-0.1,0.1-0.3,0.2-0.5,0.2c-0.4,0-0.8-0.3-0.8-0.8C18.4,51.2,18.5,51,18.6,50.8z', // jshint ignore:line
  59017. prevIcon: 'path://M43,52.8L20.4,30.3c-0.2-0.2-0.3-0.4-0.3-0.7c0-0.3,0.1-0.5,0.3-0.7L42.9,6.4c0.1-0.1,0.2-0.3,0.2-0.5 c0-0.4-0.3-0.8-0.8-0.8c-0.2,0-0.5,0.1-0.6,0.3L18.3,28.8l0,0c-0.2,0.2-0.3,0.4-0.3,0.7c0,0.3,0.1,0.5,0.3,0.7l0.1,0.1L41.9,54 c0.1,0.1,0.3,0.2,0.5,0.2c0.4,0,0.8-0.3,0.8-0.8C43.2,53.2,43.1,53,43,52.8z', // jshint ignore:line
  59018. normal: {
  59019. color: '#304654',
  59020. borderColor: '#304654',
  59021. borderWidth: 1
  59022. },
  59023. emphasis: {
  59024. color: '#c23531',
  59025. borderColor: '#c23531',
  59026. borderWidth: 2
  59027. }
  59028. },
  59029. data: []
  59030. }
  59031. });
  59032. zrUtil.mixin(SliderTimelineModel, modelUtil.dataFormatMixin);
  59033. module.exports = SliderTimelineModel;
  59034. /***/ },
  59035. /* 407 */
  59036. /***/ function(module, exports, __webpack_require__) {
  59037. /**
  59038. * @file Timeline model
  59039. */
  59040. var ComponentModel = __webpack_require__(69);
  59041. var List = __webpack_require__(98);
  59042. var zrUtil = __webpack_require__(4);
  59043. var modelUtil = __webpack_require__(5);
  59044. var TimelineModel = ComponentModel.extend({
  59045. type: 'timeline',
  59046. layoutMode: 'box',
  59047. /**
  59048. * @protected
  59049. */
  59050. defaultOption: {
  59051. zlevel: 0, // 一级层叠
  59052. z: 4, // 二级层叠
  59053. show: true,
  59054. axisType: 'time', // 模式是时间类型,支持 value, category
  59055. realtime: true,
  59056. left: '20%',
  59057. top: null,
  59058. right: '20%',
  59059. bottom: 0,
  59060. width: null,
  59061. height: 40,
  59062. padding: 5,
  59063. controlPosition: 'left', // 'left' 'right' 'top' 'bottom' 'none'
  59064. autoPlay: false,
  59065. rewind: false, // 反向播放
  59066. loop: true,
  59067. playInterval: 2000, // 播放时间间隔,单位ms
  59068. currentIndex: 0,
  59069. itemStyle: {
  59070. normal: {},
  59071. emphasis: {}
  59072. },
  59073. label: {
  59074. normal: {
  59075. textStyle: {
  59076. color: '#000'
  59077. }
  59078. },
  59079. emphasis: {}
  59080. },
  59081. data: []
  59082. },
  59083. /**
  59084. * @override
  59085. */
  59086. init: function (option, parentModel, ecModel) {
  59087. /**
  59088. * @private
  59089. * @type {module:echarts/data/List}
  59090. */
  59091. this._data;
  59092. /**
  59093. * @private
  59094. * @type {Array.<string>}
  59095. */
  59096. this._names;
  59097. this.mergeDefaultAndTheme(option, ecModel);
  59098. this._initData();
  59099. },
  59100. /**
  59101. * @override
  59102. */
  59103. mergeOption: function (option) {
  59104. TimelineModel.superApply(this, 'mergeOption', arguments);
  59105. this._initData();
  59106. },
  59107. /**
  59108. * @param {number} [currentIndex]
  59109. */
  59110. setCurrentIndex: function (currentIndex) {
  59111. if (currentIndex == null) {
  59112. currentIndex = this.option.currentIndex;
  59113. }
  59114. var count = this._data.count();
  59115. if (this.option.loop) {
  59116. currentIndex = (currentIndex % count + count) % count;
  59117. }
  59118. else {
  59119. currentIndex >= count && (currentIndex = count - 1);
  59120. currentIndex < 0 && (currentIndex = 0);
  59121. }
  59122. this.option.currentIndex = currentIndex;
  59123. },
  59124. /**
  59125. * @return {number} currentIndex
  59126. */
  59127. getCurrentIndex: function () {
  59128. return this.option.currentIndex;
  59129. },
  59130. /**
  59131. * @return {boolean}
  59132. */
  59133. isIndexMax: function () {
  59134. return this.getCurrentIndex() >= this._data.count() - 1;
  59135. },
  59136. /**
  59137. * @param {boolean} state true: play, false: stop
  59138. */
  59139. setPlayState: function (state) {
  59140. this.option.autoPlay = !!state;
  59141. },
  59142. /**
  59143. * @return {boolean} true: play, false: stop
  59144. */
  59145. getPlayState: function () {
  59146. return !!this.option.autoPlay;
  59147. },
  59148. /**
  59149. * @private
  59150. */
  59151. _initData: function () {
  59152. var thisOption = this.option;
  59153. var dataArr = thisOption.data || [];
  59154. var axisType = thisOption.axisType;
  59155. var names = this._names = [];
  59156. if (axisType === 'category') {
  59157. var idxArr = [];
  59158. zrUtil.each(dataArr, function (item, index) {
  59159. var value = modelUtil.getDataItemValue(item);
  59160. var newItem;
  59161. if (zrUtil.isObject(item)) {
  59162. newItem = zrUtil.clone(item);
  59163. newItem.value = index;
  59164. }
  59165. else {
  59166. newItem = index;
  59167. }
  59168. idxArr.push(newItem);
  59169. if (!zrUtil.isString(value) && (value == null || isNaN(value))) {
  59170. value = '';
  59171. }
  59172. names.push(value + '');
  59173. });
  59174. dataArr = idxArr;
  59175. }
  59176. var dimType = ({category: 'ordinal', time: 'time'})[axisType] || 'number';
  59177. var data = this._data = new List([{name: 'value', type: dimType}], this);
  59178. data.initData(dataArr, names);
  59179. },
  59180. getData: function () {
  59181. return this._data;
  59182. },
  59183. /**
  59184. * @public
  59185. * @return {Array.<string>} categoreis
  59186. */
  59187. getCategories: function () {
  59188. if (this.get('axisType') === 'category') {
  59189. return this._names.slice();
  59190. }
  59191. }
  59192. });
  59193. module.exports = TimelineModel;
  59194. /***/ },
  59195. /* 408 */
  59196. /***/ function(module, exports, __webpack_require__) {
  59197. /**
  59198. * @file Silder timeline view
  59199. */
  59200. var zrUtil = __webpack_require__(4);
  59201. var graphic = __webpack_require__(18);
  59202. var layout = __webpack_require__(71);
  59203. var TimelineView = __webpack_require__(409);
  59204. var TimelineAxis = __webpack_require__(410);
  59205. var symbolUtil = __webpack_require__(111);
  59206. var axisHelper = __webpack_require__(101);
  59207. var BoundingRect = __webpack_require__(9);
  59208. var matrix = __webpack_require__(11);
  59209. var numberUtil = __webpack_require__(7);
  59210. var formatUtil = __webpack_require__(6);
  59211. var encodeHTML = formatUtil.encodeHTML;
  59212. var bind = zrUtil.bind;
  59213. var each = zrUtil.each;
  59214. var PI = Math.PI;
  59215. module.exports = TimelineView.extend({
  59216. type: 'timeline.slider',
  59217. init: function (ecModel, api) {
  59218. this.api = api;
  59219. /**
  59220. * @private
  59221. * @type {module:echarts/component/timeline/TimelineAxis}
  59222. */
  59223. this._axis;
  59224. /**
  59225. * @private
  59226. * @type {module:zrender/core/BoundingRect}
  59227. */
  59228. this._viewRect;
  59229. /**
  59230. * @type {number}
  59231. */
  59232. this._timer;
  59233. /**
  59234. * @type {module:zrender/Element}
  59235. */
  59236. this._currentPointer;
  59237. /**
  59238. * @type {module:zrender/container/Group}
  59239. */
  59240. this._mainGroup;
  59241. /**
  59242. * @type {module:zrender/container/Group}
  59243. */
  59244. this._labelGroup;
  59245. },
  59246. /**
  59247. * @override
  59248. */
  59249. render: function (timelineModel, ecModel, api, payload) {
  59250. this.model = timelineModel;
  59251. this.api = api;
  59252. this.ecModel = ecModel;
  59253. this.group.removeAll();
  59254. if (timelineModel.get('show', true)) {
  59255. var layoutInfo = this._layout(timelineModel, api);
  59256. var mainGroup = this._createGroup('mainGroup');
  59257. var labelGroup = this._createGroup('labelGroup');
  59258. /**
  59259. * @private
  59260. * @type {module:echarts/component/timeline/TimelineAxis}
  59261. */
  59262. var axis = this._axis = this._createAxis(layoutInfo, timelineModel);
  59263. timelineModel.formatTooltip = function (dataIndex) {
  59264. return encodeHTML(axis.scale.getLabel(dataIndex));
  59265. };
  59266. each(
  59267. ['AxisLine', 'AxisTick', 'Control', 'CurrentPointer'],
  59268. function (name) {
  59269. this['_render' + name](layoutInfo, mainGroup, axis, timelineModel);
  59270. },
  59271. this
  59272. );
  59273. this._renderAxisLabel(layoutInfo, labelGroup, axis, timelineModel);
  59274. this._position(layoutInfo, timelineModel);
  59275. }
  59276. this._doPlayStop();
  59277. },
  59278. /**
  59279. * @override
  59280. */
  59281. remove: function () {
  59282. this._clearTimer();
  59283. this.group.removeAll();
  59284. },
  59285. /**
  59286. * @override
  59287. */
  59288. dispose: function () {
  59289. this._clearTimer();
  59290. },
  59291. _layout: function (timelineModel, api) {
  59292. var labelPosOpt = timelineModel.get('label.normal.position');
  59293. var orient = timelineModel.get('orient');
  59294. var viewRect = getViewRect(timelineModel, api);
  59295. // Auto label offset.
  59296. if (labelPosOpt == null || labelPosOpt === 'auto') {
  59297. labelPosOpt = orient === 'horizontal'
  59298. ? ((viewRect.y + viewRect.height / 2) < api.getHeight() / 2 ? '-' : '+')
  59299. : ((viewRect.x + viewRect.width / 2) < api.getWidth() / 2 ? '+' : '-');
  59300. }
  59301. else if (isNaN(labelPosOpt)) {
  59302. labelPosOpt = ({
  59303. horizontal: {top: '-', bottom: '+'},
  59304. vertical: {left: '-', right: '+'}
  59305. })[orient][labelPosOpt];
  59306. }
  59307. // FIXME
  59308. // 暂没有实现用户传入
  59309. // var labelAlign = timelineModel.get('label.normal.textStyle.align');
  59310. // var labelBaseline = timelineModel.get('label.normal.textStyle.baseline');
  59311. var labelAlignMap = {
  59312. horizontal: 'center',
  59313. vertical: (labelPosOpt >= 0 || labelPosOpt === '+') ? 'left' : 'right'
  59314. };
  59315. var labelBaselineMap = {
  59316. horizontal: (labelPosOpt >= 0 || labelPosOpt === '+') ? 'top' : 'bottom',
  59317. vertical: 'middle'
  59318. };
  59319. var rotationMap = {
  59320. horizontal: 0,
  59321. vertical: PI / 2
  59322. };
  59323. // Position
  59324. var mainLength = orient === 'vertical' ? viewRect.height : viewRect.width;
  59325. var controlModel = timelineModel.getModel('controlStyle');
  59326. var showControl = controlModel.get('show');
  59327. var controlSize = showControl ? controlModel.get('itemSize') : 0;
  59328. var controlGap = showControl ? controlModel.get('itemGap') : 0;
  59329. var sizePlusGap = controlSize + controlGap;
  59330. // Special label rotate.
  59331. var labelRotation = timelineModel.get('label.normal.rotate') || 0;
  59332. labelRotation = labelRotation * PI / 180; // To radian.
  59333. var playPosition;
  59334. var prevBtnPosition;
  59335. var nextBtnPosition;
  59336. var axisExtent;
  59337. var controlPosition = controlModel.get('position', true);
  59338. var showControl = controlModel.get('show', true);
  59339. var showPlayBtn = showControl && controlModel.get('showPlayBtn', true);
  59340. var showPrevBtn = showControl && controlModel.get('showPrevBtn', true);
  59341. var showNextBtn = showControl && controlModel.get('showNextBtn', true);
  59342. var xLeft = 0;
  59343. var xRight = mainLength;
  59344. // position[0] means left, position[1] means middle.
  59345. if (controlPosition === 'left' || controlPosition === 'bottom') {
  59346. showPlayBtn && (playPosition = [0, 0], xLeft += sizePlusGap);
  59347. showPrevBtn && (prevBtnPosition = [xLeft, 0], xLeft += sizePlusGap);
  59348. showNextBtn && (nextBtnPosition = [xRight - controlSize, 0], xRight -= sizePlusGap);
  59349. }
  59350. else { // 'top' 'right'
  59351. showPlayBtn && (playPosition = [xRight - controlSize, 0], xRight -= sizePlusGap);
  59352. showPrevBtn && (prevBtnPosition = [0, 0], xLeft += sizePlusGap);
  59353. showNextBtn && (nextBtnPosition = [xRight - controlSize, 0], xRight -= sizePlusGap);
  59354. }
  59355. axisExtent = [xLeft, xRight];
  59356. if (timelineModel.get('inverse')) {
  59357. axisExtent.reverse();
  59358. }
  59359. return {
  59360. viewRect: viewRect,
  59361. mainLength: mainLength,
  59362. orient: orient,
  59363. rotation: rotationMap[orient],
  59364. labelRotation: labelRotation,
  59365. labelPosOpt: labelPosOpt,
  59366. labelAlign: labelAlignMap[orient],
  59367. labelBaseline: labelBaselineMap[orient],
  59368. // Based on mainGroup.
  59369. playPosition: playPosition,
  59370. prevBtnPosition: prevBtnPosition,
  59371. nextBtnPosition: nextBtnPosition,
  59372. axisExtent: axisExtent,
  59373. controlSize: controlSize,
  59374. controlGap: controlGap
  59375. };
  59376. },
  59377. _position: function (layoutInfo, timelineModel) {
  59378. // Position is be called finally, because bounding rect is needed for
  59379. // adapt content to fill viewRect (auto adapt offset).
  59380. // Timeline may be not all in the viewRect when 'offset' is specified
  59381. // as a number, because it is more appropriate that label aligns at
  59382. // 'offset' but not the other edge defined by viewRect.
  59383. var mainGroup = this._mainGroup;
  59384. var labelGroup = this._labelGroup;
  59385. var viewRect = layoutInfo.viewRect;
  59386. if (layoutInfo.orient === 'vertical') {
  59387. // transfrom to horizontal, inverse rotate by left-top point.
  59388. var m = matrix.create();
  59389. var rotateOriginX = viewRect.x;
  59390. var rotateOriginY = viewRect.y + viewRect.height;
  59391. matrix.translate(m, m, [-rotateOriginX, -rotateOriginY]);
  59392. matrix.rotate(m, m, -PI / 2);
  59393. matrix.translate(m, m, [rotateOriginX, rotateOriginY]);
  59394. viewRect = viewRect.clone();
  59395. viewRect.applyTransform(m);
  59396. }
  59397. var viewBound = getBound(viewRect);
  59398. var mainBound = getBound(mainGroup.getBoundingRect());
  59399. var labelBound = getBound(labelGroup.getBoundingRect());
  59400. var mainPosition = mainGroup.position;
  59401. var labelsPosition = labelGroup.position;
  59402. labelsPosition[0] = mainPosition[0] = viewBound[0][0];
  59403. var labelPosOpt = layoutInfo.labelPosOpt;
  59404. if (isNaN(labelPosOpt)) { // '+' or '-'
  59405. var mainBoundIdx = labelPosOpt === '+' ? 0 : 1;
  59406. toBound(mainPosition, mainBound, viewBound, 1, mainBoundIdx);
  59407. toBound(labelsPosition, labelBound, viewBound, 1, 1 - mainBoundIdx);
  59408. }
  59409. else {
  59410. var mainBoundIdx = labelPosOpt >= 0 ? 0 : 1;
  59411. toBound(mainPosition, mainBound, viewBound, 1, mainBoundIdx);
  59412. labelsPosition[1] = mainPosition[1] + labelPosOpt;
  59413. }
  59414. mainGroup.attr('position', mainPosition);
  59415. labelGroup.attr('position', labelsPosition);
  59416. mainGroup.rotation = labelGroup.rotation = layoutInfo.rotation;
  59417. setOrigin(mainGroup);
  59418. setOrigin(labelGroup);
  59419. function setOrigin(targetGroup) {
  59420. var pos = targetGroup.position;
  59421. targetGroup.origin = [
  59422. viewBound[0][0] - pos[0],
  59423. viewBound[1][0] - pos[1]
  59424. ];
  59425. }
  59426. function getBound(rect) {
  59427. // [[xmin, xmax], [ymin, ymax]]
  59428. return [
  59429. [rect.x, rect.x + rect.width],
  59430. [rect.y, rect.y + rect.height]
  59431. ];
  59432. }
  59433. function toBound(fromPos, from, to, dimIdx, boundIdx) {
  59434. fromPos[dimIdx] += to[dimIdx][boundIdx] - from[dimIdx][boundIdx];
  59435. }
  59436. },
  59437. _createAxis: function (layoutInfo, timelineModel) {
  59438. var data = timelineModel.getData();
  59439. var axisType = timelineModel.get('axisType');
  59440. var scale = axisHelper.createScaleByModel(timelineModel, axisType);
  59441. var dataExtent = data.getDataExtent('value');
  59442. scale.setExtent(dataExtent[0], dataExtent[1]);
  59443. this._customizeScale(scale, data);
  59444. scale.niceTicks();
  59445. var axis = new TimelineAxis('value', scale, layoutInfo.axisExtent, axisType);
  59446. axis.model = timelineModel;
  59447. return axis;
  59448. },
  59449. _customizeScale: function (scale, data) {
  59450. scale.getTicks = function () {
  59451. return data.mapArray(['value'], function (value) {
  59452. return value;
  59453. });
  59454. };
  59455. scale.getTicksLabels = function () {
  59456. return zrUtil.map(this.getTicks(), scale.getLabel, scale);
  59457. };
  59458. },
  59459. _createGroup: function (name) {
  59460. var newGroup = this['_' + name] = new graphic.Group();
  59461. this.group.add(newGroup);
  59462. return newGroup;
  59463. },
  59464. _renderAxisLine: function (layoutInfo, group, axis, timelineModel) {
  59465. var axisExtent = axis.getExtent();
  59466. if (!timelineModel.get('lineStyle.show')) {
  59467. return;
  59468. }
  59469. group.add(new graphic.Line({
  59470. shape: {
  59471. x1: axisExtent[0], y1: 0,
  59472. x2: axisExtent[1], y2: 0
  59473. },
  59474. style: zrUtil.extend(
  59475. {lineCap: 'round'},
  59476. timelineModel.getModel('lineStyle').getLineStyle()
  59477. ),
  59478. silent: true,
  59479. z2: 1
  59480. }));
  59481. },
  59482. /**
  59483. * @private
  59484. */
  59485. _renderAxisTick: function (layoutInfo, group, axis, timelineModel) {
  59486. var data = timelineModel.getData();
  59487. var ticks = axis.scale.getTicks();
  59488. each(ticks, function (value, dataIndex) {
  59489. var tickCoord = axis.dataToCoord(value);
  59490. var itemModel = data.getItemModel(dataIndex);
  59491. var itemStyleModel = itemModel.getModel('itemStyle.normal');
  59492. var hoverStyleModel = itemModel.getModel('itemStyle.emphasis');
  59493. var symbolOpt = {
  59494. position: [tickCoord, 0],
  59495. onclick: bind(this._changeTimeline, this, dataIndex)
  59496. };
  59497. var el = giveSymbol(itemModel, itemStyleModel, group, symbolOpt);
  59498. graphic.setHoverStyle(el, hoverStyleModel.getItemStyle());
  59499. if (itemModel.get('tooltip')) {
  59500. el.dataIndex = dataIndex;
  59501. el.dataModel = timelineModel;
  59502. }
  59503. else {
  59504. el.dataIndex = el.dataModel = null;
  59505. }
  59506. }, this);
  59507. },
  59508. /**
  59509. * @private
  59510. */
  59511. _renderAxisLabel: function (layoutInfo, group, axis, timelineModel) {
  59512. var labelModel = timelineModel.getModel('label.normal');
  59513. if (!labelModel.get('show')) {
  59514. return;
  59515. }
  59516. var data = timelineModel.getData();
  59517. var ticks = axis.scale.getTicks();
  59518. var labels = axisHelper.getFormattedLabels(
  59519. axis, labelModel.get('formatter')
  59520. );
  59521. var labelInterval = axis.getLabelInterval();
  59522. each(ticks, function (tick, dataIndex) {
  59523. if (axis.isLabelIgnored(dataIndex, labelInterval)) {
  59524. return;
  59525. }
  59526. var itemModel = data.getItemModel(dataIndex);
  59527. var itemTextStyleModel = itemModel.getModel('label.normal.textStyle');
  59528. var hoverTextStyleModel = itemModel.getModel('label.emphasis.textStyle');
  59529. var tickCoord = axis.dataToCoord(tick);
  59530. var textEl = new graphic.Text({
  59531. style: {
  59532. text: labels[dataIndex],
  59533. textAlign: layoutInfo.labelAlign,
  59534. textVerticalAlign: layoutInfo.labelBaseline,
  59535. textFont: itemTextStyleModel.getFont(),
  59536. fill: itemTextStyleModel.getTextColor()
  59537. },
  59538. position: [tickCoord, 0],
  59539. rotation: layoutInfo.labelRotation - layoutInfo.rotation,
  59540. onclick: bind(this._changeTimeline, this, dataIndex),
  59541. silent: false
  59542. });
  59543. group.add(textEl);
  59544. graphic.setHoverStyle(textEl, hoverTextStyleModel.getItemStyle());
  59545. }, this);
  59546. },
  59547. /**
  59548. * @private
  59549. */
  59550. _renderControl: function (layoutInfo, group, axis, timelineModel) {
  59551. var controlSize = layoutInfo.controlSize;
  59552. var rotation = layoutInfo.rotation;
  59553. var itemStyle = timelineModel.getModel('controlStyle.normal').getItemStyle();
  59554. var hoverStyle = timelineModel.getModel('controlStyle.emphasis').getItemStyle();
  59555. var rect = [0, -controlSize / 2, controlSize, controlSize];
  59556. var playState = timelineModel.getPlayState();
  59557. var inverse = timelineModel.get('inverse', true);
  59558. makeBtn(
  59559. layoutInfo.nextBtnPosition,
  59560. 'controlStyle.nextIcon',
  59561. bind(this._changeTimeline, this, inverse ? '-' : '+')
  59562. );
  59563. makeBtn(
  59564. layoutInfo.prevBtnPosition,
  59565. 'controlStyle.prevIcon',
  59566. bind(this._changeTimeline, this, inverse ? '+' : '-')
  59567. );
  59568. makeBtn(
  59569. layoutInfo.playPosition,
  59570. 'controlStyle.' + (playState ? 'stopIcon' : 'playIcon'),
  59571. bind(this._handlePlayClick, this, !playState),
  59572. true
  59573. );
  59574. function makeBtn(position, iconPath, onclick, willRotate) {
  59575. if (!position) {
  59576. return;
  59577. }
  59578. var opt = {
  59579. position: position,
  59580. origin: [controlSize / 2, 0],
  59581. rotation: willRotate ? -rotation : 0,
  59582. rectHover: true,
  59583. style: itemStyle,
  59584. onclick: onclick
  59585. };
  59586. var btn = makeIcon(timelineModel, iconPath, rect, opt);
  59587. group.add(btn);
  59588. graphic.setHoverStyle(btn, hoverStyle);
  59589. }
  59590. },
  59591. _renderCurrentPointer: function (layoutInfo, group, axis, timelineModel) {
  59592. var data = timelineModel.getData();
  59593. var currentIndex = timelineModel.getCurrentIndex();
  59594. var pointerModel = data.getItemModel(currentIndex).getModel('checkpointStyle');
  59595. var me = this;
  59596. var callback = {
  59597. onCreate: function (pointer) {
  59598. pointer.draggable = true;
  59599. pointer.drift = bind(me._handlePointerDrag, me);
  59600. pointer.ondragend = bind(me._handlePointerDragend, me);
  59601. pointerMoveTo(pointer, currentIndex, axis, timelineModel, true);
  59602. },
  59603. onUpdate: function (pointer) {
  59604. pointerMoveTo(pointer, currentIndex, axis, timelineModel);
  59605. }
  59606. };
  59607. // Reuse when exists, for animation and drag.
  59608. this._currentPointer = giveSymbol(
  59609. pointerModel, pointerModel, this._mainGroup, {}, this._currentPointer, callback
  59610. );
  59611. },
  59612. _handlePlayClick: function (nextState) {
  59613. this._clearTimer();
  59614. this.api.dispatchAction({
  59615. type: 'timelinePlayChange',
  59616. playState: nextState,
  59617. from: this.uid
  59618. });
  59619. },
  59620. _handlePointerDrag: function (dx, dy, e) {
  59621. this._clearTimer();
  59622. this._pointerChangeTimeline([e.offsetX, e.offsetY]);
  59623. },
  59624. _handlePointerDragend: function (e) {
  59625. this._pointerChangeTimeline([e.offsetX, e.offsetY], true);
  59626. },
  59627. _pointerChangeTimeline: function (mousePos, trigger) {
  59628. var toCoord = this._toAxisCoord(mousePos)[0];
  59629. var axis = this._axis;
  59630. var axisExtent = numberUtil.asc(axis.getExtent().slice());
  59631. toCoord > axisExtent[1] && (toCoord = axisExtent[1]);
  59632. toCoord < axisExtent[0] && (toCoord = axisExtent[0]);
  59633. this._currentPointer.position[0] = toCoord;
  59634. this._currentPointer.dirty();
  59635. var targetDataIndex = this._findNearestTick(toCoord);
  59636. var timelineModel = this.model;
  59637. if (trigger || (
  59638. targetDataIndex !== timelineModel.getCurrentIndex()
  59639. && timelineModel.get('realtime')
  59640. )) {
  59641. this._changeTimeline(targetDataIndex);
  59642. }
  59643. },
  59644. _doPlayStop: function () {
  59645. this._clearTimer();
  59646. if (this.model.getPlayState()) {
  59647. this._timer = setTimeout(
  59648. bind(handleFrame, this),
  59649. this.model.get('playInterval')
  59650. );
  59651. }
  59652. function handleFrame() {
  59653. // Do not cache
  59654. var timelineModel = this.model;
  59655. this._changeTimeline(
  59656. timelineModel.getCurrentIndex()
  59657. + (timelineModel.get('rewind', true) ? -1 : 1)
  59658. );
  59659. }
  59660. },
  59661. _toAxisCoord: function (vertex) {
  59662. var trans = this._mainGroup.getLocalTransform();
  59663. return graphic.applyTransform(vertex, trans, true);
  59664. },
  59665. _findNearestTick: function (axisCoord) {
  59666. var data = this.model.getData();
  59667. var dist = Infinity;
  59668. var targetDataIndex;
  59669. var axis = this._axis;
  59670. data.each(['value'], function (value, dataIndex) {
  59671. var coord = axis.dataToCoord(value);
  59672. var d = Math.abs(coord - axisCoord);
  59673. if (d < dist) {
  59674. dist = d;
  59675. targetDataIndex = dataIndex;
  59676. }
  59677. });
  59678. return targetDataIndex;
  59679. },
  59680. _clearTimer: function () {
  59681. if (this._timer) {
  59682. clearTimeout(this._timer);
  59683. this._timer = null;
  59684. }
  59685. },
  59686. _changeTimeline: function (nextIndex) {
  59687. var currentIndex = this.model.getCurrentIndex();
  59688. if (nextIndex === '+') {
  59689. nextIndex = currentIndex + 1;
  59690. }
  59691. else if (nextIndex === '-') {
  59692. nextIndex = currentIndex - 1;
  59693. }
  59694. this.api.dispatchAction({
  59695. type: 'timelineChange',
  59696. currentIndex: nextIndex,
  59697. from: this.uid
  59698. });
  59699. }
  59700. });
  59701. function getViewRect(model, api) {
  59702. return layout.getLayoutRect(
  59703. model.getBoxLayoutParams(),
  59704. {
  59705. width: api.getWidth(),
  59706. height: api.getHeight()
  59707. },
  59708. model.get('padding')
  59709. );
  59710. }
  59711. function makeIcon(timelineModel, objPath, rect, opts) {
  59712. var icon = graphic.makePath(
  59713. timelineModel.get(objPath).replace(/^path:\/\//, ''),
  59714. zrUtil.clone(opts || {}),
  59715. new BoundingRect(rect[0], rect[1], rect[2], rect[3]),
  59716. 'center'
  59717. );
  59718. return icon;
  59719. }
  59720. /**
  59721. * Create symbol or update symbol
  59722. * opt: basic position and event handlers
  59723. */
  59724. function giveSymbol(hostModel, itemStyleModel, group, opt, symbol, callback) {
  59725. var color = itemStyleModel.get('color');
  59726. if (!symbol) {
  59727. var symbolType = hostModel.get('symbol');
  59728. symbol = symbolUtil.createSymbol(symbolType, -1, -1, 2, 2, color);
  59729. symbol.setStyle('strokeNoScale', true);
  59730. group.add(symbol);
  59731. callback && callback.onCreate(symbol);
  59732. }
  59733. else {
  59734. symbol.setColor(color);
  59735. group.add(symbol); // Group may be new, also need to add.
  59736. callback && callback.onUpdate(symbol);
  59737. }
  59738. // Style
  59739. var itemStyle = itemStyleModel.getItemStyle(['color', 'symbol', 'symbolSize']);
  59740. symbol.setStyle(itemStyle);
  59741. // Transform and events.
  59742. opt = zrUtil.merge({
  59743. rectHover: true,
  59744. z2: 100
  59745. }, opt, true);
  59746. var symbolSize = hostModel.get('symbolSize');
  59747. symbolSize = symbolSize instanceof Array
  59748. ? symbolSize.slice()
  59749. : [+symbolSize, +symbolSize];
  59750. symbolSize[0] /= 2;
  59751. symbolSize[1] /= 2;
  59752. opt.scale = symbolSize;
  59753. var symbolOffset = hostModel.get('symbolOffset');
  59754. if (symbolOffset) {
  59755. var pos = opt.position = opt.position || [0, 0];
  59756. pos[0] += numberUtil.parsePercent(symbolOffset[0], symbolSize[0]);
  59757. pos[1] += numberUtil.parsePercent(symbolOffset[1], symbolSize[1]);
  59758. }
  59759. var symbolRotate = hostModel.get('symbolRotate');
  59760. opt.rotation = (symbolRotate || 0) * Math.PI / 180 || 0;
  59761. symbol.attr(opt);
  59762. // FIXME
  59763. // (1) When symbol.style.strokeNoScale is true and updateTransform is not performed,
  59764. // getBoundingRect will return wrong result.
  59765. // (This is supposed to be resolved in zrender, but it is a little difficult to
  59766. // leverage performance and auto updateTransform)
  59767. // (2) All of ancesters of symbol do not scale, so we can just updateTransform symbol.
  59768. symbol.updateTransform();
  59769. return symbol;
  59770. }
  59771. function pointerMoveTo(pointer, dataIndex, axis, timelineModel, noAnimation) {
  59772. if (pointer.dragging) {
  59773. return;
  59774. }
  59775. var pointerModel = timelineModel.getModel('checkpointStyle');
  59776. var toCoord = axis.dataToCoord(timelineModel.getData().get(['value'], dataIndex));
  59777. if (noAnimation || !pointerModel.get('animation', true)) {
  59778. pointer.attr({position: [toCoord, 0]});
  59779. }
  59780. else {
  59781. pointer.stopAnimation(true);
  59782. pointer.animateTo(
  59783. {position: [toCoord, 0]},
  59784. pointerModel.get('animationDuration', true),
  59785. pointerModel.get('animationEasing', true)
  59786. );
  59787. }
  59788. }
  59789. /***/ },
  59790. /* 409 */
  59791. /***/ function(module, exports, __webpack_require__) {
  59792. /**
  59793. * @file Timeline view
  59794. */
  59795. // var zrUtil = require('zrender/lib/core/util');
  59796. // var graphic = require('../../util/graphic');
  59797. var ComponentView = __webpack_require__(79);
  59798. module.exports = ComponentView.extend({
  59799. type: 'timeline'
  59800. });
  59801. /***/ },
  59802. /* 410 */
  59803. /***/ function(module, exports, __webpack_require__) {
  59804. var zrUtil = __webpack_require__(4);
  59805. var Axis = __webpack_require__(100);
  59806. var axisHelper = __webpack_require__(101);
  59807. /**
  59808. * Extend axis 2d
  59809. * @constructor module:echarts/coord/cartesian/Axis2D
  59810. * @extends {module:echarts/coord/cartesian/Axis}
  59811. * @param {string} dim
  59812. * @param {*} scale
  59813. * @param {Array.<number>} coordExtent
  59814. * @param {string} axisType
  59815. * @param {string} position
  59816. */
  59817. var TimelineAxis = function (dim, scale, coordExtent, axisType) {
  59818. Axis.call(this, dim, scale, coordExtent);
  59819. /**
  59820. * Axis type
  59821. * - 'category'
  59822. * - 'value'
  59823. * - 'time'
  59824. * - 'log'
  59825. * @type {string}
  59826. */
  59827. this.type = axisType || 'value';
  59828. /**
  59829. * @private
  59830. * @type {number}
  59831. */
  59832. this._autoLabelInterval;
  59833. /**
  59834. * Axis model
  59835. * @param {module:echarts/component/TimelineModel}
  59836. */
  59837. this.model = null;
  59838. };
  59839. TimelineAxis.prototype = {
  59840. constructor: TimelineAxis,
  59841. /**
  59842. * @public
  59843. * @return {number}
  59844. */
  59845. getLabelInterval: function () {
  59846. var timelineModel = this.model;
  59847. var labelModel = timelineModel.getModel('label.normal');
  59848. var labelInterval = labelModel.get('interval');
  59849. if (labelInterval != null && labelInterval != 'auto') {
  59850. return labelInterval;
  59851. }
  59852. var labelInterval = this._autoLabelInterval;
  59853. if (!labelInterval) {
  59854. labelInterval = this._autoLabelInterval = axisHelper.getAxisLabelInterval(
  59855. zrUtil.map(this.scale.getTicks(), this.dataToCoord, this),
  59856. axisHelper.getFormattedLabels(this, labelModel.get('formatter')),
  59857. labelModel.getModel('textStyle').getFont(),
  59858. timelineModel.get('orient') === 'horizontal'
  59859. );
  59860. }
  59861. return labelInterval;
  59862. },
  59863. /**
  59864. * If label is ignored.
  59865. * Automatically used when axis is category and label can not be all shown
  59866. * @public
  59867. * @param {number} idx
  59868. * @return {boolean}
  59869. */
  59870. isLabelIgnored: function (idx) {
  59871. if (this.type === 'category') {
  59872. var labelInterval = this.getLabelInterval();
  59873. return ((typeof labelInterval === 'function')
  59874. && !labelInterval(idx, this.scale.getLabel(idx)))
  59875. || idx % (labelInterval + 1);
  59876. }
  59877. }
  59878. };
  59879. zrUtil.inherits(TimelineAxis, Axis);
  59880. module.exports = TimelineAxis;
  59881. /***/ },
  59882. /* 411 */
  59883. /***/ function(module, exports, __webpack_require__) {
  59884. __webpack_require__(412);
  59885. __webpack_require__(413);
  59886. __webpack_require__(414);
  59887. __webpack_require__(415);
  59888. __webpack_require__(416);
  59889. __webpack_require__(417);
  59890. __webpack_require__(422);
  59891. /***/ },
  59892. /* 412 */
  59893. /***/ function(module, exports, __webpack_require__) {
  59894. var featureManager = __webpack_require__(356);
  59895. var zrUtil = __webpack_require__(4);
  59896. var ToolboxModel = __webpack_require__(1).extendComponentModel({
  59897. type: 'toolbox',
  59898. layoutMode: {
  59899. type: 'box',
  59900. ignoreSize: true
  59901. },
  59902. mergeDefaultAndTheme: function (option) {
  59903. ToolboxModel.superApply(this, 'mergeDefaultAndTheme', arguments);
  59904. zrUtil.each(this.option.feature, function (featureOpt, featureName) {
  59905. var Feature = featureManager.get(featureName);
  59906. Feature && zrUtil.merge(featureOpt, Feature.defaultOption);
  59907. });
  59908. },
  59909. defaultOption: {
  59910. show: true,
  59911. z: 6,
  59912. zlevel: 0,
  59913. orient: 'horizontal',
  59914. left: 'right',
  59915. top: 'top',
  59916. // right
  59917. // bottom
  59918. backgroundColor: 'transparent',
  59919. borderColor: '#ccc',
  59920. borderWidth: 0,
  59921. padding: 5,
  59922. itemSize: 15,
  59923. itemGap: 8,
  59924. showTitle: true,
  59925. iconStyle: {
  59926. normal: {
  59927. borderColor: '#666',
  59928. color: 'none'
  59929. },
  59930. emphasis: {
  59931. borderColor: '#3E98C5'
  59932. }
  59933. }
  59934. // textStyle: {},
  59935. // feature
  59936. }
  59937. });
  59938. module.exports = ToolboxModel;
  59939. /***/ },
  59940. /* 413 */
  59941. /***/ function(module, exports, __webpack_require__) {
  59942. /* WEBPACK VAR INJECTION */(function(process) {
  59943. var featureManager = __webpack_require__(356);
  59944. var zrUtil = __webpack_require__(4);
  59945. var graphic = __webpack_require__(18);
  59946. var Model = __webpack_require__(12);
  59947. var DataDiffer = __webpack_require__(99);
  59948. var listComponentHelper = __webpack_require__(324);
  59949. var textContain = __webpack_require__(8);
  59950. module.exports = __webpack_require__(1).extendComponentView({
  59951. type: 'toolbox',
  59952. render: function (toolboxModel, ecModel, api, payload) {
  59953. var group = this.group;
  59954. group.removeAll();
  59955. if (!toolboxModel.get('show')) {
  59956. return;
  59957. }
  59958. var itemSize = +toolboxModel.get('itemSize');
  59959. var featureOpts = toolboxModel.get('feature') || {};
  59960. var features = this._features || (this._features = {});
  59961. var featureNames = [];
  59962. zrUtil.each(featureOpts, function (opt, name) {
  59963. featureNames.push(name);
  59964. });
  59965. (new DataDiffer(this._featureNames || [], featureNames))
  59966. .add(process)
  59967. .update(process)
  59968. .remove(zrUtil.curry(process, null))
  59969. .execute();
  59970. // Keep for diff.
  59971. this._featureNames = featureNames;
  59972. function process(newIndex, oldIndex) {
  59973. var featureName = featureNames[newIndex];
  59974. var oldName = featureNames[oldIndex];
  59975. var featureOpt = featureOpts[featureName];
  59976. var featureModel = new Model(featureOpt, toolboxModel, toolboxModel.ecModel);
  59977. var feature;
  59978. if (featureName && !oldName) { // Create
  59979. if (isUserFeatureName(featureName)) {
  59980. feature = {
  59981. model: featureModel,
  59982. onclick: featureModel.option.onclick,
  59983. featureName: featureName
  59984. };
  59985. }
  59986. else {
  59987. var Feature = featureManager.get(featureName);
  59988. if (!Feature) {
  59989. return;
  59990. }
  59991. feature = new Feature(featureModel, ecModel, api);
  59992. }
  59993. features[featureName] = feature;
  59994. }
  59995. else {
  59996. feature = features[oldName];
  59997. // If feature does not exsit.
  59998. if (!feature) {
  59999. return;
  60000. }
  60001. feature.model = featureModel;
  60002. feature.ecModel = ecModel;
  60003. feature.api = api;
  60004. }
  60005. if (!featureName && oldName) {
  60006. feature.dispose && feature.dispose(ecModel, api);
  60007. return;
  60008. }
  60009. if (!featureModel.get('show') || feature.unusable) {
  60010. feature.remove && feature.remove(ecModel, api);
  60011. return;
  60012. }
  60013. createIconPaths(featureModel, feature, featureName);
  60014. featureModel.setIconStatus = function (iconName, status) {
  60015. var option = this.option;
  60016. var iconPaths = this.iconPaths;
  60017. option.iconStatus = option.iconStatus || {};
  60018. option.iconStatus[iconName] = status;
  60019. // FIXME
  60020. iconPaths[iconName] && iconPaths[iconName].trigger(status);
  60021. };
  60022. if (feature.render) {
  60023. feature.render(featureModel, ecModel, api, payload);
  60024. }
  60025. }
  60026. function createIconPaths(featureModel, feature, featureName) {
  60027. var iconStyleModel = featureModel.getModel('iconStyle');
  60028. // If one feature has mutiple icon. they are orginaized as
  60029. // {
  60030. // icon: {
  60031. // foo: '',
  60032. // bar: ''
  60033. // },
  60034. // title: {
  60035. // foo: '',
  60036. // bar: ''
  60037. // }
  60038. // }
  60039. var icons = feature.getIcons ? feature.getIcons() : featureModel.get('icon');
  60040. var titles = featureModel.get('title') || {};
  60041. if (typeof icons === 'string') {
  60042. var icon = icons;
  60043. var title = titles;
  60044. icons = {};
  60045. titles = {};
  60046. icons[featureName] = icon;
  60047. titles[featureName] = title;
  60048. }
  60049. var iconPaths = featureModel.iconPaths = {};
  60050. zrUtil.each(icons, function (icon, iconName) {
  60051. var normalStyle = iconStyleModel.getModel('normal').getItemStyle();
  60052. var hoverStyle = iconStyleModel.getModel('emphasis').getItemStyle();
  60053. var style = {
  60054. x: -itemSize / 2,
  60055. y: -itemSize / 2,
  60056. width: itemSize,
  60057. height: itemSize
  60058. };
  60059. var path = icon.indexOf('image://') === 0
  60060. ? (
  60061. style.image = icon.slice(8),
  60062. new graphic.Image({style: style})
  60063. )
  60064. : graphic.makePath(
  60065. icon.replace('path://', ''),
  60066. {
  60067. style: normalStyle,
  60068. hoverStyle: hoverStyle,
  60069. rectHover: true
  60070. },
  60071. style,
  60072. 'center'
  60073. );
  60074. graphic.setHoverStyle(path);
  60075. if (toolboxModel.get('showTitle')) {
  60076. path.__title = titles[iconName];
  60077. path.on('mouseover', function () {
  60078. // Should not reuse above hoverStyle, which might be modified.
  60079. var hoverStyle = iconStyleModel.getModel('emphasis').getItemStyle();
  60080. path.setStyle({
  60081. text: titles[iconName],
  60082. textPosition: hoverStyle.textPosition || 'bottom',
  60083. textFill: hoverStyle.fill || hoverStyle.stroke || '#000',
  60084. textAlign: hoverStyle.textAlign || 'center'
  60085. });
  60086. })
  60087. .on('mouseout', function () {
  60088. path.setStyle({
  60089. textFill: null
  60090. });
  60091. });
  60092. }
  60093. path.trigger(featureModel.get('iconStatus.' + iconName) || 'normal');
  60094. group.add(path);
  60095. path.on('click', zrUtil.bind(
  60096. feature.onclick, feature, ecModel, api, iconName
  60097. ));
  60098. iconPaths[iconName] = path;
  60099. });
  60100. }
  60101. listComponentHelper.layout(group, toolboxModel, api);
  60102. // Render background after group is layout
  60103. // FIXME
  60104. listComponentHelper.addBackground(group, toolboxModel);
  60105. // Adjust icon title positions to avoid them out of screen
  60106. group.eachChild(function (icon) {
  60107. var titleText = icon.__title;
  60108. var hoverStyle = icon.hoverStyle;
  60109. // May be background element
  60110. if (hoverStyle && titleText) {
  60111. var rect = textContain.getBoundingRect(
  60112. titleText, hoverStyle.font
  60113. );
  60114. var offsetX = icon.position[0] + group.position[0];
  60115. var offsetY = icon.position[1] + group.position[1] + itemSize;
  60116. var needPutOnTop = false;
  60117. if (offsetY + rect.height > api.getHeight()) {
  60118. hoverStyle.textPosition = 'top';
  60119. needPutOnTop = true;
  60120. }
  60121. var topOffset = needPutOnTop ? (-5 - rect.height) : (itemSize + 8);
  60122. if (offsetX + rect.width / 2 > api.getWidth()) {
  60123. hoverStyle.textPosition = ['100%', topOffset];
  60124. hoverStyle.textAlign = 'right';
  60125. }
  60126. else if (offsetX - rect.width / 2 < 0) {
  60127. hoverStyle.textPosition = [0, topOffset];
  60128. hoverStyle.textAlign = 'left';
  60129. }
  60130. }
  60131. });
  60132. },
  60133. updateView: function (toolboxModel, ecModel, api, payload) {
  60134. zrUtil.each(this._features, function (feature) {
  60135. feature.updateView && feature.updateView(feature.model, ecModel, api, payload);
  60136. });
  60137. },
  60138. updateLayout: function (toolboxModel, ecModel, api, payload) {
  60139. zrUtil.each(this._features, function (feature) {
  60140. feature.updateLayout && feature.updateLayout(feature.model, ecModel, api, payload);
  60141. });
  60142. },
  60143. remove: function (ecModel, api) {
  60144. zrUtil.each(this._features, function (feature) {
  60145. feature.remove && feature.remove(ecModel, api);
  60146. });
  60147. this.group.removeAll();
  60148. },
  60149. dispose: function (ecModel, api) {
  60150. zrUtil.each(this._features, function (feature) {
  60151. feature.dispose && feature.dispose(ecModel, api);
  60152. });
  60153. }
  60154. });
  60155. function isUserFeatureName(featureName) {
  60156. return featureName.indexOf('my') === 0;
  60157. }
  60158. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(309)))
  60159. /***/ },
  60160. /* 414 */
  60161. /***/ function(module, exports, __webpack_require__) {
  60162. var env = __webpack_require__(2);
  60163. function SaveAsImage (model) {
  60164. this.model = model;
  60165. }
  60166. SaveAsImage.defaultOption = {
  60167. show: true,
  60168. icon: 'M4.7,22.9L29.3,45.5L54.7,23.4M4.6,43.6L4.6,58L53.8,58L53.8,43.6M29.2,45.1L29.2,0',
  60169. title: '保存为图片',
  60170. type: 'png',
  60171. // Default use option.backgroundColor
  60172. // backgroundColor: '#fff',
  60173. name: '',
  60174. excludeComponents: ['toolbox'],
  60175. pixelRatio: 1,
  60176. lang: ['右键另存为图片']
  60177. };
  60178. SaveAsImage.prototype.unusable = !env.canvasSupported;
  60179. var proto = SaveAsImage.prototype;
  60180. proto.onclick = function (ecModel, api) {
  60181. var model = this.model;
  60182. var title = model.get('name') || ecModel.get('title.0.text') || 'echarts';
  60183. var $a = document.createElement('a');
  60184. var type = model.get('type', true) || 'png';
  60185. $a.download = title + '.' + type;
  60186. $a.target = '_blank';
  60187. var url = api.getConnectedDataURL({
  60188. type: type,
  60189. backgroundColor: model.get('backgroundColor', true)
  60190. || ecModel.get('backgroundColor') || '#fff',
  60191. excludeComponents: model.get('excludeComponents'),
  60192. pixelRatio: model.get('pixelRatio')
  60193. });
  60194. $a.href = url;
  60195. // Chrome and Firefox
  60196. if (typeof MouseEvent === 'function' && !env.browser.ie && !env.browser.edge) {
  60197. var evt = new MouseEvent('click', {
  60198. view: window,
  60199. bubbles: true,
  60200. cancelable: false
  60201. });
  60202. $a.dispatchEvent(evt);
  60203. }
  60204. // IE
  60205. else {
  60206. var lang = model.get('lang');
  60207. var html = ''
  60208. + '<body style="margin:0;">'
  60209. + '<img src="' + url + '" style="max-width:100%;" title="' + ((lang && lang[0]) || '') + '" />'
  60210. + '</body>';
  60211. var tab = window.open();
  60212. tab.document.write(html);
  60213. }
  60214. };
  60215. __webpack_require__(356).register(
  60216. 'saveAsImage', SaveAsImage
  60217. );
  60218. module.exports = SaveAsImage;
  60219. /***/ },
  60220. /* 415 */
  60221. /***/ function(module, exports, __webpack_require__) {
  60222. 'use strict';
  60223. var zrUtil = __webpack_require__(4);
  60224. function MagicType(model) {
  60225. this.model = model;
  60226. }
  60227. MagicType.defaultOption = {
  60228. show: true,
  60229. type: [],
  60230. // Icon group
  60231. icon: {
  60232. line: 'M4.1,28.9h7.1l9.3-22l7.4,38l9.7-19.7l3,12.8h14.9M4.1,58h51.4',
  60233. bar: 'M6.7,22.9h10V48h-10V22.9zM24.9,13h10v35h-10V13zM43.2,2h10v46h-10V2zM3.1,58h53.7',
  60234. stack: 'M8.2,38.4l-8.4,4.1l30.6,15.3L60,42.5l-8.1-4.1l-21.5,11L8.2,38.4z M51.9,30l-8.1,4.2l-13.4,6.9l-13.9-6.9L8.2,30l-8.4,4.2l8.4,4.2l22.2,11l21.5-11l8.1-4.2L51.9,30z M51.9,21.7l-8.1,4.2L35.7,30l-5.3,2.8L24.9,30l-8.4-4.1l-8.3-4.2l-8.4,4.2L8.2,30l8.3,4.2l13.9,6.9l13.4-6.9l8.1-4.2l8.1-4.1L51.9,21.7zM30.4,2.2L-0.2,17.5l8.4,4.1l8.3,4.2l8.4,4.2l5.5,2.7l5.3-2.7l8.1-4.2l8.1-4.2l8.1-4.1L30.4,2.2z', // jshint ignore:line
  60235. tiled: 'M2.3,2.2h22.8V25H2.3V2.2z M35,2.2h22.8V25H35V2.2zM2.3,35h22.8v22.8H2.3V35z M35,35h22.8v22.8H35V35z'
  60236. },
  60237. title: {
  60238. line: '切换为折线图',
  60239. bar: '切换为柱状图',
  60240. stack: '切换为堆叠',
  60241. tiled: '切换为平铺'
  60242. },
  60243. option: {},
  60244. seriesIndex: {}
  60245. };
  60246. var proto = MagicType.prototype;
  60247. proto.getIcons = function () {
  60248. var model = this.model;
  60249. var availableIcons = model.get('icon');
  60250. var icons = {};
  60251. zrUtil.each(model.get('type'), function (type) {
  60252. if (availableIcons[type]) {
  60253. icons[type] = availableIcons[type];
  60254. }
  60255. });
  60256. return icons;
  60257. };
  60258. var seriesOptGenreator = {
  60259. 'line': function (seriesType, seriesId, seriesModel, model) {
  60260. if (seriesType === 'bar') {
  60261. return zrUtil.merge({
  60262. id: seriesId,
  60263. type: 'line',
  60264. // Preserve data related option
  60265. data: seriesModel.get('data'),
  60266. stack: seriesModel.get('stack'),
  60267. markPoint: seriesModel.get('markPoint'),
  60268. markLine: seriesModel.get('markLine')
  60269. }, model.get('option.line') || {}, true);
  60270. }
  60271. },
  60272. 'bar': function (seriesType, seriesId, seriesModel, model) {
  60273. if (seriesType === 'line') {
  60274. return zrUtil.merge({
  60275. id: seriesId,
  60276. type: 'bar',
  60277. // Preserve data related option
  60278. data: seriesModel.get('data'),
  60279. stack: seriesModel.get('stack'),
  60280. markPoint: seriesModel.get('markPoint'),
  60281. markLine: seriesModel.get('markLine')
  60282. }, model.get('option.bar') || {}, true);
  60283. }
  60284. },
  60285. 'stack': function (seriesType, seriesId, seriesModel, model) {
  60286. if (seriesType === 'line' || seriesType === 'bar') {
  60287. return zrUtil.merge({
  60288. id: seriesId,
  60289. stack: '__ec_magicType_stack__'
  60290. }, model.get('option.stack') || {}, true);
  60291. }
  60292. },
  60293. 'tiled': function (seriesType, seriesId, seriesModel, model) {
  60294. if (seriesType === 'line' || seriesType === 'bar') {
  60295. return zrUtil.merge({
  60296. id: seriesId,
  60297. stack: ''
  60298. }, model.get('option.tiled') || {}, true);
  60299. }
  60300. }
  60301. };
  60302. var radioTypes = [
  60303. ['line', 'bar'],
  60304. ['stack', 'tiled']
  60305. ];
  60306. proto.onclick = function (ecModel, api, type) {
  60307. var model = this.model;
  60308. var seriesIndex = model.get('seriesIndex.' + type);
  60309. // Not supported magicType
  60310. if (!seriesOptGenreator[type]) {
  60311. return;
  60312. }
  60313. var newOption = {
  60314. series: []
  60315. };
  60316. var generateNewSeriesTypes = function (seriesModel) {
  60317. var seriesType = seriesModel.subType;
  60318. var seriesId = seriesModel.id;
  60319. var newSeriesOpt = seriesOptGenreator[type](
  60320. seriesType, seriesId, seriesModel, model
  60321. );
  60322. if (newSeriesOpt) {
  60323. // PENDING If merge original option?
  60324. zrUtil.defaults(newSeriesOpt, seriesModel.option);
  60325. newOption.series.push(newSeriesOpt);
  60326. }
  60327. // Modify boundaryGap
  60328. var coordSys = seriesModel.coordinateSystem;
  60329. if (coordSys && coordSys.type === 'cartesian2d' && (type === 'line' || type === 'bar')) {
  60330. var categoryAxis = coordSys.getAxesByScale('ordinal')[0];
  60331. if (categoryAxis) {
  60332. var axisDim = categoryAxis.dim;
  60333. var axisType = axisDim + 'Axis';
  60334. var axisModel = ecModel.queryComponents({
  60335. mainType: axisType,
  60336. index: seriesModel.get(name + 'Index'),
  60337. id: seriesModel.get(name + 'Id')
  60338. })[0];
  60339. var axisIndex = axisModel.componentIndex;
  60340. newOption[axisType] = newOption[axisType] || [];
  60341. for (var i = 0; i <= axisIndex; i++) {
  60342. newOption[axisType][axisIndex] = newOption[axisType][axisIndex] || {};
  60343. }
  60344. newOption[axisType][axisIndex].boundaryGap = type === 'bar' ? true : false;
  60345. }
  60346. }
  60347. };
  60348. zrUtil.each(radioTypes, function (radio) {
  60349. if (zrUtil.indexOf(radio, type) >= 0) {
  60350. zrUtil.each(radio, function (item) {
  60351. model.setIconStatus(item, 'normal');
  60352. });
  60353. }
  60354. });
  60355. model.setIconStatus(type, 'emphasis');
  60356. ecModel.eachComponent(
  60357. {
  60358. mainType: 'series',
  60359. query: seriesIndex == null ? null : {
  60360. seriesIndex: seriesIndex
  60361. }
  60362. }, generateNewSeriesTypes
  60363. );
  60364. api.dispatchAction({
  60365. type: 'changeMagicType',
  60366. currentType: type,
  60367. newOption: newOption
  60368. });
  60369. };
  60370. var echarts = __webpack_require__(1);
  60371. echarts.registerAction({
  60372. type: 'changeMagicType',
  60373. event: 'magicTypeChanged',
  60374. update: 'prepareAndUpdate'
  60375. }, function (payload, ecModel) {
  60376. ecModel.mergeOption(payload.newOption);
  60377. });
  60378. __webpack_require__(356).register('magicType', MagicType);
  60379. module.exports = MagicType;
  60380. /***/ },
  60381. /* 416 */
  60382. /***/ function(module, exports, __webpack_require__) {
  60383. /**
  60384. * @module echarts/component/toolbox/feature/DataView
  60385. */
  60386. var zrUtil = __webpack_require__(4);
  60387. var eventTool = __webpack_require__(88);
  60388. var BLOCK_SPLITER = new Array(60).join('-');
  60389. var ITEM_SPLITER = '\t';
  60390. /**
  60391. * Group series into two types
  60392. * 1. on category axis, like line, bar
  60393. * 2. others, like scatter, pie
  60394. * @param {module:echarts/model/Global} ecModel
  60395. * @return {Object}
  60396. * @inner
  60397. */
  60398. function groupSeries(ecModel) {
  60399. var seriesGroupByCategoryAxis = {};
  60400. var otherSeries = [];
  60401. var meta = [];
  60402. ecModel.eachRawSeries(function (seriesModel) {
  60403. var coordSys = seriesModel.coordinateSystem;
  60404. if (coordSys && (coordSys.type === 'cartesian2d' || coordSys.type === 'polar')) {
  60405. var baseAxis = coordSys.getBaseAxis();
  60406. if (baseAxis.type === 'category') {
  60407. var key = baseAxis.dim + '_' + baseAxis.index;
  60408. if (!seriesGroupByCategoryAxis[key]) {
  60409. seriesGroupByCategoryAxis[key] = {
  60410. categoryAxis: baseAxis,
  60411. valueAxis: coordSys.getOtherAxis(baseAxis),
  60412. series: []
  60413. };
  60414. meta.push({
  60415. axisDim: baseAxis.dim,
  60416. axisIndex: baseAxis.index
  60417. });
  60418. }
  60419. seriesGroupByCategoryAxis[key].series.push(seriesModel);
  60420. }
  60421. else {
  60422. otherSeries.push(seriesModel);
  60423. }
  60424. }
  60425. else {
  60426. otherSeries.push(seriesModel);
  60427. }
  60428. });
  60429. return {
  60430. seriesGroupByCategoryAxis: seriesGroupByCategoryAxis,
  60431. other: otherSeries,
  60432. meta: meta
  60433. };
  60434. }
  60435. /**
  60436. * Assemble content of series on cateogory axis
  60437. * @param {Array.<module:echarts/model/Series>} series
  60438. * @return {string}
  60439. * @inner
  60440. */
  60441. function assembleSeriesWithCategoryAxis(series) {
  60442. var tables = [];
  60443. zrUtil.each(series, function (group, key) {
  60444. var categoryAxis = group.categoryAxis;
  60445. var valueAxis = group.valueAxis;
  60446. var valueAxisDim = valueAxis.dim;
  60447. var headers = [' '].concat(zrUtil.map(group.series, function (series) {
  60448. return series.name;
  60449. }));
  60450. var columns = [categoryAxis.model.getCategories()];
  60451. zrUtil.each(group.series, function (series) {
  60452. columns.push(series.getRawData().mapArray(valueAxisDim, function (val) {
  60453. return val;
  60454. }));
  60455. });
  60456. // Assemble table content
  60457. var lines = [headers.join(ITEM_SPLITER)];
  60458. for (var i = 0; i < columns[0].length; i++) {
  60459. var items = [];
  60460. for (var j = 0; j < columns.length; j++) {
  60461. items.push(columns[j][i]);
  60462. }
  60463. lines.push(items.join(ITEM_SPLITER));
  60464. }
  60465. tables.push(lines.join('\n'));
  60466. });
  60467. return tables.join('\n\n' + BLOCK_SPLITER + '\n\n');
  60468. }
  60469. /**
  60470. * Assemble content of other series
  60471. * @param {Array.<module:echarts/model/Series>} series
  60472. * @return {string}
  60473. * @inner
  60474. */
  60475. function assembleOtherSeries(series) {
  60476. return zrUtil.map(series, function (series) {
  60477. var data = series.getRawData();
  60478. var lines = [series.name];
  60479. var vals = [];
  60480. data.each(data.dimensions, function () {
  60481. var argLen = arguments.length;
  60482. var dataIndex = arguments[argLen - 1];
  60483. var name = data.getName(dataIndex);
  60484. for (var i = 0; i < argLen - 1; i++) {
  60485. vals[i] = arguments[i];
  60486. }
  60487. lines.push((name ? (name + ITEM_SPLITER) : '') + vals.join(ITEM_SPLITER));
  60488. });
  60489. return lines.join('\n');
  60490. }).join('\n\n' + BLOCK_SPLITER + '\n\n');
  60491. }
  60492. /**
  60493. * @param {module:echarts/model/Global}
  60494. * @return {string}
  60495. * @inner
  60496. */
  60497. function getContentFromModel(ecModel) {
  60498. var result = groupSeries(ecModel);
  60499. return {
  60500. value: zrUtil.filter([
  60501. assembleSeriesWithCategoryAxis(result.seriesGroupByCategoryAxis),
  60502. assembleOtherSeries(result.other)
  60503. ], function (str) {
  60504. return str.replace(/[\n\t\s]/g, '');
  60505. }).join('\n\n' + BLOCK_SPLITER + '\n\n'),
  60506. meta: result.meta
  60507. };
  60508. }
  60509. function trim(str) {
  60510. return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
  60511. }
  60512. /**
  60513. * If a block is tsv format
  60514. */
  60515. function isTSVFormat(block) {
  60516. // Simple method to find out if a block is tsv format
  60517. var firstLine = block.slice(0, block.indexOf('\n'));
  60518. if (firstLine.indexOf(ITEM_SPLITER) >= 0) {
  60519. return true;
  60520. }
  60521. }
  60522. var itemSplitRegex = new RegExp('[' + ITEM_SPLITER + ']+', 'g');
  60523. /**
  60524. * @param {string} tsv
  60525. * @return {Array.<Object>}
  60526. */
  60527. function parseTSVContents(tsv) {
  60528. var tsvLines = tsv.split(/\n+/g);
  60529. var headers = trim(tsvLines.shift()).split(itemSplitRegex);
  60530. var categories = [];
  60531. var series = zrUtil.map(headers, function (header) {
  60532. return {
  60533. name: header,
  60534. data: []
  60535. };
  60536. });
  60537. for (var i = 0; i < tsvLines.length; i++) {
  60538. var items = trim(tsvLines[i]).split(itemSplitRegex);
  60539. categories.push(items.shift());
  60540. for (var j = 0; j < items.length; j++) {
  60541. series[j] && (series[j].data[i] = items[j]);
  60542. }
  60543. }
  60544. return {
  60545. series: series,
  60546. categories: categories
  60547. };
  60548. }
  60549. /**
  60550. * @param {string} str
  60551. * @return {Array.<Object>}
  60552. * @inner
  60553. */
  60554. function parseListContents(str) {
  60555. var lines = str.split(/\n+/g);
  60556. var seriesName = trim(lines.shift());
  60557. var data = [];
  60558. for (var i = 0; i < lines.length; i++) {
  60559. var items = trim(lines[i]).split(itemSplitRegex);
  60560. var name = '';
  60561. var value;
  60562. var hasName = false;
  60563. if (isNaN(items[0])) { // First item is name
  60564. hasName = true;
  60565. name = items[0];
  60566. items = items.slice(1);
  60567. data[i] = {
  60568. name: name,
  60569. value: []
  60570. };
  60571. value = data[i].value;
  60572. }
  60573. else {
  60574. value = data[i] = [];
  60575. }
  60576. for (var j = 0; j < items.length; j++) {
  60577. value.push(+items[j]);
  60578. }
  60579. if (value.length === 1) {
  60580. hasName ? (data[i].value = value[0]) : (data[i] = value[0]);
  60581. }
  60582. }
  60583. return {
  60584. name: seriesName,
  60585. data: data
  60586. };
  60587. }
  60588. /**
  60589. * @param {string} str
  60590. * @param {Array.<Object>} blockMetaList
  60591. * @return {Object}
  60592. * @inner
  60593. */
  60594. function parseContents(str, blockMetaList) {
  60595. var blocks = str.split(new RegExp('\n*' + BLOCK_SPLITER + '\n*', 'g'));
  60596. var newOption = {
  60597. series: []
  60598. };
  60599. zrUtil.each(blocks, function (block, idx) {
  60600. if (isTSVFormat(block)) {
  60601. var result = parseTSVContents(block);
  60602. var blockMeta = blockMetaList[idx];
  60603. var axisKey = blockMeta.axisDim + 'Axis';
  60604. if (blockMeta) {
  60605. newOption[axisKey] = newOption[axisKey] || [];
  60606. newOption[axisKey][blockMeta.axisIndex] = {
  60607. data: result.categories
  60608. };
  60609. newOption.series = newOption.series.concat(result.series);
  60610. }
  60611. }
  60612. else {
  60613. var result = parseListContents(block);
  60614. newOption.series.push(result);
  60615. }
  60616. });
  60617. return newOption;
  60618. }
  60619. /**
  60620. * @alias {module:echarts/component/toolbox/feature/DataView}
  60621. * @constructor
  60622. * @param {module:echarts/model/Model} model
  60623. */
  60624. function DataView(model) {
  60625. this._dom = null;
  60626. this.model = model;
  60627. }
  60628. DataView.defaultOption = {
  60629. show: true,
  60630. readOnly: false,
  60631. optionToContent: null,
  60632. contentToOption: null,
  60633. icon: 'M17.5,17.3H33 M17.5,17.3H33 M45.4,29.5h-28 M11.5,2v56H51V14.8L38.4,2H11.5z M38.4,2.2v12.7H51 M45.4,41.7h-28',
  60634. title: '数据视图',
  60635. lang: ['数据视图', '关闭', '刷新'],
  60636. backgroundColor: '#fff',
  60637. textColor: '#000',
  60638. textareaColor: '#fff',
  60639. textareaBorderColor: '#333',
  60640. buttonColor: '#c23531',
  60641. buttonTextColor: '#fff'
  60642. };
  60643. DataView.prototype.onclick = function (ecModel, api) {
  60644. var container = api.getDom();
  60645. var model = this.model;
  60646. if (this._dom) {
  60647. container.removeChild(this._dom);
  60648. }
  60649. var root = document.createElement('div');
  60650. root.style.cssText = 'position:absolute;left:5px;top:5px;bottom:5px;right:5px;';
  60651. root.style.backgroundColor = model.get('backgroundColor') || '#fff';
  60652. // Create elements
  60653. var header = document.createElement('h4');
  60654. var lang = model.get('lang') || [];
  60655. header.innerHTML = lang[0] || model.get('title');
  60656. header.style.cssText = 'margin: 10px 20px;';
  60657. header.style.color = model.get('textColor');
  60658. var viewMain = document.createElement('div');
  60659. var textarea = document.createElement('textarea');
  60660. viewMain.style.cssText = 'display:block;width:100%;overflow:auto;';
  60661. var optionToContent = model.get('optionToContent');
  60662. var contentToOption = model.get('contentToOption');
  60663. var result = getContentFromModel(ecModel);
  60664. if (typeof optionToContent === 'function') {
  60665. var htmlOrDom = optionToContent(api.getOption());
  60666. if (typeof htmlOrDom === 'string') {
  60667. viewMain.innerHTML = htmlOrDom;
  60668. }
  60669. else if (zrUtil.isDom(htmlOrDom)) {
  60670. viewMain.appendChild(htmlOrDom);
  60671. }
  60672. }
  60673. else {
  60674. // Use default textarea
  60675. viewMain.appendChild(textarea);
  60676. textarea.readOnly = model.get('readOnly');
  60677. textarea.style.cssText = 'width:100%;height:100%;font-family:monospace;font-size:14px;line-height:1.6rem;';
  60678. textarea.style.color = model.get('textColor');
  60679. textarea.style.borderColor = model.get('textareaBorderColor');
  60680. textarea.style.backgroundColor = model.get('textareaColor');
  60681. textarea.value = result.value;
  60682. }
  60683. var blockMetaList = result.meta;
  60684. var buttonContainer = document.createElement('div');
  60685. buttonContainer.style.cssText = 'position:absolute;bottom:0;left:0;right:0;';
  60686. var buttonStyle = 'float:right;margin-right:20px;border:none;'
  60687. + 'cursor:pointer;padding:2px 5px;font-size:12px;border-radius:3px';
  60688. var closeButton = document.createElement('div');
  60689. var refreshButton = document.createElement('div');
  60690. buttonStyle += ';background-color:' + model.get('buttonColor');
  60691. buttonStyle += ';color:' + model.get('buttonTextColor');
  60692. var self = this;
  60693. function close() {
  60694. container.removeChild(root);
  60695. self._dom = null;
  60696. }
  60697. eventTool.addEventListener(closeButton, 'click', close);
  60698. eventTool.addEventListener(refreshButton, 'click', function () {
  60699. var newOption;
  60700. try {
  60701. if (typeof contentToOption === 'function') {
  60702. newOption = contentToOption(viewMain, api.getOption());
  60703. }
  60704. else {
  60705. newOption = parseContents(textarea.value, blockMetaList);
  60706. }
  60707. }
  60708. catch (e) {
  60709. close();
  60710. throw new Error('Data view format error ' + e);
  60711. }
  60712. if (newOption) {
  60713. api.dispatchAction({
  60714. type: 'changeDataView',
  60715. newOption: newOption
  60716. });
  60717. }
  60718. close();
  60719. });
  60720. closeButton.innerHTML = lang[1];
  60721. refreshButton.innerHTML = lang[2];
  60722. refreshButton.style.cssText = buttonStyle;
  60723. closeButton.style.cssText = buttonStyle;
  60724. !model.get('readOnly') && buttonContainer.appendChild(refreshButton);
  60725. buttonContainer.appendChild(closeButton);
  60726. // http://stackoverflow.com/questions/6637341/use-tab-to-indent-in-textarea
  60727. eventTool.addEventListener(textarea, 'keydown', function (e) {
  60728. if ((e.keyCode || e.which) === 9) {
  60729. // get caret position/selection
  60730. var val = this.value;
  60731. var start = this.selectionStart;
  60732. var end = this.selectionEnd;
  60733. // set textarea value to: text before caret + tab + text after caret
  60734. this.value = val.substring(0, start) + ITEM_SPLITER + val.substring(end);
  60735. // put caret at right position again
  60736. this.selectionStart = this.selectionEnd = start + 1;
  60737. // prevent the focus lose
  60738. eventTool.stop(e);
  60739. }
  60740. });
  60741. root.appendChild(header);
  60742. root.appendChild(viewMain);
  60743. root.appendChild(buttonContainer);
  60744. viewMain.style.height = (container.clientHeight - 80) + 'px';
  60745. container.appendChild(root);
  60746. this._dom = root;
  60747. };
  60748. DataView.prototype.remove = function (ecModel, api) {
  60749. this._dom && api.getDom().removeChild(this._dom);
  60750. };
  60751. DataView.prototype.dispose = function (ecModel, api) {
  60752. this.remove(ecModel, api);
  60753. };
  60754. /**
  60755. * @inner
  60756. */
  60757. function tryMergeDataOption(newData, originalData) {
  60758. return zrUtil.map(newData, function (newVal, idx) {
  60759. var original = originalData && originalData[idx];
  60760. if (zrUtil.isObject(original) && !zrUtil.isArray(original)) {
  60761. if (zrUtil.isObject(newVal) && !zrUtil.isArray(newVal)) {
  60762. newVal = newVal.value;
  60763. }
  60764. // Original data has option
  60765. return zrUtil.defaults({
  60766. value: newVal
  60767. }, original);
  60768. }
  60769. else {
  60770. return newVal;
  60771. }
  60772. });
  60773. }
  60774. __webpack_require__(356).register('dataView', DataView);
  60775. __webpack_require__(1).registerAction({
  60776. type: 'changeDataView',
  60777. event: 'dataViewChanged',
  60778. update: 'prepareAndUpdate'
  60779. }, function (payload, ecModel) {
  60780. var newSeriesOptList = [];
  60781. zrUtil.each(payload.newOption.series, function (seriesOpt) {
  60782. var seriesModel = ecModel.getSeriesByName(seriesOpt.name)[0];
  60783. if (!seriesModel) {
  60784. // New created series
  60785. // Geuss the series type
  60786. newSeriesOptList.push(zrUtil.extend({
  60787. // Default is scatter
  60788. type: 'scatter'
  60789. }, seriesOpt));
  60790. }
  60791. else {
  60792. var originalData = seriesModel.get('data');
  60793. newSeriesOptList.push({
  60794. name: seriesOpt.name,
  60795. data: tryMergeDataOption(seriesOpt.data, originalData)
  60796. });
  60797. }
  60798. });
  60799. ecModel.mergeOption(zrUtil.defaults({
  60800. series: newSeriesOptList
  60801. }, payload.newOption));
  60802. });
  60803. module.exports = DataView;
  60804. /***/ },
  60805. /* 417 */
  60806. /***/ function(module, exports, __webpack_require__) {
  60807. 'use strict';
  60808. var zrUtil = __webpack_require__(4);
  60809. var BrushController = __webpack_require__(244);
  60810. var BrushTargetManager = __webpack_require__(351);
  60811. var history = __webpack_require__(418);
  60812. var sliderMove = __webpack_require__(238);
  60813. var each = zrUtil.each;
  60814. // Use dataZoomSelect
  60815. __webpack_require__(419);
  60816. // Spectial component id start with \0ec\0, see echarts/model/Global.js~hasInnerId
  60817. var DATA_ZOOM_ID_BASE = '\0_ec_\0toolbox-dataZoom_';
  60818. function DataZoom(model, ecModel, api) {
  60819. /**
  60820. * @private
  60821. * @type {module:echarts/component/helper/BrushController}
  60822. */
  60823. (this._brushController = new BrushController(api.getZr()))
  60824. .on('brush', zrUtil.bind(this._onBrush, this))
  60825. .mount();
  60826. /**
  60827. * @private
  60828. * @type {boolean}
  60829. */
  60830. this._isZoomActive;
  60831. }
  60832. DataZoom.defaultOption = {
  60833. show: true,
  60834. // Icon group
  60835. icon: {
  60836. zoom: 'M0,13.5h26.9 M13.5,26.9V0 M32.1,13.5H58V58H13.5 V32.1',
  60837. back: 'M22,1.4L9.9,13.5l12.3,12.3 M10.3,13.5H54.9v44.6 H10.3v-26'
  60838. },
  60839. title: {
  60840. zoom: '区域缩放',
  60841. back: '区域缩放还原'
  60842. }
  60843. };
  60844. var proto = DataZoom.prototype;
  60845. proto.render = function (featureModel, ecModel, api, payload) {
  60846. this.model = featureModel;
  60847. this.ecModel = ecModel;
  60848. this.api = api;
  60849. updateZoomBtnStatus(featureModel, ecModel, this, payload, api);
  60850. updateBackBtnStatus(featureModel, ecModel);
  60851. };
  60852. proto.onclick = function (ecModel, api, type) {
  60853. handlers[type].call(this);
  60854. };
  60855. proto.remove = function (ecModel, api) {
  60856. this._brushController.unmount();
  60857. };
  60858. proto.dispose = function (ecModel, api) {
  60859. this._brushController.dispose();
  60860. };
  60861. /**
  60862. * @private
  60863. */
  60864. var handlers = {
  60865. zoom: function () {
  60866. var nextActive = !this._isZoomActive;
  60867. this.api.dispatchAction({
  60868. type: 'takeGlobalCursor',
  60869. key: 'dataZoomSelect',
  60870. dataZoomSelectActive: nextActive
  60871. });
  60872. },
  60873. back: function () {
  60874. this._dispatchZoomAction(history.pop(this.ecModel));
  60875. }
  60876. };
  60877. /**
  60878. * @private
  60879. */
  60880. proto._onBrush = function (areas, opt) {
  60881. if (!opt.isEnd || !areas.length) {
  60882. return;
  60883. }
  60884. var snapshot = {};
  60885. var ecModel = this.ecModel;
  60886. this._brushController.updateCovers([]); // remove cover
  60887. var brushTargetManager = new BrushTargetManager(
  60888. retrieveAxisSetting(this.model.option), ecModel, {include: ['grid']}
  60889. );
  60890. brushTargetManager.matchOutputRanges(areas, ecModel, function (area, coordRange, coordSys) {
  60891. if (coordSys.type !== 'cartesian2d') {
  60892. return;
  60893. }
  60894. var brushType = area.brushType;
  60895. if (brushType === 'rect') {
  60896. setBatch('x', coordSys, coordRange[0]);
  60897. setBatch('y', coordSys, coordRange[1]);
  60898. }
  60899. else {
  60900. setBatch(({lineX: 'x', lineY: 'y'})[brushType], coordSys, coordRange);
  60901. }
  60902. });
  60903. history.push(ecModel, snapshot);
  60904. this._dispatchZoomAction(snapshot);
  60905. function setBatch(dimName, coordSys, minMax) {
  60906. var axis = coordSys.getAxis(dimName);
  60907. var axisModel = axis.model;
  60908. var dataZoomModel = findDataZoom(dimName, axisModel, ecModel);
  60909. // Restrict range.
  60910. var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy(axisModel).getMinMaxSpan();
  60911. if (minMaxSpan.minValueSpan != null || minMaxSpan.maxValueSpan != null) {
  60912. minMax = sliderMove(
  60913. 0, minMax.slice(), axis.scale.getExtent(), 0,
  60914. minMaxSpan.minValueSpan, minMaxSpan.maxValueSpan
  60915. );
  60916. }
  60917. dataZoomModel && (snapshot[dataZoomModel.id] = {
  60918. dataZoomId: dataZoomModel.id,
  60919. startValue: minMax[0],
  60920. endValue: minMax[1]
  60921. });
  60922. }
  60923. function findDataZoom(dimName, axisModel, ecModel) {
  60924. var found;
  60925. ecModel.eachComponent({mainType: 'dataZoom', subType: 'select'}, function (dzModel) {
  60926. var has = dzModel.getAxisModel(dimName, axisModel.componentIndex);
  60927. has && (found = dzModel);
  60928. });
  60929. return found;
  60930. }
  60931. };
  60932. /**
  60933. * @private
  60934. */
  60935. proto._dispatchZoomAction = function (snapshot) {
  60936. var batch = [];
  60937. // Convert from hash map to array.
  60938. each(snapshot, function (batchItem, dataZoomId) {
  60939. batch.push(zrUtil.clone(batchItem));
  60940. });
  60941. batch.length && this.api.dispatchAction({
  60942. type: 'dataZoom',
  60943. from: this.uid,
  60944. batch: batch
  60945. });
  60946. };
  60947. function retrieveAxisSetting(option) {
  60948. var setting = {};
  60949. // Compatible with previous setting: null => all axis, false => no axis.
  60950. zrUtil.each(['xAxisIndex', 'yAxisIndex'], function (name) {
  60951. setting[name] = option[name];
  60952. setting[name] == null && (setting[name] = 'all');
  60953. (setting[name] === false || setting[name] === 'none') && (setting[name] = []);
  60954. });
  60955. return setting;
  60956. }
  60957. function updateBackBtnStatus(featureModel, ecModel) {
  60958. featureModel.setIconStatus(
  60959. 'back',
  60960. history.count(ecModel) > 1 ? 'emphasis' : 'normal'
  60961. );
  60962. }
  60963. function updateZoomBtnStatus(featureModel, ecModel, view, payload, api) {
  60964. var zoomActive = view._isZoomActive;
  60965. if (payload && payload.type === 'takeGlobalCursor') {
  60966. zoomActive = payload.key === 'dataZoomSelect'
  60967. ? payload.dataZoomSelectActive : false;
  60968. }
  60969. view._isZoomActive = zoomActive;
  60970. featureModel.setIconStatus('zoom', zoomActive ? 'emphasis' : 'normal');
  60971. var brushTargetManager = new BrushTargetManager(
  60972. retrieveAxisSetting(featureModel.option), ecModel, {include: ['grid']}
  60973. );
  60974. view._brushController
  60975. .setPanels(brushTargetManager.makePanelOpts(api, function (targetInfo) {
  60976. return (targetInfo.xAxisDeclared && !targetInfo.yAxisDeclared)
  60977. ? 'lineX'
  60978. : (!targetInfo.xAxisDeclared && targetInfo.yAxisDeclared)
  60979. ? 'lineY'
  60980. : 'rect';
  60981. }))
  60982. .enableBrush(
  60983. zoomActive
  60984. ? {
  60985. brushType: 'auto',
  60986. brushStyle: {
  60987. // FIXME user customized?
  60988. lineWidth: 0,
  60989. fill: 'rgba(0,0,0,0.2)'
  60990. }
  60991. }
  60992. : false
  60993. );
  60994. }
  60995. __webpack_require__(356).register('dataZoom', DataZoom);
  60996. // Create special dataZoom option for select
  60997. __webpack_require__(1).registerPreprocessor(function (option) {
  60998. if (!option) {
  60999. return;
  61000. }
  61001. var dataZoomOpts = option.dataZoom || (option.dataZoom = []);
  61002. if (!zrUtil.isArray(dataZoomOpts)) {
  61003. option.dataZoom = dataZoomOpts = [dataZoomOpts];
  61004. }
  61005. var toolboxOpt = option.toolbox;
  61006. if (toolboxOpt) {
  61007. // Assume there is only one toolbox
  61008. if (zrUtil.isArray(toolboxOpt)) {
  61009. toolboxOpt = toolboxOpt[0];
  61010. }
  61011. if (toolboxOpt && toolboxOpt.feature) {
  61012. var dataZoomOpt = toolboxOpt.feature.dataZoom;
  61013. addForAxis('xAxis', dataZoomOpt);
  61014. addForAxis('yAxis', dataZoomOpt);
  61015. }
  61016. }
  61017. function addForAxis(axisName, dataZoomOpt) {
  61018. if (!dataZoomOpt) {
  61019. return;
  61020. }
  61021. // Try not to modify model, because it is not merged yet.
  61022. var axisIndicesName = axisName + 'Index';
  61023. var givenAxisIndices = dataZoomOpt[axisIndicesName];
  61024. if (givenAxisIndices != null
  61025. && givenAxisIndices != 'all'
  61026. && !zrUtil.isArray(givenAxisIndices)
  61027. ) {
  61028. givenAxisIndices = (givenAxisIndices === false || givenAxisIndices === 'none') ? [] : [givenAxisIndices];
  61029. }
  61030. forEachComponent(axisName, function (axisOpt, axisIndex) {
  61031. if (givenAxisIndices != null
  61032. && givenAxisIndices != 'all'
  61033. && zrUtil.indexOf(givenAxisIndices, axisIndex) === -1
  61034. ) {
  61035. return;
  61036. }
  61037. var newOpt = {
  61038. type: 'select',
  61039. $fromToolbox: true,
  61040. // Id for merge mapping.
  61041. id: DATA_ZOOM_ID_BASE + axisName + axisIndex
  61042. };
  61043. // FIXME
  61044. // Only support one axis now.
  61045. newOpt[axisIndicesName] = axisIndex;
  61046. dataZoomOpts.push(newOpt);
  61047. });
  61048. }
  61049. function forEachComponent(mainType, cb) {
  61050. var opts = option[mainType];
  61051. if (!zrUtil.isArray(opts)) {
  61052. opts = opts ? [opts] : [];
  61053. }
  61054. each(opts, cb);
  61055. }
  61056. });
  61057. module.exports = DataZoom;
  61058. /***/ },
  61059. /* 418 */
  61060. /***/ function(module, exports, __webpack_require__) {
  61061. /**
  61062. * @file History manager.
  61063. */
  61064. var zrUtil = __webpack_require__(4);
  61065. var each = zrUtil.each;
  61066. var ATTR = '\0_ec_hist_store';
  61067. var history = {
  61068. /**
  61069. * @public
  61070. * @param {module:echarts/model/Global} ecModel
  61071. * @param {Object} newSnapshot {dataZoomId, batch: [payloadInfo, ...]}
  61072. */
  61073. push: function (ecModel, newSnapshot) {
  61074. var store = giveStore(ecModel);
  61075. // If previous dataZoom can not be found,
  61076. // complete an range with current range.
  61077. each(newSnapshot, function (batchItem, dataZoomId) {
  61078. var i = store.length - 1;
  61079. for (; i >= 0; i--) {
  61080. var snapshot = store[i];
  61081. if (snapshot[dataZoomId]) {
  61082. break;
  61083. }
  61084. }
  61085. if (i < 0) {
  61086. // No origin range set, create one by current range.
  61087. var dataZoomModel = ecModel.queryComponents(
  61088. {mainType: 'dataZoom', subType: 'select', id: dataZoomId}
  61089. )[0];
  61090. if (dataZoomModel) {
  61091. var percentRange = dataZoomModel.getPercentRange();
  61092. store[0][dataZoomId] = {
  61093. dataZoomId: dataZoomId,
  61094. start: percentRange[0],
  61095. end: percentRange[1]
  61096. };
  61097. }
  61098. }
  61099. });
  61100. store.push(newSnapshot);
  61101. },
  61102. /**
  61103. * @public
  61104. * @param {module:echarts/model/Global} ecModel
  61105. * @return {Object} snapshot
  61106. */
  61107. pop: function (ecModel) {
  61108. var store = giveStore(ecModel);
  61109. var head = store[store.length - 1];
  61110. store.length > 1 && store.pop();
  61111. // Find top for all dataZoom.
  61112. var snapshot = {};
  61113. each(head, function (batchItem, dataZoomId) {
  61114. for (var i = store.length - 1; i >= 0; i--) {
  61115. var batchItem = store[i][dataZoomId];
  61116. if (batchItem) {
  61117. snapshot[dataZoomId] = batchItem;
  61118. break;
  61119. }
  61120. }
  61121. });
  61122. return snapshot;
  61123. },
  61124. /**
  61125. * @public
  61126. */
  61127. clear: function (ecModel) {
  61128. ecModel[ATTR] = null;
  61129. },
  61130. /**
  61131. * @public
  61132. * @param {module:echarts/model/Global} ecModel
  61133. * @return {number} records. always >= 1.
  61134. */
  61135. count: function (ecModel) {
  61136. return giveStore(ecModel).length;
  61137. }
  61138. };
  61139. /**
  61140. * [{key: dataZoomId, value: {dataZoomId, range}}, ...]
  61141. * History length of each dataZoom may be different.
  61142. * this._history[0] is used to store origin range.
  61143. * @type {Array.<Object>}
  61144. */
  61145. function giveStore(ecModel) {
  61146. var store = ecModel[ATTR];
  61147. if (!store) {
  61148. store = ecModel[ATTR] = [{}];
  61149. }
  61150. return store;
  61151. }
  61152. module.exports = history;
  61153. /***/ },
  61154. /* 419 */
  61155. /***/ function(module, exports, __webpack_require__) {
  61156. /**
  61157. * DataZoom component entry
  61158. */
  61159. __webpack_require__(363);
  61160. __webpack_require__(364);
  61161. __webpack_require__(367);
  61162. __webpack_require__(420);
  61163. __webpack_require__(421);
  61164. __webpack_require__(373);
  61165. __webpack_require__(374);
  61166. /***/ },
  61167. /* 420 */
  61168. /***/ function(module, exports, __webpack_require__) {
  61169. /**
  61170. * @file Data zoom model
  61171. */
  61172. var DataZoomModel = __webpack_require__(364);
  61173. module.exports = DataZoomModel.extend({
  61174. type: 'dataZoom.select'
  61175. });
  61176. /***/ },
  61177. /* 421 */
  61178. /***/ function(module, exports, __webpack_require__) {
  61179. module.exports = __webpack_require__(367).extend({
  61180. type: 'dataZoom.select'
  61181. });
  61182. /***/ },
  61183. /* 422 */
  61184. /***/ function(module, exports, __webpack_require__) {
  61185. 'use strict';
  61186. var history = __webpack_require__(418);
  61187. function Restore(model) {
  61188. this.model = model;
  61189. }
  61190. Restore.defaultOption = {
  61191. show: true,
  61192. icon: 'M3.8,33.4 M47,18.9h9.8V8.7 M56.3,20.1 C52.1,9,40.5,0.6,26.8,2.1C12.6,3.7,1.6,16.2,2.1,30.6 M13,41.1H3.1v10.2 M3.7,39.9c4.2,11.1,15.8,19.5,29.5,18 c14.2-1.6,25.2-14.1,24.7-28.5',
  61193. title: '还原'
  61194. };
  61195. var proto = Restore.prototype;
  61196. proto.onclick = function (ecModel, api, type) {
  61197. history.clear(ecModel);
  61198. api.dispatchAction({
  61199. type: 'restore',
  61200. from: this.uid
  61201. });
  61202. };
  61203. __webpack_require__(356).register('restore', Restore);
  61204. __webpack_require__(1).registerAction(
  61205. {type: 'restore', event: 'restore', update: 'prepareAndUpdate'},
  61206. function (payload, ecModel) {
  61207. ecModel.resetOption('recreate');
  61208. }
  61209. );
  61210. module.exports = Restore;
  61211. /***/ },
  61212. /* 423 */
  61213. /***/ function(module, exports, __webpack_require__) {
  61214. __webpack_require__(424);
  61215. __webpack_require__(82).registerPainter('vml', __webpack_require__(426));
  61216. /***/ },
  61217. /* 424 */
  61218. /***/ function(module, exports, __webpack_require__) {
  61219. // http://www.w3.org/TR/NOTE-VML
  61220. // TODO Use proxy like svg instead of overwrite brush methods
  61221. if (!__webpack_require__(2).canvasSupported) {
  61222. var vec2 = __webpack_require__(10);
  61223. var BoundingRect = __webpack_require__(9);
  61224. var CMD = __webpack_require__(36).CMD;
  61225. var colorTool = __webpack_require__(31);
  61226. var textContain = __webpack_require__(8);
  61227. var RectText = __webpack_require__(35);
  61228. var Displayable = __webpack_require__(21);
  61229. var ZImage = __webpack_require__(49);
  61230. var Text = __webpack_require__(50);
  61231. var Path = __webpack_require__(20);
  61232. var PathProxy = __webpack_require__(36);
  61233. var Gradient = __webpack_require__(66);
  61234. var vmlCore = __webpack_require__(425);
  61235. var round = Math.round;
  61236. var sqrt = Math.sqrt;
  61237. var abs = Math.abs;
  61238. var cos = Math.cos;
  61239. var sin = Math.sin;
  61240. var mathMax = Math.max;
  61241. var applyTransform = vec2.applyTransform;
  61242. var comma = ',';
  61243. var imageTransformPrefix = 'progid:DXImageTransform.Microsoft';
  61244. var Z = 21600;
  61245. var Z2 = Z / 2;
  61246. var ZLEVEL_BASE = 100000;
  61247. var Z_BASE = 1000;
  61248. var initRootElStyle = function (el) {
  61249. el.style.cssText = 'position:absolute;left:0;top:0;width:1px;height:1px;';
  61250. el.coordsize = Z + ',' + Z;
  61251. el.coordorigin = '0,0';
  61252. };
  61253. var encodeHtmlAttribute = function (s) {
  61254. return String(s).replace(/&/g, '&amp;').replace(/"/g, '&quot;');
  61255. };
  61256. var rgb2Str = function (r, g, b) {
  61257. return 'rgb(' + [r, g, b].join(',') + ')';
  61258. };
  61259. var append = function (parent, child) {
  61260. if (child && parent && child.parentNode !== parent) {
  61261. parent.appendChild(child);
  61262. }
  61263. };
  61264. var remove = function (parent, child) {
  61265. if (child && parent && child.parentNode === parent) {
  61266. parent.removeChild(child);
  61267. }
  61268. };
  61269. var getZIndex = function (zlevel, z, z2) {
  61270. // z 的取值范围为 [0, 1000]
  61271. return (parseFloat(zlevel) || 0) * ZLEVEL_BASE + (parseFloat(z) || 0) * Z_BASE + z2;
  61272. };
  61273. var parsePercent = function (value, maxValue) {
  61274. if (typeof value === 'string') {
  61275. if (value.lastIndexOf('%') >= 0) {
  61276. return parseFloat(value) / 100 * maxValue;
  61277. }
  61278. return parseFloat(value);
  61279. }
  61280. return value;
  61281. };
  61282. /***************************************************
  61283. * PATH
  61284. **************************************************/
  61285. var setColorAndOpacity = function (el, color, opacity) {
  61286. var colorArr = colorTool.parse(color);
  61287. opacity = +opacity;
  61288. if (isNaN(opacity)) {
  61289. opacity = 1;
  61290. }
  61291. if (colorArr) {
  61292. el.color = rgb2Str(colorArr[0], colorArr[1], colorArr[2]);
  61293. el.opacity = opacity * colorArr[3];
  61294. }
  61295. };
  61296. var getColorAndAlpha = function (color) {
  61297. var colorArr = colorTool.parse(color);
  61298. return [
  61299. rgb2Str(colorArr[0], colorArr[1], colorArr[2]),
  61300. colorArr[3]
  61301. ];
  61302. };
  61303. var updateFillNode = function (el, style, zrEl) {
  61304. // TODO pattern
  61305. var fill = style.fill;
  61306. if (fill != null) {
  61307. // Modified from excanvas
  61308. if (fill instanceof Gradient) {
  61309. var gradientType;
  61310. var angle = 0;
  61311. var focus = [0, 0];
  61312. // additional offset
  61313. var shift = 0;
  61314. // scale factor for offset
  61315. var expansion = 1;
  61316. var rect = zrEl.getBoundingRect();
  61317. var rectWidth = rect.width;
  61318. var rectHeight = rect.height;
  61319. if (fill.type === 'linear') {
  61320. gradientType = 'gradient';
  61321. var transform = zrEl.transform;
  61322. var p0 = [fill.x * rectWidth, fill.y * rectHeight];
  61323. var p1 = [fill.x2 * rectWidth, fill.y2 * rectHeight];
  61324. if (transform) {
  61325. applyTransform(p0, p0, transform);
  61326. applyTransform(p1, p1, transform);
  61327. }
  61328. var dx = p1[0] - p0[0];
  61329. var dy = p1[1] - p0[1];
  61330. angle = Math.atan2(dx, dy) * 180 / Math.PI;
  61331. // The angle should be a non-negative number.
  61332. if (angle < 0) {
  61333. angle += 360;
  61334. }
  61335. // Very small angles produce an unexpected result because they are
  61336. // converted to a scientific notation string.
  61337. if (angle < 1e-6) {
  61338. angle = 0;
  61339. }
  61340. }
  61341. else {
  61342. gradientType = 'gradientradial';
  61343. var p0 = [fill.x * rectWidth, fill.y * rectHeight];
  61344. var transform = zrEl.transform;
  61345. var scale = zrEl.scale;
  61346. var width = rectWidth;
  61347. var height = rectHeight;
  61348. focus = [
  61349. // Percent in bounding rect
  61350. (p0[0] - rect.x) / width,
  61351. (p0[1] - rect.y) / height
  61352. ];
  61353. if (transform) {
  61354. applyTransform(p0, p0, transform);
  61355. }
  61356. width /= scale[0] * Z;
  61357. height /= scale[1] * Z;
  61358. var dimension = mathMax(width, height);
  61359. shift = 2 * 0 / dimension;
  61360. expansion = 2 * fill.r / dimension - shift;
  61361. }
  61362. // We need to sort the color stops in ascending order by offset,
  61363. // otherwise IE won't interpret it correctly.
  61364. var stops = fill.colorStops.slice();
  61365. stops.sort(function(cs1, cs2) {
  61366. return cs1.offset - cs2.offset;
  61367. });
  61368. var length = stops.length;
  61369. // Color and alpha list of first and last stop
  61370. var colorAndAlphaList = [];
  61371. var colors = [];
  61372. for (var i = 0; i < length; i++) {
  61373. var stop = stops[i];
  61374. var colorAndAlpha = getColorAndAlpha(stop.color);
  61375. colors.push(stop.offset * expansion + shift + ' ' + colorAndAlpha[0]);
  61376. if (i === 0 || i === length - 1) {
  61377. colorAndAlphaList.push(colorAndAlpha);
  61378. }
  61379. }
  61380. if (length >= 2) {
  61381. var color1 = colorAndAlphaList[0][0];
  61382. var color2 = colorAndAlphaList[1][0];
  61383. var opacity1 = colorAndAlphaList[0][1] * style.opacity;
  61384. var opacity2 = colorAndAlphaList[1][1] * style.opacity;
  61385. el.type = gradientType;
  61386. el.method = 'none';
  61387. el.focus = '100%';
  61388. el.angle = angle;
  61389. el.color = color1;
  61390. el.color2 = color2;
  61391. el.colors = colors.join(',');
  61392. // When colors attribute is used, the meanings of opacity and o:opacity2
  61393. // are reversed.
  61394. el.opacity = opacity2;
  61395. // FIXME g_o_:opacity ?
  61396. el.opacity2 = opacity1;
  61397. }
  61398. if (gradientType === 'radial') {
  61399. el.focusposition = focus.join(',');
  61400. }
  61401. }
  61402. else {
  61403. // FIXME Change from Gradient fill to color fill
  61404. setColorAndOpacity(el, fill, style.opacity);
  61405. }
  61406. }
  61407. };
  61408. var updateStrokeNode = function (el, style) {
  61409. // if (style.lineJoin != null) {
  61410. // el.joinstyle = style.lineJoin;
  61411. // }
  61412. // if (style.miterLimit != null) {
  61413. // el.miterlimit = style.miterLimit * Z;
  61414. // }
  61415. // if (style.lineCap != null) {
  61416. // el.endcap = style.lineCap;
  61417. // }
  61418. if (style.lineDash != null) {
  61419. el.dashstyle = style.lineDash.join(' ');
  61420. }
  61421. if (style.stroke != null && !(style.stroke instanceof Gradient)) {
  61422. setColorAndOpacity(el, style.stroke, style.opacity);
  61423. }
  61424. };
  61425. var updateFillAndStroke = function (vmlEl, type, style, zrEl) {
  61426. var isFill = type == 'fill';
  61427. var el = vmlEl.getElementsByTagName(type)[0];
  61428. // Stroke must have lineWidth
  61429. if (style[type] != null && style[type] !== 'none' && (isFill || (!isFill && style.lineWidth))) {
  61430. vmlEl[isFill ? 'filled' : 'stroked'] = 'true';
  61431. // FIXME Remove before updating, or set `colors` will throw error
  61432. if (style[type] instanceof Gradient) {
  61433. remove(vmlEl, el);
  61434. }
  61435. if (!el) {
  61436. el = vmlCore.createNode(type);
  61437. }
  61438. isFill ? updateFillNode(el, style, zrEl) : updateStrokeNode(el, style);
  61439. append(vmlEl, el);
  61440. }
  61441. else {
  61442. vmlEl[isFill ? 'filled' : 'stroked'] = 'false';
  61443. remove(vmlEl, el);
  61444. }
  61445. };
  61446. var points = [[], [], []];
  61447. var pathDataToString = function (data, m) {
  61448. var M = CMD.M;
  61449. var C = CMD.C;
  61450. var L = CMD.L;
  61451. var A = CMD.A;
  61452. var Q = CMD.Q;
  61453. var str = [];
  61454. var nPoint;
  61455. var cmdStr;
  61456. var cmd;
  61457. var i;
  61458. var xi;
  61459. var yi;
  61460. for (i = 0; i < data.length;) {
  61461. cmd = data[i++];
  61462. cmdStr = '';
  61463. nPoint = 0;
  61464. switch (cmd) {
  61465. case M:
  61466. cmdStr = ' m ';
  61467. nPoint = 1;
  61468. xi = data[i++];
  61469. yi = data[i++];
  61470. points[0][0] = xi;
  61471. points[0][1] = yi;
  61472. break;
  61473. case L:
  61474. cmdStr = ' l ';
  61475. nPoint = 1;
  61476. xi = data[i++];
  61477. yi = data[i++];
  61478. points[0][0] = xi;
  61479. points[0][1] = yi;
  61480. break;
  61481. case Q:
  61482. case C:
  61483. cmdStr = ' c ';
  61484. nPoint = 3;
  61485. var x1 = data[i++];
  61486. var y1 = data[i++];
  61487. var x2 = data[i++];
  61488. var y2 = data[i++];
  61489. var x3;
  61490. var y3;
  61491. if (cmd === Q) {
  61492. // Convert quadratic to cubic using degree elevation
  61493. x3 = x2;
  61494. y3 = y2;
  61495. x2 = (x2 + 2 * x1) / 3;
  61496. y2 = (y2 + 2 * y1) / 3;
  61497. x1 = (xi + 2 * x1) / 3;
  61498. y1 = (yi + 2 * y1) / 3;
  61499. }
  61500. else {
  61501. x3 = data[i++];
  61502. y3 = data[i++];
  61503. }
  61504. points[0][0] = x1;
  61505. points[0][1] = y1;
  61506. points[1][0] = x2;
  61507. points[1][1] = y2;
  61508. points[2][0] = x3;
  61509. points[2][1] = y3;
  61510. xi = x3;
  61511. yi = y3;
  61512. break;
  61513. case A:
  61514. var x = 0;
  61515. var y = 0;
  61516. var sx = 1;
  61517. var sy = 1;
  61518. var angle = 0;
  61519. if (m) {
  61520. // Extract SRT from matrix
  61521. x = m[4];
  61522. y = m[5];
  61523. sx = sqrt(m[0] * m[0] + m[1] * m[1]);
  61524. sy = sqrt(m[2] * m[2] + m[3] * m[3]);
  61525. angle = Math.atan2(-m[1] / sy, m[0] / sx);
  61526. }
  61527. var cx = data[i++];
  61528. var cy = data[i++];
  61529. var rx = data[i++];
  61530. var ry = data[i++];
  61531. var startAngle = data[i++] + angle;
  61532. var endAngle = data[i++] + startAngle + angle;
  61533. // FIXME
  61534. // var psi = data[i++];
  61535. i++;
  61536. var clockwise = data[i++];
  61537. var x0 = cx + cos(startAngle) * rx;
  61538. var y0 = cy + sin(startAngle) * ry;
  61539. var x1 = cx + cos(endAngle) * rx;
  61540. var y1 = cy + sin(endAngle) * ry;
  61541. var type = clockwise ? ' wa ' : ' at ';
  61542. if (Math.abs(x0 - x1) < 1e-4) {
  61543. // IE won't render arches drawn counter clockwise if x0 == x1.
  61544. if (Math.abs(endAngle - startAngle) > 1e-2) {
  61545. // Offset x0 by 1/80 of a pixel. Use something
  61546. // that can be represented in binary
  61547. if (clockwise) {
  61548. x0 += 270 / Z;
  61549. }
  61550. }
  61551. else {
  61552. // Avoid case draw full circle
  61553. if (Math.abs(y0 - cy) < 1e-4) {
  61554. if ((clockwise && x0 < cx) || (!clockwise && x0 > cx)) {
  61555. y1 -= 270 / Z;
  61556. }
  61557. else {
  61558. y1 += 270 / Z;
  61559. }
  61560. }
  61561. else if ((clockwise && y0 < cy) || (!clockwise && y0 > cy)) {
  61562. x1 += 270 / Z;
  61563. }
  61564. else {
  61565. x1 -= 270 / Z;
  61566. }
  61567. }
  61568. }
  61569. str.push(
  61570. type,
  61571. round(((cx - rx) * sx + x) * Z - Z2), comma,
  61572. round(((cy - ry) * sy + y) * Z - Z2), comma,
  61573. round(((cx + rx) * sx + x) * Z - Z2), comma,
  61574. round(((cy + ry) * sy + y) * Z - Z2), comma,
  61575. round((x0 * sx + x) * Z - Z2), comma,
  61576. round((y0 * sy + y) * Z - Z2), comma,
  61577. round((x1 * sx + x) * Z - Z2), comma,
  61578. round((y1 * sy + y) * Z - Z2)
  61579. );
  61580. xi = x1;
  61581. yi = y1;
  61582. break;
  61583. case CMD.R:
  61584. var p0 = points[0];
  61585. var p1 = points[1];
  61586. // x0, y0
  61587. p0[0] = data[i++];
  61588. p0[1] = data[i++];
  61589. // x1, y1
  61590. p1[0] = p0[0] + data[i++];
  61591. p1[1] = p0[1] + data[i++];
  61592. if (m) {
  61593. applyTransform(p0, p0, m);
  61594. applyTransform(p1, p1, m);
  61595. }
  61596. p0[0] = round(p0[0] * Z - Z2);
  61597. p1[0] = round(p1[0] * Z - Z2);
  61598. p0[1] = round(p0[1] * Z - Z2);
  61599. p1[1] = round(p1[1] * Z - Z2);
  61600. str.push(
  61601. // x0, y0
  61602. ' m ', p0[0], comma, p0[1],
  61603. // x1, y0
  61604. ' l ', p1[0], comma, p0[1],
  61605. // x1, y1
  61606. ' l ', p1[0], comma, p1[1],
  61607. // x0, y1
  61608. ' l ', p0[0], comma, p1[1]
  61609. );
  61610. break;
  61611. case CMD.Z:
  61612. // FIXME Update xi, yi
  61613. str.push(' x ');
  61614. }
  61615. if (nPoint > 0) {
  61616. str.push(cmdStr);
  61617. for (var k = 0; k < nPoint; k++) {
  61618. var p = points[k];
  61619. m && applyTransform(p, p, m);
  61620. // 不 round 会非常慢
  61621. str.push(
  61622. round(p[0] * Z - Z2), comma, round(p[1] * Z - Z2),
  61623. k < nPoint - 1 ? comma : ''
  61624. );
  61625. }
  61626. }
  61627. }
  61628. return str.join('');
  61629. };
  61630. // Rewrite the original path method
  61631. Path.prototype.brushVML = function (vmlRoot) {
  61632. var style = this.style;
  61633. var vmlEl = this._vmlEl;
  61634. if (!vmlEl) {
  61635. vmlEl = vmlCore.createNode('shape');
  61636. initRootElStyle(vmlEl);
  61637. this._vmlEl = vmlEl;
  61638. }
  61639. updateFillAndStroke(vmlEl, 'fill', style, this);
  61640. updateFillAndStroke(vmlEl, 'stroke', style, this);
  61641. var m = this.transform;
  61642. var needTransform = m != null;
  61643. var strokeEl = vmlEl.getElementsByTagName('stroke')[0];
  61644. if (strokeEl) {
  61645. var lineWidth = style.lineWidth;
  61646. // Get the line scale.
  61647. // Determinant of this.m_ means how much the area is enlarged by the
  61648. // transformation. So its square root can be used as a scale factor
  61649. // for width.
  61650. if (needTransform && !style.strokeNoScale) {
  61651. var det = m[0] * m[3] - m[1] * m[2];
  61652. lineWidth *= sqrt(abs(det));
  61653. }
  61654. strokeEl.weight = lineWidth + 'px';
  61655. }
  61656. var path = this.path || (this.path = new PathProxy());
  61657. if (this.__dirtyPath) {
  61658. path.beginPath();
  61659. this.buildPath(path, this.shape);
  61660. path.toStatic();
  61661. this.__dirtyPath = false;
  61662. }
  61663. vmlEl.path = pathDataToString(path.data, this.transform);
  61664. vmlEl.style.zIndex = getZIndex(this.zlevel, this.z, this.z2);
  61665. // Append to root
  61666. append(vmlRoot, vmlEl);
  61667. // Text
  61668. if (style.text != null) {
  61669. this.drawRectText(vmlRoot, this.getBoundingRect());
  61670. }
  61671. else {
  61672. this.removeRectText(vmlRoot);
  61673. }
  61674. };
  61675. Path.prototype.onRemove = function (vmlRoot) {
  61676. remove(vmlRoot, this._vmlEl);
  61677. this.removeRectText(vmlRoot);
  61678. };
  61679. Path.prototype.onAdd = function (vmlRoot) {
  61680. append(vmlRoot, this._vmlEl);
  61681. this.appendRectText(vmlRoot);
  61682. };
  61683. /***************************************************
  61684. * IMAGE
  61685. **************************************************/
  61686. var isImage = function (img) {
  61687. // FIXME img instanceof Image 如果 img 是一个字符串的时候,IE8 下会报错
  61688. return (typeof img === 'object') && img.tagName && img.tagName.toUpperCase() === 'IMG';
  61689. // return img instanceof Image;
  61690. };
  61691. // Rewrite the original path method
  61692. ZImage.prototype.brushVML = function (vmlRoot) {
  61693. var style = this.style;
  61694. var image = style.image;
  61695. // Image original width, height
  61696. var ow;
  61697. var oh;
  61698. if (isImage(image)) {
  61699. var src = image.src;
  61700. if (src === this._imageSrc) {
  61701. ow = this._imageWidth;
  61702. oh = this._imageHeight;
  61703. }
  61704. else {
  61705. var imageRuntimeStyle = image.runtimeStyle;
  61706. var oldRuntimeWidth = imageRuntimeStyle.width;
  61707. var oldRuntimeHeight = imageRuntimeStyle.height;
  61708. imageRuntimeStyle.width = 'auto';
  61709. imageRuntimeStyle.height = 'auto';
  61710. // get the original size
  61711. ow = image.width;
  61712. oh = image.height;
  61713. // and remove overides
  61714. imageRuntimeStyle.width = oldRuntimeWidth;
  61715. imageRuntimeStyle.height = oldRuntimeHeight;
  61716. // Caching image original width, height and src
  61717. this._imageSrc = src;
  61718. this._imageWidth = ow;
  61719. this._imageHeight = oh;
  61720. }
  61721. image = src;
  61722. }
  61723. else {
  61724. if (image === this._imageSrc) {
  61725. ow = this._imageWidth;
  61726. oh = this._imageHeight;
  61727. }
  61728. }
  61729. if (!image) {
  61730. return;
  61731. }
  61732. var x = style.x || 0;
  61733. var y = style.y || 0;
  61734. var dw = style.width;
  61735. var dh = style.height;
  61736. var sw = style.sWidth;
  61737. var sh = style.sHeight;
  61738. var sx = style.sx || 0;
  61739. var sy = style.sy || 0;
  61740. var hasCrop = sw && sh;
  61741. var vmlEl = this._vmlEl;
  61742. if (!vmlEl) {
  61743. // FIXME 使用 group 在 left, top 都不是 0 的时候就无法显示了。
  61744. // vmlEl = vmlCore.createNode('group');
  61745. vmlEl = vmlCore.doc.createElement('div');
  61746. initRootElStyle(vmlEl);
  61747. this._vmlEl = vmlEl;
  61748. }
  61749. var vmlElStyle = vmlEl.style;
  61750. var hasRotation = false;
  61751. var m;
  61752. var scaleX = 1;
  61753. var scaleY = 1;
  61754. if (this.transform) {
  61755. m = this.transform;
  61756. scaleX = sqrt(m[0] * m[0] + m[1] * m[1]);
  61757. scaleY = sqrt(m[2] * m[2] + m[3] * m[3]);
  61758. hasRotation = m[1] || m[2];
  61759. }
  61760. if (hasRotation) {
  61761. // If filters are necessary (rotation exists), create them
  61762. // filters are bog-slow, so only create them if abbsolutely necessary
  61763. // The following check doesn't account for skews (which don't exist
  61764. // in the canvas spec (yet) anyway.
  61765. // From excanvas
  61766. var p0 = [x, y];
  61767. var p1 = [x + dw, y];
  61768. var p2 = [x, y + dh];
  61769. var p3 = [x + dw, y + dh];
  61770. applyTransform(p0, p0, m);
  61771. applyTransform(p1, p1, m);
  61772. applyTransform(p2, p2, m);
  61773. applyTransform(p3, p3, m);
  61774. var maxX = mathMax(p0[0], p1[0], p2[0], p3[0]);
  61775. var maxY = mathMax(p0[1], p1[1], p2[1], p3[1]);
  61776. var transformFilter = [];
  61777. transformFilter.push('M11=', m[0] / scaleX, comma,
  61778. 'M12=', m[2] / scaleY, comma,
  61779. 'M21=', m[1] / scaleX, comma,
  61780. 'M22=', m[3] / scaleY, comma,
  61781. 'Dx=', round(x * scaleX + m[4]), comma,
  61782. 'Dy=', round(y * scaleY + m[5]));
  61783. vmlElStyle.padding = '0 ' + round(maxX) + 'px ' + round(maxY) + 'px 0';
  61784. // FIXME DXImageTransform 在 IE11 的兼容模式下不起作用
  61785. vmlElStyle.filter = imageTransformPrefix + '.Matrix('
  61786. + transformFilter.join('') + ', SizingMethod=clip)';
  61787. }
  61788. else {
  61789. if (m) {
  61790. x = x * scaleX + m[4];
  61791. y = y * scaleY + m[5];
  61792. }
  61793. vmlElStyle.filter = '';
  61794. vmlElStyle.left = round(x) + 'px';
  61795. vmlElStyle.top = round(y) + 'px';
  61796. }
  61797. var imageEl = this._imageEl;
  61798. var cropEl = this._cropEl;
  61799. if (!imageEl) {
  61800. imageEl = vmlCore.doc.createElement('div');
  61801. this._imageEl = imageEl;
  61802. }
  61803. var imageELStyle = imageEl.style;
  61804. if (hasCrop) {
  61805. // Needs know image original width and height
  61806. if (! (ow && oh)) {
  61807. var tmpImage = new Image();
  61808. var self = this;
  61809. tmpImage.onload = function () {
  61810. tmpImage.onload = null;
  61811. ow = tmpImage.width;
  61812. oh = tmpImage.height;
  61813. // Adjust image width and height to fit the ratio destinationSize / sourceSize
  61814. imageELStyle.width = round(scaleX * ow * dw / sw) + 'px';
  61815. imageELStyle.height = round(scaleY * oh * dh / sh) + 'px';
  61816. // Caching image original width, height and src
  61817. self._imageWidth = ow;
  61818. self._imageHeight = oh;
  61819. self._imageSrc = image;
  61820. };
  61821. tmpImage.src = image;
  61822. }
  61823. else {
  61824. imageELStyle.width = round(scaleX * ow * dw / sw) + 'px';
  61825. imageELStyle.height = round(scaleY * oh * dh / sh) + 'px';
  61826. }
  61827. if (! cropEl) {
  61828. cropEl = vmlCore.doc.createElement('div');
  61829. cropEl.style.overflow = 'hidden';
  61830. this._cropEl = cropEl;
  61831. }
  61832. var cropElStyle = cropEl.style;
  61833. cropElStyle.width = round((dw + sx * dw / sw) * scaleX);
  61834. cropElStyle.height = round((dh + sy * dh / sh) * scaleY);
  61835. cropElStyle.filter = imageTransformPrefix + '.Matrix(Dx='
  61836. + (-sx * dw / sw * scaleX) + ',Dy=' + (-sy * dh / sh * scaleY) + ')';
  61837. if (! cropEl.parentNode) {
  61838. vmlEl.appendChild(cropEl);
  61839. }
  61840. if (imageEl.parentNode != cropEl) {
  61841. cropEl.appendChild(imageEl);
  61842. }
  61843. }
  61844. else {
  61845. imageELStyle.width = round(scaleX * dw) + 'px';
  61846. imageELStyle.height = round(scaleY * dh) + 'px';
  61847. vmlEl.appendChild(imageEl);
  61848. if (cropEl && cropEl.parentNode) {
  61849. vmlEl.removeChild(cropEl);
  61850. this._cropEl = null;
  61851. }
  61852. }
  61853. var filterStr = '';
  61854. var alpha = style.opacity;
  61855. if (alpha < 1) {
  61856. filterStr += '.Alpha(opacity=' + round(alpha * 100) + ') ';
  61857. }
  61858. filterStr += imageTransformPrefix + '.AlphaImageLoader(src=' + image + ', SizingMethod=scale)';
  61859. imageELStyle.filter = filterStr;
  61860. vmlEl.style.zIndex = getZIndex(this.zlevel, this.z, this.z2);
  61861. // Append to root
  61862. append(vmlRoot, vmlEl);
  61863. // Text
  61864. if (style.text != null) {
  61865. this.drawRectText(vmlRoot, this.getBoundingRect());
  61866. }
  61867. };
  61868. ZImage.prototype.onRemove = function (vmlRoot) {
  61869. remove(vmlRoot, this._vmlEl);
  61870. this._vmlEl = null;
  61871. this._cropEl = null;
  61872. this._imageEl = null;
  61873. this.removeRectText(vmlRoot);
  61874. };
  61875. ZImage.prototype.onAdd = function (vmlRoot) {
  61876. append(vmlRoot, this._vmlEl);
  61877. this.appendRectText(vmlRoot);
  61878. };
  61879. /***************************************************
  61880. * TEXT
  61881. **************************************************/
  61882. var DEFAULT_STYLE_NORMAL = 'normal';
  61883. var fontStyleCache = {};
  61884. var fontStyleCacheCount = 0;
  61885. var MAX_FONT_CACHE_SIZE = 100;
  61886. var fontEl = document.createElement('div');
  61887. var getFontStyle = function (fontString) {
  61888. var fontStyle = fontStyleCache[fontString];
  61889. if (!fontStyle) {
  61890. // Clear cache
  61891. if (fontStyleCacheCount > MAX_FONT_CACHE_SIZE) {
  61892. fontStyleCacheCount = 0;
  61893. fontStyleCache = {};
  61894. }
  61895. var style = fontEl.style;
  61896. var fontFamily;
  61897. try {
  61898. style.font = fontString;
  61899. fontFamily = style.fontFamily.split(',')[0];
  61900. }
  61901. catch (e) {
  61902. }
  61903. fontStyle = {
  61904. style: style.fontStyle || DEFAULT_STYLE_NORMAL,
  61905. variant: style.fontVariant || DEFAULT_STYLE_NORMAL,
  61906. weight: style.fontWeight || DEFAULT_STYLE_NORMAL,
  61907. size: parseFloat(style.fontSize || 12) | 0,
  61908. family: fontFamily || 'Microsoft YaHei'
  61909. };
  61910. fontStyleCache[fontString] = fontStyle;
  61911. fontStyleCacheCount++;
  61912. }
  61913. return fontStyle;
  61914. };
  61915. var textMeasureEl;
  61916. // Overwrite measure text method
  61917. textContain.measureText = function (text, textFont) {
  61918. var doc = vmlCore.doc;
  61919. if (!textMeasureEl) {
  61920. textMeasureEl = doc.createElement('div');
  61921. textMeasureEl.style.cssText = 'position:absolute;top:-20000px;left:0;'
  61922. + 'padding:0;margin:0;border:none;white-space:pre;';
  61923. vmlCore.doc.body.appendChild(textMeasureEl);
  61924. }
  61925. try {
  61926. textMeasureEl.style.font = textFont;
  61927. } catch (ex) {
  61928. // Ignore failures to set to invalid font.
  61929. }
  61930. textMeasureEl.innerHTML = '';
  61931. // Don't use innerHTML or innerText because they allow markup/whitespace.
  61932. textMeasureEl.appendChild(doc.createTextNode(text));
  61933. return {
  61934. width: textMeasureEl.offsetWidth
  61935. };
  61936. };
  61937. var tmpRect = new BoundingRect();
  61938. var drawRectText = function (vmlRoot, rect, textRect, fromTextEl) {
  61939. var style = this.style;
  61940. var text = style.text;
  61941. // Convert to string
  61942. text != null && (text += '');
  61943. if (!text) {
  61944. return;
  61945. }
  61946. var x;
  61947. var y;
  61948. var align = style.textAlign;
  61949. var fontStyle = getFontStyle(style.textFont);
  61950. // FIXME encodeHtmlAttribute ?
  61951. var font = fontStyle.style + ' ' + fontStyle.variant + ' ' + fontStyle.weight + ' '
  61952. + fontStyle.size + 'px "' + fontStyle.family + '"';
  61953. var baseline = style.textBaseline;
  61954. var verticalAlign = style.textVerticalAlign;
  61955. textRect = textRect || textContain.getBoundingRect(text, font, align, baseline);
  61956. // Transform rect to view space
  61957. var m = this.transform;
  61958. // Ignore transform for text in other element
  61959. if (m && !fromTextEl) {
  61960. tmpRect.copy(rect);
  61961. tmpRect.applyTransform(m);
  61962. rect = tmpRect;
  61963. }
  61964. if (!fromTextEl) {
  61965. var textPosition = style.textPosition;
  61966. var distance = style.textDistance;
  61967. // Text position represented by coord
  61968. if (textPosition instanceof Array) {
  61969. x = rect.x + parsePercent(textPosition[0], rect.width);
  61970. y = rect.y + parsePercent(textPosition[1], rect.height);
  61971. align = align || 'left';
  61972. baseline = baseline || 'top';
  61973. }
  61974. else {
  61975. var res = textContain.adjustTextPositionOnRect(
  61976. textPosition, rect, textRect, distance
  61977. );
  61978. x = res.x;
  61979. y = res.y;
  61980. // Default align and baseline when has textPosition
  61981. align = align || res.textAlign;
  61982. baseline = baseline || res.textBaseline;
  61983. }
  61984. }
  61985. else {
  61986. x = rect.x;
  61987. y = rect.y;
  61988. }
  61989. if (verticalAlign) {
  61990. switch (verticalAlign) {
  61991. case 'middle':
  61992. y -= textRect.height / 2;
  61993. break;
  61994. case 'bottom':
  61995. y -= textRect.height;
  61996. break;
  61997. // 'top'
  61998. }
  61999. // Ignore baseline
  62000. baseline = 'top';
  62001. }
  62002. var fontSize = fontStyle.size;
  62003. // 1.75 is an arbitrary number, as there is no info about the text baseline
  62004. switch (baseline) {
  62005. case 'hanging':
  62006. case 'top':
  62007. y += fontSize / 1.75;
  62008. break;
  62009. case 'middle':
  62010. break;
  62011. default:
  62012. // case null:
  62013. // case 'alphabetic':
  62014. // case 'ideographic':
  62015. // case 'bottom':
  62016. y -= fontSize / 2.25;
  62017. break;
  62018. }
  62019. switch (align) {
  62020. case 'left':
  62021. break;
  62022. case 'center':
  62023. x -= textRect.width / 2;
  62024. break;
  62025. case 'right':
  62026. x -= textRect.width;
  62027. break;
  62028. // case 'end':
  62029. // align = elementStyle.direction == 'ltr' ? 'right' : 'left';
  62030. // break;
  62031. // case 'start':
  62032. // align = elementStyle.direction == 'rtl' ? 'right' : 'left';
  62033. // break;
  62034. // default:
  62035. // align = 'left';
  62036. }
  62037. var createNode = vmlCore.createNode;
  62038. var textVmlEl = this._textVmlEl;
  62039. var pathEl;
  62040. var textPathEl;
  62041. var skewEl;
  62042. if (!textVmlEl) {
  62043. textVmlEl = createNode('line');
  62044. pathEl = createNode('path');
  62045. textPathEl = createNode('textpath');
  62046. skewEl = createNode('skew');
  62047. // FIXME Why here is not cammel case
  62048. // Align 'center' seems wrong
  62049. textPathEl.style['v-text-align'] = 'left';
  62050. initRootElStyle(textVmlEl);
  62051. pathEl.textpathok = true;
  62052. textPathEl.on = true;
  62053. textVmlEl.from = '0 0';
  62054. textVmlEl.to = '1000 0.05';
  62055. append(textVmlEl, skewEl);
  62056. append(textVmlEl, pathEl);
  62057. append(textVmlEl, textPathEl);
  62058. this._textVmlEl = textVmlEl;
  62059. }
  62060. else {
  62061. // 这里是在前面 appendChild 保证顺序的前提下
  62062. skewEl = textVmlEl.firstChild;
  62063. pathEl = skewEl.nextSibling;
  62064. textPathEl = pathEl.nextSibling;
  62065. }
  62066. var coords = [x, y];
  62067. var textVmlElStyle = textVmlEl.style;
  62068. // Ignore transform for text in other element
  62069. if (m && fromTextEl) {
  62070. applyTransform(coords, coords, m);
  62071. skewEl.on = true;
  62072. skewEl.matrix = m[0].toFixed(3) + comma + m[2].toFixed(3) + comma +
  62073. m[1].toFixed(3) + comma + m[3].toFixed(3) + ',0,0';
  62074. // Text position
  62075. skewEl.offset = (round(coords[0]) || 0) + ',' + (round(coords[1]) || 0);
  62076. // Left top point as origin
  62077. skewEl.origin = '0 0';
  62078. textVmlElStyle.left = '0px';
  62079. textVmlElStyle.top = '0px';
  62080. }
  62081. else {
  62082. skewEl.on = false;
  62083. textVmlElStyle.left = round(x) + 'px';
  62084. textVmlElStyle.top = round(y) + 'px';
  62085. }
  62086. textPathEl.string = encodeHtmlAttribute(text);
  62087. // TODO
  62088. try {
  62089. textPathEl.style.font = font;
  62090. }
  62091. // Error font format
  62092. catch (e) {}
  62093. updateFillAndStroke(textVmlEl, 'fill', {
  62094. fill: fromTextEl ? style.fill : style.textFill,
  62095. opacity: style.opacity
  62096. }, this);
  62097. updateFillAndStroke(textVmlEl, 'stroke', {
  62098. stroke: fromTextEl ? style.stroke : style.textStroke,
  62099. opacity: style.opacity,
  62100. lineDash: style.lineDash
  62101. }, this);
  62102. textVmlEl.style.zIndex = getZIndex(this.zlevel, this.z, this.z2);
  62103. // Attached to root
  62104. append(vmlRoot, textVmlEl);
  62105. };
  62106. var removeRectText = function (vmlRoot) {
  62107. remove(vmlRoot, this._textVmlEl);
  62108. this._textVmlEl = null;
  62109. };
  62110. var appendRectText = function (vmlRoot) {
  62111. append(vmlRoot, this._textVmlEl);
  62112. };
  62113. var list = [RectText, Displayable, ZImage, Path, Text];
  62114. // In case Displayable has been mixed in RectText
  62115. for (var i = 0; i < list.length; i++) {
  62116. var proto = list[i].prototype;
  62117. proto.drawRectText = drawRectText;
  62118. proto.removeRectText = removeRectText;
  62119. proto.appendRectText = appendRectText;
  62120. }
  62121. Text.prototype.brushVML = function (vmlRoot) {
  62122. var style = this.style;
  62123. if (style.text != null) {
  62124. this.drawRectText(vmlRoot, {
  62125. x: style.x || 0, y: style.y || 0,
  62126. width: 0, height: 0
  62127. }, this.getBoundingRect(), true);
  62128. }
  62129. else {
  62130. this.removeRectText(vmlRoot);
  62131. }
  62132. };
  62133. Text.prototype.onRemove = function (vmlRoot) {
  62134. this.removeRectText(vmlRoot);
  62135. };
  62136. Text.prototype.onAdd = function (vmlRoot) {
  62137. this.appendRectText(vmlRoot);
  62138. };
  62139. }
  62140. /***/ },
  62141. /* 425 */
  62142. /***/ function(module, exports, __webpack_require__) {
  62143. if (!__webpack_require__(2).canvasSupported) {
  62144. var urn = 'urn:schemas-microsoft-com:vml';
  62145. var createNode;
  62146. var win = window;
  62147. var doc = win.document;
  62148. var vmlInited = false;
  62149. try {
  62150. !doc.namespaces.zrvml && doc.namespaces.add('zrvml', urn);
  62151. createNode = function (tagName) {
  62152. return doc.createElement('<zrvml:' + tagName + ' class="zrvml">');
  62153. };
  62154. }
  62155. catch (e) {
  62156. createNode = function (tagName) {
  62157. return doc.createElement('<' + tagName + ' xmlns="' + urn + '" class="zrvml">');
  62158. };
  62159. }
  62160. // From raphael
  62161. var initVML = function () {
  62162. if (vmlInited) {
  62163. return;
  62164. }
  62165. vmlInited = true;
  62166. var styleSheets = doc.styleSheets;
  62167. if (styleSheets.length < 31) {
  62168. doc.createStyleSheet().addRule('.zrvml', 'behavior:url(#default#VML)');
  62169. }
  62170. else {
  62171. // http://msdn.microsoft.com/en-us/library/ms531194%28VS.85%29.aspx
  62172. styleSheets[0].addRule('.zrvml', 'behavior:url(#default#VML)');
  62173. }
  62174. };
  62175. // Not useing return to avoid error when converting to CommonJS module
  62176. module.exports = {
  62177. doc: doc,
  62178. initVML: initVML,
  62179. createNode: createNode
  62180. };
  62181. }
  62182. /***/ },
  62183. /* 426 */
  62184. /***/ function(module, exports, __webpack_require__) {
  62185. /**
  62186. * VML Painter.
  62187. *
  62188. * @module zrender/vml/Painter
  62189. */
  62190. var zrLog = __webpack_require__(33);
  62191. var vmlCore = __webpack_require__(425);
  62192. function parseInt10(val) {
  62193. return parseInt(val, 10);
  62194. }
  62195. /**
  62196. * @alias module:zrender/vml/Painter
  62197. */
  62198. function VMLPainter(root, storage) {
  62199. vmlCore.initVML();
  62200. this.root = root;
  62201. this.storage = storage;
  62202. var vmlViewport = document.createElement('div');
  62203. var vmlRoot = document.createElement('div');
  62204. vmlViewport.style.cssText = 'display:inline-block;overflow:hidden;position:relative;width:300px;height:150px;';
  62205. vmlRoot.style.cssText = 'position:absolute;left:0;top:0;';
  62206. root.appendChild(vmlViewport);
  62207. this._vmlRoot = vmlRoot;
  62208. this._vmlViewport = vmlViewport;
  62209. this.resize();
  62210. // Modify storage
  62211. var oldDelFromStorage = storage.delFromStorage;
  62212. var oldAddToStorage = storage.addToStorage;
  62213. storage.delFromStorage = function (el) {
  62214. oldDelFromStorage.call(storage, el);
  62215. if (el) {
  62216. el.onRemove && el.onRemove(vmlRoot);
  62217. }
  62218. };
  62219. storage.addToStorage = function (el) {
  62220. // Displayable already has a vml node
  62221. el.onAdd && el.onAdd(vmlRoot);
  62222. oldAddToStorage.call(storage, el);
  62223. };
  62224. this._firstPaint = true;
  62225. }
  62226. VMLPainter.prototype = {
  62227. constructor: VMLPainter,
  62228. /**
  62229. * @return {HTMLDivElement}
  62230. */
  62231. getViewportRoot: function () {
  62232. return this._vmlViewport;
  62233. },
  62234. /**
  62235. * 刷新
  62236. */
  62237. refresh: function () {
  62238. var list = this.storage.getDisplayList(true, true);
  62239. this._paintList(list);
  62240. },
  62241. _paintList: function (list) {
  62242. var vmlRoot = this._vmlRoot;
  62243. for (var i = 0; i < list.length; i++) {
  62244. var el = list[i];
  62245. if (el.invisible || el.ignore) {
  62246. if (!el.__alreadyNotVisible) {
  62247. el.onRemove(vmlRoot);
  62248. }
  62249. // Set as already invisible
  62250. el.__alreadyNotVisible = true;
  62251. }
  62252. else {
  62253. if (el.__alreadyNotVisible) {
  62254. el.onAdd(vmlRoot);
  62255. }
  62256. el.__alreadyNotVisible = false;
  62257. if (el.__dirty) {
  62258. el.beforeBrush && el.beforeBrush();
  62259. (el.brushVML || el.brush).call(el, vmlRoot);
  62260. el.afterBrush && el.afterBrush();
  62261. }
  62262. }
  62263. el.__dirty = false;
  62264. }
  62265. if (this._firstPaint) {
  62266. // Detached from document at first time
  62267. // to avoid page refreshing too many times
  62268. // FIXME 如果每次都先 removeChild 可能会导致一些填充和描边的效果改变
  62269. this._vmlViewport.appendChild(vmlRoot);
  62270. this._firstPaint = false;
  62271. }
  62272. },
  62273. resize: function (width, height) {
  62274. var width = width == null ? this._getWidth() : width;
  62275. var height = height == null ? this._getHeight() : height;
  62276. if (this._width != width || this._height != height) {
  62277. this._width = width;
  62278. this._height = height;
  62279. var vmlViewportStyle = this._vmlViewport.style;
  62280. vmlViewportStyle.width = width + 'px';
  62281. vmlViewportStyle.height = height + 'px';
  62282. }
  62283. },
  62284. dispose: function () {
  62285. this.root.innerHTML = '';
  62286. this._vmlRoot =
  62287. this._vmlViewport =
  62288. this.storage = null;
  62289. },
  62290. getWidth: function () {
  62291. return this._width;
  62292. },
  62293. getHeight: function () {
  62294. return this._height;
  62295. },
  62296. clear: function () {
  62297. if (this._vmlViewport) {
  62298. this.root.removeChild(this._vmlViewport);
  62299. }
  62300. },
  62301. _getWidth: function () {
  62302. var root = this.root;
  62303. var stl = root.currentStyle;
  62304. return ((root.clientWidth || parseInt10(stl.width))
  62305. - parseInt10(stl.paddingLeft)
  62306. - parseInt10(stl.paddingRight)) | 0;
  62307. },
  62308. _getHeight: function () {
  62309. var root = this.root;
  62310. var stl = root.currentStyle;
  62311. return ((root.clientHeight || parseInt10(stl.height))
  62312. - parseInt10(stl.paddingTop)
  62313. - parseInt10(stl.paddingBottom)) | 0;
  62314. }
  62315. };
  62316. // Not supported methods
  62317. function createMethodNotSupport(method) {
  62318. return function () {
  62319. zrLog('In IE8.0 VML mode painter not support method "' + method + '"');
  62320. };
  62321. }
  62322. var notSupportedMethods = [
  62323. 'getLayer', 'insertLayer', 'eachLayer', 'eachBuiltinLayer', 'eachOtherLayer', 'getLayers',
  62324. 'modLayer', 'delLayer', 'clearLayer', 'toDataURL', 'pathToImage'
  62325. ];
  62326. for (var i = 0; i < notSupportedMethods.length; i++) {
  62327. var name = notSupportedMethods[i];
  62328. VMLPainter.prototype[name] = createMethodNotSupport(name);
  62329. }
  62330. module.exports = VMLPainter;
  62331. /***/ }
  62332. /******/ ])
  62333. });
  62334. ;