echarts 4.5.0 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/dist/echarts-en.common.js +1790 -774
  2. package/dist/echarts-en.common.min.js +1 -1
  3. package/dist/echarts-en.js +2029 -849
  4. package/dist/echarts-en.js.map +1 -1
  5. package/dist/echarts-en.min.js +1 -1
  6. package/dist/echarts-en.simple.js +1676 -691
  7. package/dist/echarts-en.simple.min.js +1 -1
  8. package/dist/echarts.common.js +1790 -774
  9. package/dist/echarts.common.min.js +1 -1
  10. package/dist/echarts.js +2029 -849
  11. package/dist/echarts.js.map +1 -1
  12. package/dist/echarts.min.js +1 -1
  13. package/dist/echarts.simple.js +1676 -691
  14. package/dist/echarts.simple.min.js +1 -1
  15. package/lib/chart/bar/BarView.js +11 -1
  16. package/lib/chart/bar/BaseBarSeries.js +3 -1
  17. package/lib/chart/effectScatter/EffectScatterSeries.js +3 -1
  18. package/lib/chart/funnel/FunnelSeries.js +15 -5
  19. package/lib/chart/gauge/GaugeSeries.js +0 -2
  20. package/lib/chart/graph/GraphSeries.js +9 -4
  21. package/lib/chart/graph/GraphView.js +28 -8
  22. package/lib/chart/heatmap/HeatmapView.js +4 -4
  23. package/lib/chart/helper/createListFromArray.js +14 -8
  24. package/lib/chart/helper/whiskerBoxCommon.js +22 -16
  25. package/lib/chart/line/LineSeries.js +3 -1
  26. package/lib/chart/line/LineView.js +8 -2
  27. package/lib/chart/map/MapSeries.js +8 -1
  28. package/lib/chart/pie/PieSeries.js +27 -6
  29. package/lib/chart/pie/PieView.js +1 -1
  30. package/lib/chart/pie/labelLayout.js +102 -19
  31. package/lib/chart/pie/pieLayout.js +19 -7
  32. package/lib/chart/radar/RadarSeries.js +3 -3
  33. package/lib/chart/sankey/SankeyView.js +28 -9
  34. package/lib/chart/scatter/ScatterSeries.js +3 -1
  35. package/lib/chart/themeRiver/ThemeRiverSeries.js +3 -3
  36. package/lib/chart/tree/TreeSeries.js +15 -1
  37. package/lib/component/axis/AngleAxisView.js +64 -7
  38. package/lib/component/axis/AxisBuilder.js +63 -24
  39. package/lib/component/axis/CartesianAxisView.js +55 -11
  40. package/lib/component/axis/RadiusAxisView.js +36 -4
  41. package/lib/component/dataZoom/SliderZoomView.js +4 -10
  42. package/lib/component/helper/BrushController.js +33 -43
  43. package/lib/component/legend/LegendModel.js +3 -3
  44. package/lib/component/legend/LegendView.js +17 -13
  45. package/lib/component/toolbox/ToolboxView.js +5 -1
  46. package/lib/component/toolbox/feature/MagicType.js +19 -14
  47. package/lib/coord/Axis.js +30 -2
  48. package/lib/coord/axisDefault.js +21 -2
  49. package/lib/data/DataDimensionInfo.js +157 -0
  50. package/lib/data/List.js +25 -19
  51. package/lib/data/Tree.js +2 -1
  52. package/lib/data/helper/completeDimensions.js +43 -32
  53. package/lib/data/helper/createDimensions.js +2 -0
  54. package/lib/data/helper/sourceHelper.js +214 -114
  55. package/lib/echarts.js +2 -2
  56. package/lib/layout/barGrid.js +2 -3
  57. package/lib/model/Series.js +3 -3
  58. package/lib/model/referHelper.js +40 -12
  59. package/lib/scale/Interval.js +87 -2
  60. package/lib/scale/Log.js +9 -2
  61. package/lib/scale/helper.js +1 -43
  62. package/lib/theme/dark.js +3 -0
  63. package/lib/util/graphic.js +1 -2
  64. package/lib/visual/LegendVisualProvider.js +75 -0
  65. package/lib/visual/dataColor.js +2 -12
  66. package/lib/visual/seriesColor.js +15 -7
  67. package/map/json/province/tianjin.json +1 -1
  68. package/package.json +3 -2
  69. package/src/chart/bar/BarView.js +12 -2
  70. package/src/chart/bar/BaseBarSeries.js +1 -1
  71. package/src/chart/effectScatter/EffectScatterSeries.js +1 -1
  72. package/src/chart/funnel/FunnelSeries.js +11 -4
  73. package/src/chart/gauge/GaugeSeries.js +0 -1
  74. package/src/chart/graph/GraphSeries.js +8 -3
  75. package/src/chart/graph/GraphView.js +26 -8
  76. package/src/chart/heatmap/HeatmapView.js +4 -4
  77. package/src/chart/helper/createListFromArray.js +13 -8
  78. package/src/chart/helper/whiskerBoxCommon.js +21 -16
  79. package/src/chart/line/LineSeries.js +1 -1
  80. package/src/chart/line/LineView.js +6 -1
  81. package/src/chart/map/MapSeries.js +5 -1
  82. package/src/chart/pie/PieSeries.js +26 -5
  83. package/src/chart/pie/PieView.js +1 -1
  84. package/src/chart/pie/labelLayout.js +114 -22
  85. package/src/chart/pie/pieLayout.js +20 -7
  86. package/src/chart/radar/RadarSeries.js +5 -3
  87. package/src/chart/sankey/SankeyView.js +26 -9
  88. package/src/chart/scatter/ScatterSeries.js +1 -1
  89. package/src/chart/themeRiver/ThemeRiverSeries.js +4 -3
  90. package/src/chart/tree/TreeSeries.js +12 -1
  91. package/src/component/axis/AngleAxisView.js +75 -7
  92. package/src/component/axis/AxisBuilder.js +78 -33
  93. package/src/component/axis/CartesianAxisView.js +58 -11
  94. package/src/component/axis/RadiusAxisView.js +37 -4
  95. package/src/component/dataZoom/SliderZoomView.js +4 -9
  96. package/src/component/helper/BrushController.js +40 -47
  97. package/src/component/legend/LegendModel.js +3 -3
  98. package/src/component/legend/LegendView.js +18 -12
  99. package/src/component/toolbox/ToolboxView.js +5 -0
  100. package/src/component/toolbox/feature/MagicType.js +18 -13
  101. package/src/coord/Axis.js +29 -2
  102. package/src/coord/axisDefault.js +25 -1
  103. package/src/data/DataDimensionInfo.js +135 -0
  104. package/src/data/List.js +29 -16
  105. package/src/data/Tree.js +3 -1
  106. package/src/data/helper/completeDimensions.js +49 -30
  107. package/src/data/helper/createDimensions.js +2 -0
  108. package/src/data/helper/sourceHelper.js +216 -124
  109. package/src/echarts.js +2 -2
  110. package/src/layout/barGrid.js +6 -3
  111. package/src/model/Series.js +3 -3
  112. package/src/model/referHelper.js +34 -11
  113. package/src/scale/Interval.js +84 -4
  114. package/src/scale/Log.js +9 -2
  115. package/src/scale/helper.js +1 -39
  116. package/src/theme/dark.js +3 -0
  117. package/src/util/graphic.js +1 -2
  118. package/src/visual/LegendVisualProvider.js +55 -0
  119. package/src/visual/dataColor.js +0 -13
  120. package/src/visual/seriesColor.js +13 -7
  121. package/theme/azul.js +163 -0
  122. package/theme/bee-inspired.js +178 -0
  123. package/theme/blue.js +178 -0
  124. package/theme/caravan.js +178 -0
  125. package/theme/carp.js +163 -0
  126. package/theme/cool.js +180 -0
  127. package/theme/dark-blue.js +168 -0
  128. package/theme/dark-bold.js +168 -0
  129. package/theme/dark-digerati.js +168 -0
  130. package/theme/dark-fresh-cut.js +168 -0
  131. package/theme/dark-mushroom.js +168 -0
  132. package/theme/dark.js +69 -62
  133. package/theme/eduardo.js +178 -0
  134. package/theme/forest.js +163 -0
  135. package/theme/fresh-cut.js +163 -0
  136. package/theme/fruit.js +178 -0
  137. package/theme/gray.js +220 -0
  138. package/theme/green.js +222 -0
  139. package/theme/helianthus.js +263 -0
  140. package/theme/infographic.js +72 -57
  141. package/theme/inspired.js +163 -0
  142. package/theme/jazz.js +163 -0
  143. package/theme/london.js +163 -0
  144. package/theme/macarons.js +80 -57
  145. package/theme/macarons2.js +251 -0
  146. package/theme/mint.js +155 -0
  147. package/theme/red-velvet.js +163 -0
  148. package/theme/red.js +225 -0
  149. package/theme/roma.js +55 -22
  150. package/theme/royal.js +163 -0
  151. package/theme/sakura.js +140 -0
  152. package/theme/shine.js +52 -45
  153. package/theme/tech-blue.js +180 -0
  154. package/theme/vintage.js +37 -23
@@ -208,12 +208,17 @@ function detect(ua) {
208
208
  // default, so we dont check navigator.maxTouchPoints for them here.
209
209
  touchEventsSupported: 'ontouchstart' in window && !browser.ie && !browser.edge,
210
210
  // <http://caniuse.com/#search=pointer%20event>.
211
- pointerEventsSupported: 'onpointerdown' in window
212
- // Firefox supports pointer but not by default, only MS browsers are reliable on pointer
211
+ pointerEventsSupported:
212
+ // (1) Firefox supports pointer but not by default, only MS browsers are reliable on pointer
213
213
  // events currently. So we dont use that on other browsers unless tested sufficiently.
214
- // Although IE 10 supports pointer event, it use old style and is different from the
214
+ // For example, in iOS 13 Mobile Chromium 78, if the touching behavior starts page
215
+ // scroll, the `pointermove` event can not be fired any more. That will break some
216
+ // features like "pan horizontally to move something and pan vertically to page scroll".
217
+ // The horizontal pan probably be interrupted by the casually triggered page scroll.
218
+ // (2) Although IE 10 supports pointer event, it use old style and is different from the
215
219
  // standard. So we exclude that. (IE 10 is hardly used on touch device)
216
- && (browser.edge || (browser.ie && browser.version >= 11)),
220
+ 'onpointerdown' in window
221
+ && (browser.edge || (browser.ie && browser.version >= 11)),
217
222
  // passiveSupported: detectPassiveSupport()
218
223
  domSupported: typeof document !== 'undefined'
219
224
  };
@@ -1262,7 +1267,11 @@ function Draggable() {
1262
1267
  this.on('mousedown', this._dragStart, this);
1263
1268
  this.on('mousemove', this._drag, this);
1264
1269
  this.on('mouseup', this._dragEnd, this);
1265
- this.on('globalout', this._dragEnd, this);
1270
+ // `mosuemove` and `mouseup` can be continue to fire when dragging.
1271
+ // See [Drag outside] in `Handler.js`. So we do not need to trigger
1272
+ // `_dragEnd` when globalout. That would brings better user experience.
1273
+ // this.on('globalout', this._dragEnd, this);
1274
+
1266
1275
  // this._dropTarget = null;
1267
1276
  // this._draggingTarget = null;
1268
1277
 
@@ -1363,7 +1372,7 @@ var arrySlice = Array.prototype.slice;
1363
1372
  * param: {string} eventType
1364
1373
  * param: {string|Object} query
1365
1374
  * return: {boolean}
1366
- * @param {Function} [eventProcessor.afterTrigger] Call after all handlers called.
1375
+ * @param {Function} [eventProcessor.afterTrigger] Called after all handlers called.
1367
1376
  * param: {string} eventType
1368
1377
  */
1369
1378
  var Eventful = function (eventProcessor) {
@@ -1413,8 +1422,10 @@ Eventful.prototype = {
1413
1422
  /**
1414
1423
  * Unbind a event.
1415
1424
  *
1416
- * @param {string} event The event name.
1425
+ * @param {string} [event] The event name.
1426
+ * If no `event` input, "off" all listeners.
1417
1427
  * @param {Function} [handler] The event handler.
1428
+ * If no `handler` input, "off" all listeners of the `event`.
1418
1429
  */
1419
1430
  off: function (event, handler) {
1420
1431
  var _h = this._$handlers;
@@ -1572,6 +1583,7 @@ Eventful.prototype = {
1572
1583
  }
1573
1584
  };
1574
1585
 
1586
+
1575
1587
  function normalizeQuery(host, query) {
1576
1588
  var eventProcessor = host._$eventProcessor;
1577
1589
  if (query != null && eventProcessor && eventProcessor.normalizeQuery) {
@@ -1889,6 +1901,18 @@ function preparePointerTransformer(markers, saved) {
1889
1901
  );
1890
1902
  }
1891
1903
 
1904
+ /**
1905
+ * Find native event compat for legency IE.
1906
+ * Should be called at the begining of a native event listener.
1907
+ *
1908
+ * @param {Event} [e] Mouse event or touch event or pointer event.
1909
+ * For lagency IE, we use `window.event` is used.
1910
+ * @return {Event} The native event.
1911
+ */
1912
+ function getNativeEvent(e) {
1913
+ return e || window.event;
1914
+ }
1915
+
1892
1916
  /**
1893
1917
  * Normalize the coordinates of the input event.
1894
1918
  *
@@ -1903,14 +1927,14 @@ function preparePointerTransformer(markers, saved) {
1903
1927
  * between the result coords and the parameters `el` and `calculate`.
1904
1928
  *
1905
1929
  * @param {HTMLElement} el DOM element.
1906
- * @param {Event} [e] Mouse event or touch event. For lagency IE,
1907
- * do not need to input it and `window.event` is used.
1930
+ * @param {Event} [e] See `getNativeEvent`.
1908
1931
  * @param {boolean} [calculate=false] Whether to force calculate
1909
1932
  * the coordinates but not use ones provided by browser.
1933
+ * @return {UIEvent} The normalized native UIEvent.
1910
1934
  */
1911
1935
  function normalizeEvent(el, e, calculate) {
1912
1936
 
1913
- e = e || window.event;
1937
+ e = getNativeEvent(e);
1914
1938
 
1915
1939
  if (e.zrX != null) {
1916
1940
  return e;
@@ -1950,8 +1974,11 @@ function normalizeEvent(el, e, calculate) {
1950
1974
  * @param {HTMLElement} el
1951
1975
  * @param {string} name
1952
1976
  * @param {Function} handler
1977
+ * @param {Object|boolean} opt If boolean, means `opt.capture`
1978
+ * @param {boolean} [opt.capture=false]
1979
+ * @param {boolean} [opt.passive=false]
1953
1980
  */
1954
- function addEventListener(el, name, handler) {
1981
+ function addEventListener(el, name, handler, opt) {
1955
1982
  if (isDomLevel2) {
1956
1983
  // Reproduct the console warning:
1957
1984
  // [Violation] Added non-passive event listener to a scroll-blocking <some> event.
@@ -1974,16 +2001,24 @@ function addEventListener(el, name, handler) {
1974
2001
  // // By default, the third param of el.addEventListener is `capture: false`.
1975
2002
  // : void 0;
1976
2003
  // el.addEventListener(name, handler /* , opts */);
1977
- el.addEventListener(name, handler);
2004
+ el.addEventListener(name, handler, opt);
1978
2005
  }
1979
2006
  else {
2007
+ // For simplicity, do not implement `setCapture` for IE9-.
1980
2008
  el.attachEvent('on' + name, handler);
1981
2009
  }
1982
2010
  }
1983
2011
 
1984
- function removeEventListener(el, name, handler) {
2012
+ /**
2013
+ * Parameter are the same as `addEventListener`.
2014
+ *
2015
+ * Notice that if a listener is registered twice, one with capture and one without,
2016
+ * remove each one separately. Removal of a capturing listener does not affect a
2017
+ * non-capturing version of the same listener, and vice versa.
2018
+ */
2019
+ function removeEventListener(el, name, handler, opt) {
1985
2020
  if (isDomLevel2) {
1986
- el.removeEventListener(name, handler);
2021
+ el.removeEventListener(name, handler, opt);
1987
2022
  }
1988
2023
  else {
1989
2024
  el.detachEvent('on' + name, handler);
@@ -2138,6 +2173,65 @@ var recognizers = {
2138
2173
  // Only pinch currently.
2139
2174
  };
2140
2175
 
2176
+ /**
2177
+ * [The interface between `Handler` and `HandlerProxy`]:
2178
+ *
2179
+ * The default `HandlerProxy` only support the common standard web environment
2180
+ * (e.g., standalone browser, headless browser, embed browser in mobild APP, ...).
2181
+ * But `HandlerProxy` can be replaced to support more non-standard environment
2182
+ * (e.g., mini app), or to support more feature that the default `HandlerProxy`
2183
+ * not provided (like echarts-gl did).
2184
+ * So the interface between `Handler` and `HandlerProxy` should be stable. Do not
2185
+ * make break changes util inevitable. The interface include the public methods
2186
+ * of `Handler` and the events listed in `handlerNames` below, by which `HandlerProxy`
2187
+ * drives `Handler`.
2188
+ */
2189
+
2190
+ /**
2191
+ * [Drag outside]:
2192
+ *
2193
+ * That is, triggering `mousemove` and `mouseup` event when the pointer is out of the
2194
+ * zrender area when dragging. That is important for the improvement of the user experience
2195
+ * when dragging something near the boundary without being terminated unexpectedly.
2196
+ *
2197
+ * We originally consider to introduce new events like `pagemovemove` and `pagemouseup`
2198
+ * to resolve this issue. But some drawbacks of it is described in
2199
+ * https://github.com/ecomfe/zrender/pull/536#issuecomment-560286899
2200
+ *
2201
+ * Instead, we referenced the specifications:
2202
+ * https://www.w3.org/TR/touch-events/#the-touchmove-event
2203
+ * https://www.w3.org/TR/2014/WD-DOM-Level-3-Events-20140925/#event-type-mousemove
2204
+ * where the the mousemove/touchmove can be continue to fire if the user began a drag
2205
+ * operation and the pointer has left the boundary. (for the mouse event, browsers
2206
+ * only do it on `document` and when the pointer has left the boundary of the browser.)
2207
+ *
2208
+ * So the default `HandlerProxy` supports this feature similarly: if it is in the dragging
2209
+ * state (see `pointerCapture` in `HandlerProxy`), the `mousemove` and `mouseup` continue
2210
+ * to fire until release the pointer. That is implemented by listen to those event on
2211
+ * `document`.
2212
+ * If we implement some other `HandlerProxy` only for touch device, that would be easier.
2213
+ * The touch event support this feature by default.
2214
+ *
2215
+ * Note:
2216
+ * There might be some cases that the mouse event can not be
2217
+ * received on `document`. For example,
2218
+ * (A) `useCapture` is not supported and some user defined event listeners on the ancestor
2219
+ * of zr dom throw Error .
2220
+ * (B) `useCapture` is not supported Some user defined event listeners on the ancestor of
2221
+ * zr dom call `stopPropagation`.
2222
+ * In these cases, the `mousemove` event might be keep triggered event
2223
+ * if the mouse is released. We try to reduce the side-effect in those cases.
2224
+ * That is, do nothing (especially, `findHover`) in those cases. See `isOutsideBoundary`.
2225
+ *
2226
+ * Note:
2227
+ * If `HandlerProxy` listens to `document` with `useCapture`, `HandlerProxy` needs to
2228
+ * make sure `stopPropagation` and `preventDefault` doing nothing if and only if the event
2229
+ * target is not zrender dom. Becuase it is dangerous to enable users to call them in
2230
+ * `document` capture phase to prevent the propagation to any listener of the webpage.
2231
+ * But they are needed to work when the pointer inside the zrender dom.
2232
+ */
2233
+
2234
+
2141
2235
  var SILENT = 'silent';
2142
2236
 
2143
2237
  function makeEventPacket(eveType, targetInfo, event) {
@@ -2162,17 +2256,19 @@ function makeEventPacket(eveType, targetInfo, event) {
2162
2256
  };
2163
2257
  }
2164
2258
 
2165
- function stopEvent(event) {
2259
+ function stopEvent() {
2166
2260
  stop(this.event);
2167
2261
  }
2168
2262
 
2169
2263
  function EmptyProxy() {}
2170
2264
  EmptyProxy.prototype.dispose = function () {};
2171
2265
 
2266
+
2172
2267
  var handlerNames = [
2173
2268
  'click', 'dblclick', 'mousewheel', 'mouseout',
2174
2269
  'mouseup', 'mousedown', 'mousemove', 'contextmenu'
2175
2270
  ];
2271
+
2176
2272
  /**
2177
2273
  * @alias module:zrender/Handler
2178
2274
  * @constructor
@@ -2229,7 +2325,6 @@ var Handler = function (storage, painter, proxy, painterRoot) {
2229
2325
  */
2230
2326
  this._gestureMgr;
2231
2327
 
2232
-
2233
2328
  Draggable.call(this);
2234
2329
 
2235
2330
  this.setHandlerProxy(proxy);
@@ -2258,6 +2353,8 @@ Handler.prototype = {
2258
2353
  var x = event.zrX;
2259
2354
  var y = event.zrY;
2260
2355
 
2356
+ var isOutside = isOutsideBoundary(this, x, y);
2357
+
2261
2358
  var lastHovered = this._hovered;
2262
2359
  var lastHoveredTarget = lastHovered.target;
2263
2360
 
@@ -2270,7 +2367,7 @@ Handler.prototype = {
2270
2367
  lastHoveredTarget = lastHovered.target;
2271
2368
  }
2272
2369
 
2273
- var hovered = this._hovered = this.findHover(x, y);
2370
+ var hovered = this._hovered = isOutside ? {x: x, y: y} : this.findHover(x, y);
2274
2371
  var hoveredTarget = hovered.target;
2275
2372
 
2276
2373
  var proxy = this.proxy;
@@ -2291,23 +2388,18 @@ Handler.prototype = {
2291
2388
  },
2292
2389
 
2293
2390
  mouseout: function (event) {
2294
- this.dispatchToElement(this._hovered, 'mouseout', event);
2391
+ var eventControl = event.zrEventControl;
2392
+ var zrIsToLocalDOM = event.zrIsToLocalDOM;
2295
2393
 
2296
- // There might be some doms created by upper layer application
2297
- // at the same level of painter.getViewportRoot() (e.g., tooltip
2298
- // dom created by echarts), where 'globalout' event should not
2299
- // be triggered when mouse enters these doms. (But 'mouseout'
2300
- // should be triggered at the original hovered element as usual).
2301
- var element = event.toElement || event.relatedTarget;
2302
- var innerDom;
2303
- do {
2304
- element = element && element.parentNode;
2394
+ if (eventControl !== 'only_globalout') {
2395
+ this.dispatchToElement(this._hovered, 'mouseout', event);
2305
2396
  }
2306
- while (element && element.nodeType !== 9 && !(
2307
- innerDom = element === this.painterRoot
2308
- ));
2309
2397
 
2310
- !innerDom && this.trigger('globalout', {event: event});
2398
+ if (eventControl !== 'no_globalout') {
2399
+ // FIXME: if the pointer moving from the extra doms to realy "outside",
2400
+ // the `globalout` should have been triggered. But currently not.
2401
+ !zrIsToLocalDOM && this.trigger('globalout', {type: 'globalout', event: event});
2402
+ }
2311
2403
  },
2312
2404
 
2313
2405
  /**
@@ -2453,9 +2545,18 @@ Handler.prototype = {
2453
2545
  // Common handlers
2454
2546
  each$1(['click', 'mousedown', 'mouseup', 'mousewheel', 'dblclick', 'contextmenu'], function (name) {
2455
2547
  Handler.prototype[name] = function (event) {
2456
- // Find hover again to avoid click event is dispatched manually. Or click is triggered without mouseover
2457
- var hovered = this.findHover(event.zrX, event.zrY);
2458
- var hoveredTarget = hovered.target;
2548
+ var x = event.zrX;
2549
+ var y = event.zrY;
2550
+ var isOutside = isOutsideBoundary(this, x, y);
2551
+
2552
+ var hovered;
2553
+ var hoveredTarget;
2554
+
2555
+ if (name !== 'mouseup' || !isOutside) {
2556
+ // Find hover again to avoid click event is dispatched manually. Or click is triggered without mouseover
2557
+ hovered = this.findHover(x, y);
2558
+ hoveredTarget = hovered.target;
2559
+ }
2459
2560
 
2460
2561
  if (name === 'mousedown') {
2461
2562
  this._downEl = hoveredTarget;
@@ -2507,6 +2608,14 @@ function isHover(displayable, x, y) {
2507
2608
  return false;
2508
2609
  }
2509
2610
 
2611
+ /**
2612
+ * See [Drag outside].
2613
+ */
2614
+ function isOutsideBoundary(handlerInstance, x, y) {
2615
+ var painter = handlerInstance.painter;
2616
+ return x < 0 || x > painter.getWidth() || y < 0 || y > painter.getHeight();
2617
+ }
2618
+
2510
2619
  mixin(Handler, Eventful);
2511
2620
  mixin(Handler, Draggable);
2512
2621
 
@@ -10810,30 +10919,55 @@ Animation.prototype = {
10810
10919
 
10811
10920
  mixin(Animation, Eventful);
10812
10921
 
10922
+ /* global document */
10923
+
10813
10924
  var TOUCH_CLICK_DELAY = 300;
10814
10925
 
10815
- var mouseHandlerNames = [
10816
- 'click', 'dblclick', 'mousewheel', 'mouseout',
10817
- 'mouseup', 'mousedown', 'mousemove', 'contextmenu'
10818
- ];
10926
+ var globalEventSupported = env$1.domSupported;
10819
10927
 
10820
- var touchHandlerNames = [
10821
- 'touchstart', 'touchend', 'touchmove'
10822
- ];
10823
10928
 
10824
- var pointerEventNames = {
10825
- pointerdown: 1, pointerup: 1, pointermove: 1, pointerout: 1
10929
+ var localNativeListenerNames = (function () {
10930
+ var mouseHandlerNames = [
10931
+ 'click', 'dblclick', 'mousewheel', 'mouseout',
10932
+ 'mouseup', 'mousedown', 'mousemove', 'contextmenu'
10933
+ ];
10934
+ var touchHandlerNames = [
10935
+ 'touchstart', 'touchend', 'touchmove'
10936
+ ];
10937
+ var pointerEventNameMap = {
10938
+ pointerdown: 1, pointerup: 1, pointermove: 1, pointerout: 1
10939
+ };
10940
+ var pointerHandlerNames = map(mouseHandlerNames, function (name) {
10941
+ var nm = name.replace('mouse', 'pointer');
10942
+ return pointerEventNameMap.hasOwnProperty(nm) ? nm : name;
10943
+ });
10944
+
10945
+ return {
10946
+ mouse: mouseHandlerNames,
10947
+ touch: touchHandlerNames,
10948
+ pointer: pointerHandlerNames
10949
+ };
10950
+ })();
10951
+
10952
+ var globalNativeListenerNames = {
10953
+ mouse: ['mousemove', 'mouseup'],
10954
+ pointer: ['pointermove', 'pointerup']
10826
10955
  };
10827
10956
 
10828
- var pointerHandlerNames = map(mouseHandlerNames, function (name) {
10829
- var nm = name.replace('mouse', 'pointer');
10830
- return pointerEventNames[nm] ? nm : name;
10831
- });
10832
10957
 
10833
10958
  function eventNameFix(name) {
10834
10959
  return (name === 'mousewheel' && env$1.browser.firefox) ? 'DOMMouseScroll' : name;
10835
10960
  }
10836
10961
 
10962
+ function isPointerFromTouch(event) {
10963
+ var pointerType = event.pointerType;
10964
+ return pointerType === 'pen' || pointerType === 'touch';
10965
+ }
10966
+
10967
+ // function useMSGuesture(handlerProxy, event) {
10968
+ // return isPointerFromTouch(event) && !!handlerProxy._msGesture;
10969
+ // }
10970
+
10837
10971
  // function onMSGestureChange(proxy, event) {
10838
10972
  // if (event.translationX || event.translationY) {
10839
10973
  // // mousemove is carried by MSGesture to reduce the sensitivity.
@@ -10853,117 +10987,174 @@ function eventNameFix(name) {
10853
10987
  * 1. Mobile browsers dispatch mouse events 300ms after touchend.
10854
10988
  * 2. Chrome for Android dispatch mousedown for long-touch about 650ms
10855
10989
  * Result: Blocking Mouse Events for 700ms.
10990
+ *
10991
+ * @param {DOMHandlerScope} scope
10856
10992
  */
10857
- function setTouchTimer(instance) {
10858
- instance._touching = true;
10859
- clearTimeout(instance._touchTimer);
10860
- instance._touchTimer = setTimeout(function () {
10861
- instance._touching = false;
10993
+ function setTouchTimer(scope) {
10994
+ scope.touching = true;
10995
+ if (scope.touchTimer != null) {
10996
+ clearTimeout(scope.touchTimer);
10997
+ scope.touchTimer = null;
10998
+ }
10999
+ scope.touchTimer = setTimeout(function () {
11000
+ scope.touching = false;
11001
+ scope.touchTimer = null;
10862
11002
  }, 700);
10863
11003
  }
10864
11004
 
11005
+ // Mark touch, which is useful in distinguish touch and
11006
+ // mouse event in upper applicatoin.
11007
+ function markTouch(event) {
11008
+ event && (event.zrByTouch = true);
11009
+ }
11010
+
11011
+
11012
+ // function markTriggeredFromLocal(event) {
11013
+ // event && (event.__zrIsFromLocal = true);
11014
+ // }
11015
+
11016
+ // function isTriggeredFromLocal(instance, event) {
11017
+ // return !!(event && event.__zrIsFromLocal);
11018
+ // }
11019
+
11020
+ function normalizeGlobalEvent(instance, event) {
11021
+ // offsetX, offsetY still need to be calculated. They are necessary in the event
11022
+ // handlers of the upper applications. Set `true` to force calculate them.
11023
+ return normalizeEvent(instance.dom, new FakeGlobalEvent(instance, event), true);
11024
+ }
11025
+
11026
+ /**
11027
+ * Detect whether the given el is in `painterRoot`.
11028
+ */
11029
+ function isLocalEl(instance, el) {
11030
+ var isLocal = false;
11031
+ do {
11032
+ el = el && el.parentNode;
11033
+ }
11034
+ while (el && el.nodeType !== 9 && !(
11035
+ isLocal = el === instance.painterRoot
11036
+ ));
11037
+ return isLocal;
11038
+ }
11039
+
11040
+ /**
11041
+ * Make a fake event but not change the original event,
11042
+ * becuase the global event probably be used by other
11043
+ * listeners not belonging to zrender.
11044
+ * @class
11045
+ */
11046
+ function FakeGlobalEvent(instance, event) {
11047
+ this.type = event.type;
11048
+ this.target = this.currentTarget = instance.dom;
11049
+ this.pointerType = event.pointerType;
11050
+ // Necessray for the force calculation of zrX, zrY
11051
+ this.clientX = event.clientX;
11052
+ this.clientY = event.clientY;
11053
+ // Because we do not mount global listeners to touch events,
11054
+ // we do not copy `targetTouches` and `changedTouches` here.
11055
+ }
11056
+ var fakeGlobalEventProto = FakeGlobalEvent.prototype;
11057
+ // we make the default methods on the event do nothing,
11058
+ // otherwise it is dangerous. See more details in
11059
+ // [Drag outside] in `Handler.js`.
11060
+ fakeGlobalEventProto.stopPropagation =
11061
+ fakeGlobalEventProto.stopImmediatePropagation =
11062
+ fakeGlobalEventProto.preventDefault = noop;
11063
+
11064
+
11065
+ /**
11066
+ * Local DOM Handlers
11067
+ * @this {HandlerProxy}
11068
+ */
11069
+ var localDOMHandlers = {
11070
+
11071
+ mousedown: function (event) {
11072
+ event = normalizeEvent(this.dom, event);
11073
+
11074
+ this._mayPointerCapture = [event.zrX, event.zrY];
11075
+
11076
+ this.trigger('mousedown', event);
11077
+ },
10865
11078
 
10866
- var domHandlers = {
10867
- /**
10868
- * Mouse move handler
10869
- * @inner
10870
- * @param {Event} event
10871
- */
10872
11079
  mousemove: function (event) {
10873
11080
  event = normalizeEvent(this.dom, event);
10874
11081
 
11082
+ var downPoint = this._mayPointerCapture;
11083
+ if (downPoint && (event.zrX !== downPoint[0] || event.zrY !== downPoint[1])) {
11084
+ togglePointerCapture(this, true);
11085
+ }
11086
+
10875
11087
  this.trigger('mousemove', event);
10876
11088
  },
10877
11089
 
10878
- /**
10879
- * Mouse out handler
10880
- * @inner
10881
- * @param {Event} event
10882
- */
10883
- mouseout: function (event) {
11090
+ mouseup: function (event) {
10884
11091
  event = normalizeEvent(this.dom, event);
10885
11092
 
10886
- var element = event.toElement || event.relatedTarget;
10887
- if (element !== this.dom) {
10888
- while (element && element.nodeType !== 9) {
10889
- // 忽略包含在root中的dom引起的mouseOut
10890
- if (element === this.dom) {
10891
- return;
10892
- }
11093
+ togglePointerCapture(this, false);
10893
11094
 
10894
- element = element.parentNode;
10895
- }
11095
+ this.trigger('mouseup', event);
11096
+ },
11097
+
11098
+ mouseout: function (event) {
11099
+ event = normalizeEvent(this.dom, event);
11100
+
11101
+ // Similarly to the browser did on `document` and touch event,
11102
+ // `globalout` will be delayed to final pointer cature release.
11103
+ if (this._pointerCapturing) {
11104
+ event.zrEventControl = 'no_globalout';
10896
11105
  }
10897
11106
 
11107
+ // There might be some doms created by upper layer application
11108
+ // at the same level of painter.getViewportRoot() (e.g., tooltip
11109
+ // dom created by echarts), where 'globalout' event should not
11110
+ // be triggered when mouse enters these doms. (But 'mouseout'
11111
+ // should be triggered at the original hovered element as usual).
11112
+ var element = event.toElement || event.relatedTarget;
11113
+ event.zrIsToLocalDOM = isLocalEl(this, element);
11114
+
10898
11115
  this.trigger('mouseout', event);
10899
11116
  },
10900
11117
 
10901
- /**
10902
- * Touch开始响应函数
10903
- * @inner
10904
- * @param {Event} event
10905
- */
10906
11118
  touchstart: function (event) {
10907
11119
  // Default mouse behaviour should not be disabled here.
10908
11120
  // For example, page may needs to be slided.
10909
11121
  event = normalizeEvent(this.dom, event);
10910
11122
 
10911
- // Mark touch, which is useful in distinguish touch and
10912
- // mouse event in upper applicatoin.
10913
- event.zrByTouch = true;
11123
+ markTouch(event);
10914
11124
 
10915
11125
  this._lastTouchMoment = new Date();
10916
11126
 
10917
11127
  this.handler.processGesture(event, 'start');
10918
11128
 
10919
- // In touch device, trigger `mousemove`(`mouseover`) should
10920
- // be triggered, and must before `mousedown` triggered.
10921
- domHandlers.mousemove.call(this, event);
10922
-
10923
- domHandlers.mousedown.call(this, event);
10924
-
10925
- setTouchTimer(this);
11129
+ // For consistent event listener for both touch device and mouse device,
11130
+ // we simulate "mouseover-->mousedown" in touch device. So we trigger
11131
+ // `mousemove` here (to trigger `mouseover` inside), and then trigger
11132
+ // `mousedown`.
11133
+ localDOMHandlers.mousemove.call(this, event);
11134
+ localDOMHandlers.mousedown.call(this, event);
10926
11135
  },
10927
11136
 
10928
- /**
10929
- * Touch移动响应函数
10930
- * @inner
10931
- * @param {Event} event
10932
- */
10933
11137
  touchmove: function (event) {
10934
-
10935
11138
  event = normalizeEvent(this.dom, event);
10936
11139
 
10937
- // Mark touch, which is useful in distinguish touch and
10938
- // mouse event in upper applicatoin.
10939
- event.zrByTouch = true;
11140
+ markTouch(event);
10940
11141
 
10941
11142
  this.handler.processGesture(event, 'change');
10942
11143
 
10943
11144
  // Mouse move should always be triggered no matter whether
10944
11145
  // there is gestrue event, because mouse move and pinch may
10945
11146
  // be used at the same time.
10946
- domHandlers.mousemove.call(this, event);
10947
-
10948
- setTouchTimer(this);
11147
+ localDOMHandlers.mousemove.call(this, event);
10949
11148
  },
10950
11149
 
10951
- /**
10952
- * Touch结束响应函数
10953
- * @inner
10954
- * @param {Event} event
10955
- */
10956
11150
  touchend: function (event) {
10957
-
10958
11151
  event = normalizeEvent(this.dom, event);
10959
11152
 
10960
- // Mark touch, which is useful in distinguish touch and
10961
- // mouse event in upper applicatoin.
10962
- event.zrByTouch = true;
11153
+ markTouch(event);
10963
11154
 
10964
11155
  this.handler.processGesture(event, 'end');
10965
11156
 
10966
- domHandlers.mouseup.call(this, event);
11157
+ localDOMHandlers.mouseup.call(this, event);
10967
11158
 
10968
11159
  // Do not trigger `mouseout` here, in spite of `mousemove`(`mouseover`) is
10969
11160
  // triggered in `touchstart`. This seems to be illogical, but by this mechanism,
@@ -10976,14 +11167,12 @@ var domHandlers = {
10976
11167
  // click event should always be triggered no matter whether
10977
11168
  // there is gestrue event. System click can not be prevented.
10978
11169
  if (+new Date() - this._lastTouchMoment < TOUCH_CLICK_DELAY) {
10979
- domHandlers.click.call(this, event);
11170
+ localDOMHandlers.click.call(this, event);
10980
11171
  }
10981
-
10982
- setTouchTimer(this);
10983
11172
  },
10984
11173
 
10985
11174
  pointerdown: function (event) {
10986
- domHandlers.mousedown.call(this, event);
11175
+ localDOMHandlers.mousedown.call(this, event);
10987
11176
 
10988
11177
  // if (useMSGuesture(this, event)) {
10989
11178
  // this._msGesture.addPointer(event.pointerId);
@@ -10997,12 +11186,12 @@ var domHandlers = {
10997
11186
  // upper application. So, we dont support mousemove on MS touch
10998
11187
  // device yet.
10999
11188
  if (!isPointerFromTouch(event)) {
11000
- domHandlers.mousemove.call(this, event);
11189
+ localDOMHandlers.mousemove.call(this, event);
11001
11190
  }
11002
11191
  },
11003
11192
 
11004
11193
  pointerup: function (event) {
11005
- domHandlers.mouseup.call(this, event);
11194
+ localDOMHandlers.mouseup.call(this, event);
11006
11195
  },
11007
11196
 
11008
11197
  pointerout: function (event) {
@@ -11010,80 +11199,77 @@ var domHandlers = {
11010
11199
  // (IE11+/Edge on MS Surface) after click event triggered,
11011
11200
  // which is inconsistent with the mousout behavior we defined
11012
11201
  // in touchend. So we unify them.
11013
- // (check domHandlers.touchend for detailed explanation)
11202
+ // (check localDOMHandlers.touchend for detailed explanation)
11014
11203
  if (!isPointerFromTouch(event)) {
11015
- domHandlers.mouseout.call(this, event);
11204
+ localDOMHandlers.mouseout.call(this, event);
11016
11205
  }
11017
11206
  }
11018
- };
11019
-
11020
- function isPointerFromTouch(event) {
11021
- var pointerType = event.pointerType;
11022
- return pointerType === 'pen' || pointerType === 'touch';
11023
- }
11024
11207
 
11025
- // function useMSGuesture(handlerProxy, event) {
11026
- // return isPointerFromTouch(event) && !!handlerProxy._msGesture;
11027
- // }
11208
+ };
11028
11209
 
11029
- // Common handlers
11030
- each$1(['click', 'mousedown', 'mouseup', 'mousewheel', 'dblclick', 'contextmenu'], function (name) {
11031
- domHandlers[name] = function (event) {
11210
+ /**
11211
+ * Othere DOM UI Event handlers for zr dom.
11212
+ * @this {HandlerProxy}
11213
+ */
11214
+ each$1(['click', 'mousewheel', 'dblclick', 'contextmenu'], function (name) {
11215
+ localDOMHandlers[name] = function (event) {
11032
11216
  event = normalizeEvent(this.dom, event);
11033
11217
  this.trigger(name, event);
11034
11218
  };
11035
11219
  });
11036
11220
 
11221
+
11037
11222
  /**
11038
- * 为控制类实例初始化dom 事件处理函数
11223
+ * DOM UI Event handlers for global page.
11039
11224
  *
11040
- * @inner
11041
- * @param {module:zrender/Handler} instance 控制类实例
11225
+ * [Caution]:
11226
+ * those handlers should both support in capture phase and bubble phase!
11227
+ *
11228
+ * @this {HandlerProxy}
11042
11229
  */
11043
- function initDomHandler(instance) {
11044
- each$1(touchHandlerNames, function (name) {
11045
- instance._handlers[name] = bind(domHandlers[name], instance);
11046
- });
11230
+ var globalDOMHandlers = {
11047
11231
 
11048
- each$1(pointerHandlerNames, function (name) {
11049
- instance._handlers[name] = bind(domHandlers[name], instance);
11050
- });
11232
+ pointermove: function (event) {
11233
+ // FIXME
11234
+ // pointermove is so sensitive that it always triggered when
11235
+ // tap(click) on touch screen, which affect some judgement in
11236
+ // upper application. So, we dont support mousemove on MS touch
11237
+ // device yet.
11238
+ if (!isPointerFromTouch(event)) {
11239
+ globalDOMHandlers.mousemove.call(this, event);
11240
+ }
11241
+ },
11051
11242
 
11052
- each$1(mouseHandlerNames, function (name) {
11053
- instance._handlers[name] = makeMouseHandler(domHandlers[name], instance);
11054
- });
11243
+ pointerup: function (event) {
11244
+ globalDOMHandlers.mouseup.call(this, event);
11245
+ },
11055
11246
 
11056
- function makeMouseHandler(fn, instance) {
11057
- return function () {
11058
- if (instance._touching) {
11059
- return;
11060
- }
11061
- return fn.apply(instance, arguments);
11062
- };
11063
- }
11064
- }
11247
+ mousemove: function (event) {
11248
+ this.trigger('mousemove', event);
11249
+ },
11065
11250
 
11251
+ mouseup: function (event) {
11252
+ var pointerCaptureReleasing = this._pointerCapturing;
11066
11253
 
11067
- function HandlerDomProxy(dom) {
11068
- Eventful.call(this);
11254
+ togglePointerCapture(this, false);
11069
11255
 
11070
- this.dom = dom;
11256
+ this.trigger('mouseup', event);
11071
11257
 
11072
- /**
11073
- * @private
11074
- * @type {boolean}
11075
- */
11076
- this._touching = false;
11258
+ if (pointerCaptureReleasing) {
11259
+ event.zrEventControl = 'only_globalout';
11260
+ this.trigger('mouseout', event);
11261
+ }
11262
+ }
11077
11263
 
11078
- /**
11079
- * @private
11080
- * @type {number}
11081
- */
11082
- this._touchTimer;
11264
+ };
11083
11265
 
11084
- this._handlers = {};
11085
11266
 
11086
- initDomHandler(this);
11267
+ /**
11268
+ * @param {HandlerProxy} instance
11269
+ * @param {DOMHandlerScope} scope
11270
+ */
11271
+ function mountLocalDOMEventListeners(instance, scope) {
11272
+ var domHandlers = scope.domHandlers;
11087
11273
 
11088
11274
  if (env$1.pointerEventsSupported) { // Only IE11+/Edge
11089
11275
  // 1. On devices that both enable touch and mouse (e.g., MS Surface and lenovo X240),
@@ -11092,7 +11278,12 @@ function HandlerDomProxy(dom) {
11092
11278
  // 2. On MS Surface, it probablely only trigger mousedown but no mouseup when tap on
11093
11279
  // screen, which do not occurs in pointer event.
11094
11280
  // So we use pointer event to both detect touch gesture and mouse behavior.
11095
- mountHandlers(pointerHandlerNames, this);
11281
+ each$1(localNativeListenerNames.pointer, function (nativeEventName) {
11282
+ mountSingleDOMEventListener(scope, nativeEventName, function (event) {
11283
+ // markTriggeredFromLocal(event);
11284
+ domHandlers[nativeEventName].call(instance, event);
11285
+ });
11286
+ });
11096
11287
 
11097
11288
  // FIXME
11098
11289
  // Note: MS Gesture require CSS touch-action set. But touch-action is not reliable,
@@ -11111,7 +11302,13 @@ function HandlerDomProxy(dom) {
11111
11302
  }
11112
11303
  else {
11113
11304
  if (env$1.touchEventsSupported) {
11114
- mountHandlers(touchHandlerNames, this);
11305
+ each$1(localNativeListenerNames.touch, function (nativeEventName) {
11306
+ mountSingleDOMEventListener(scope, nativeEventName, function (event) {
11307
+ // markTriggeredFromLocal(event);
11308
+ domHandlers[nativeEventName].call(instance, event);
11309
+ setTouchTimer(scope);
11310
+ });
11311
+ });
11115
11312
  // Handler of 'mouseout' event is needed in touch mode, which will be mounted below.
11116
11313
  // addEventListener(root, 'mouseout', this._mouseoutHandler);
11117
11314
  }
@@ -11121,23 +11318,145 @@ function HandlerDomProxy(dom) {
11121
11318
  // mouse event can not be handle in those devices.
11122
11319
  // 2. On MS Surface, Chrome will trigger both touch event and mouse event. How to prevent
11123
11320
  // mouseevent after touch event triggered, see `setTouchTimer`.
11124
- mountHandlers(mouseHandlerNames, this);
11321
+ each$1(localNativeListenerNames.mouse, function (nativeEventName) {
11322
+ mountSingleDOMEventListener(scope, nativeEventName, function (event) {
11323
+ event = getNativeEvent(event);
11324
+ if (!scope.touching) {
11325
+ // markTriggeredFromLocal(event);
11326
+ domHandlers[nativeEventName].call(instance, event);
11327
+ }
11328
+ });
11329
+ });
11330
+ }
11331
+ }
11332
+
11333
+ /**
11334
+ * @param {HandlerProxy} instance
11335
+ * @param {DOMHandlerScope} scope
11336
+ */
11337
+ function mountGlobalDOMEventListeners(instance, scope) {
11338
+ // Only IE11+/Edge. See the comment in `mountLocalDOMEventListeners`.
11339
+ if (env$1.pointerEventsSupported) {
11340
+ each$1(globalNativeListenerNames.pointer, mount);
11341
+ }
11342
+ // Touch event has implemented "drag outside" so we do not mount global listener for touch event.
11343
+ // (see https://www.w3.org/TR/touch-events/#the-touchmove-event)
11344
+ // We do not consider "both-support-touch-and-mouse device" for this feature (see the comment of
11345
+ // `mountLocalDOMEventListeners`) to avoid bugs util some requirements come.
11346
+ else if (!env$1.touchEventsSupported) {
11347
+ each$1(globalNativeListenerNames.mouse, mount);
11348
+ }
11349
+
11350
+ function mount(nativeEventName) {
11351
+ function nativeEventListener(event) {
11352
+ event = getNativeEvent(event);
11353
+ // See the reason in [Drag outside] in `Handler.js`
11354
+ // This checking supports both `useCapture` or not.
11355
+ // PENDING: if there is performance issue in some devices,
11356
+ // we probably can not use `useCapture` and change a easier
11357
+ // to judes whether local (mark).
11358
+ if (!isLocalEl(instance, event.target)) {
11359
+ event = normalizeGlobalEvent(instance, event);
11360
+ scope.domHandlers[nativeEventName].call(instance, event);
11361
+ }
11362
+ }
11363
+ mountSingleDOMEventListener(
11364
+ scope, nativeEventName, nativeEventListener,
11365
+ {capture: true} // See [Drag Outside] in `Handler.js`
11366
+ );
11367
+ }
11368
+ }
11369
+
11370
+ function mountSingleDOMEventListener(scope, nativeEventName, listener, opt) {
11371
+ scope.mounted[nativeEventName] = listener;
11372
+ scope.listenerOpts[nativeEventName] = opt;
11373
+ addEventListener(scope.domTarget, eventNameFix(nativeEventName), listener, opt);
11374
+ }
11375
+
11376
+ function unmountDOMEventListeners(scope) {
11377
+ var mounted = scope.mounted;
11378
+ for (var nativeEventName in mounted) {
11379
+ if (mounted.hasOwnProperty(nativeEventName)) {
11380
+ removeEventListener(
11381
+ scope.domTarget, eventNameFix(nativeEventName), mounted[nativeEventName],
11382
+ scope.listenerOpts[nativeEventName]
11383
+ );
11384
+ }
11385
+ }
11386
+ scope.mounted = {};
11387
+ }
11388
+
11389
+ /**
11390
+ * See [Drag Outside] in `Handler.js`.
11391
+ * @implement
11392
+ * @param {boolean} isPointerCapturing Should never be `null`/`undefined`.
11393
+ * `true`: start to capture pointer if it is not capturing.
11394
+ * `false`: end the capture if it is capturing.
11395
+ */
11396
+ function togglePointerCapture(instance, isPointerCapturing) {
11397
+ instance._mayPointerCapture = null;
11398
+
11399
+ if (globalEventSupported && (instance._pointerCapturing ^ isPointerCapturing)) {
11400
+ instance._pointerCapturing = isPointerCapturing;
11401
+
11402
+ var globalHandlerScope = instance._globalHandlerScope;
11403
+ isPointerCapturing
11404
+ ? mountGlobalDOMEventListeners(instance, globalHandlerScope)
11405
+ : unmountDOMEventListeners(globalHandlerScope);
11125
11406
  }
11407
+ }
11408
+
11409
+ /**
11410
+ * @inner
11411
+ * @class
11412
+ */
11413
+ function DOMHandlerScope(domTarget, domHandlers) {
11414
+ this.domTarget = domTarget;
11415
+ this.domHandlers = domHandlers;
11416
+
11417
+ // Key: eventName, value: mounted handler funcitons.
11418
+ // Used for unmount.
11419
+ this.mounted = {};
11420
+ this.listenerOpts = {};
11421
+
11422
+ this.touchTimer = null;
11423
+ this.touching = false;
11424
+ }
11425
+
11426
+ /**
11427
+ * @public
11428
+ * @class
11429
+ */
11430
+ function HandlerDomProxy(dom, painterRoot) {
11431
+ Eventful.call(this);
11432
+
11433
+ this.dom = dom;
11434
+ this.painterRoot = painterRoot;
11126
11435
 
11127
- function mountHandlers(handlerNames, instance) {
11128
- each$1(handlerNames, function (name) {
11129
- addEventListener(dom, eventNameFix(name), instance._handlers[name]);
11130
- }, instance);
11436
+ this._localHandlerScope = new DOMHandlerScope(dom, localDOMHandlers);
11437
+
11438
+ if (globalEventSupported) {
11439
+ this._globalHandlerScope = new DOMHandlerScope(document, globalDOMHandlers);
11131
11440
  }
11441
+
11442
+ /**
11443
+ * @type {boolean}
11444
+ */
11445
+ this._pointerCapturing = false;
11446
+ /**
11447
+ * @type {Array.<number>} [x, y] or null.
11448
+ */
11449
+ this._mayPointerCapture = null;
11450
+
11451
+ mountLocalDOMEventListeners(this, this._localHandlerScope);
11132
11452
  }
11133
11453
 
11134
11454
  var handlerDomProxyProto = HandlerDomProxy.prototype;
11135
- handlerDomProxyProto.dispose = function () {
11136
- var handlerNames = mouseHandlerNames.concat(touchHandlerNames);
11137
11455
 
11138
- for (var i = 0; i < handlerNames.length; i++) {
11139
- var name = handlerNames[i];
11140
- removeEventListener(this.dom, eventNameFix(name), this._handlers[name]);
11456
+ handlerDomProxyProto.dispose = function () {
11457
+ unmountDOMEventListeners(this._localHandlerScope);
11458
+ if (globalEventSupported) {
11459
+ unmountDOMEventListeners(this._globalHandlerScope);
11141
11460
  }
11142
11461
  };
11143
11462
 
@@ -11145,6 +11464,7 @@ handlerDomProxyProto.setCursor = function (cursorStyle) {
11145
11464
  this.dom.style && (this.dom.style.cursor = cursorStyle || 'default');
11146
11465
  };
11147
11466
 
11467
+
11148
11468
  mixin(HandlerDomProxy, Eventful);
11149
11469
 
11150
11470
  /*!
@@ -11168,7 +11488,7 @@ var instances$1 = {}; // ZRender实例map索引
11168
11488
  /**
11169
11489
  * @type {string}
11170
11490
  */
11171
- var version$1 = '4.1.2';
11491
+ var version$1 = '4.2.0';
11172
11492
 
11173
11493
  /**
11174
11494
  * Initializing a zrender instance
@@ -11270,7 +11590,7 @@ var ZRender = function (id, dom, opts) {
11270
11590
  this.storage = storage;
11271
11591
  this.painter = painter;
11272
11592
 
11273
- var handerProxy = (!env$1.node && !env$1.worker) ? new HandlerDomProxy(painter.getViewportRoot()) : null;
11593
+ var handerProxy = (!env$1.node && !env$1.worker) ? new HandlerDomProxy(painter.getViewportRoot(), painter.root) : null;
11274
11594
  this.handler = new Handler(storage, painter, handerProxy, painter.root);
11275
11595
 
11276
11596
  /**
@@ -17782,8 +18102,7 @@ function rollbackDefaultTextStyle(style) {
17782
18102
  }
17783
18103
 
17784
18104
  function getFont(opt, ecModel) {
17785
- // ecModel or default text style model.
17786
- var gTextStyleModel = ecModel || ecModel.getModel('textStyle');
18105
+ var gTextStyleModel = ecModel && ecModel.getModel('textStyle');
17787
18106
  return trim([
17788
18107
  // FIXME in node-canvas fontWeight is before fontStyle
17789
18108
  opt.fontStyle || gTextStyleModel && gTextStyleModel.getShallow('fontStyle') || '',
@@ -20493,178 +20812,6 @@ var colorPaletteMixin = {
20493
20812
  * under the License.
20494
20813
  */
20495
20814
 
20496
- /**
20497
- * Helper for model references.
20498
- * There are many manners to refer axis/coordSys.
20499
- */
20500
-
20501
- // TODO
20502
- // merge relevant logic to this file?
20503
- // check: "modelHelper" of tooltip and "BrushTargetManager".
20504
-
20505
- /**
20506
- * @return {Object} For example:
20507
- * {
20508
- * coordSysName: 'cartesian2d',
20509
- * coordSysDims: ['x', 'y', ...],
20510
- * axisMap: HashMap({
20511
- * x: xAxisModel,
20512
- * y: yAxisModel
20513
- * }),
20514
- * categoryAxisMap: HashMap({
20515
- * x: xAxisModel,
20516
- * y: undefined
20517
- * }),
20518
- * // It also indicate that whether there is category axis.
20519
- * firstCategoryDimIndex: 1,
20520
- * // To replace user specified encode.
20521
- * }
20522
- */
20523
- function getCoordSysDefineBySeries(seriesModel) {
20524
- var coordSysName = seriesModel.get('coordinateSystem');
20525
- var result = {
20526
- coordSysName: coordSysName,
20527
- coordSysDims: [],
20528
- axisMap: createHashMap(),
20529
- categoryAxisMap: createHashMap()
20530
- };
20531
- var fetch = fetchers[coordSysName];
20532
- if (fetch) {
20533
- fetch(seriesModel, result, result.axisMap, result.categoryAxisMap);
20534
- return result;
20535
- }
20536
- }
20537
-
20538
- var fetchers = {
20539
-
20540
- cartesian2d: function (seriesModel, result, axisMap, categoryAxisMap) {
20541
- var xAxisModel = seriesModel.getReferringComponents('xAxis')[0];
20542
- var yAxisModel = seriesModel.getReferringComponents('yAxis')[0];
20543
-
20544
- if (__DEV__) {
20545
- if (!xAxisModel) {
20546
- throw new Error('xAxis "' + retrieve(
20547
- seriesModel.get('xAxisIndex'),
20548
- seriesModel.get('xAxisId'),
20549
- 0
20550
- ) + '" not found');
20551
- }
20552
- if (!yAxisModel) {
20553
- throw new Error('yAxis "' + retrieve(
20554
- seriesModel.get('xAxisIndex'),
20555
- seriesModel.get('yAxisId'),
20556
- 0
20557
- ) + '" not found');
20558
- }
20559
- }
20560
-
20561
- result.coordSysDims = ['x', 'y'];
20562
- axisMap.set('x', xAxisModel);
20563
- axisMap.set('y', yAxisModel);
20564
-
20565
- if (isCategory(xAxisModel)) {
20566
- categoryAxisMap.set('x', xAxisModel);
20567
- result.firstCategoryDimIndex = 0;
20568
- }
20569
- if (isCategory(yAxisModel)) {
20570
- categoryAxisMap.set('y', yAxisModel);
20571
- result.firstCategoryDimIndex = 1;
20572
- }
20573
- },
20574
-
20575
- singleAxis: function (seriesModel, result, axisMap, categoryAxisMap) {
20576
- var singleAxisModel = seriesModel.getReferringComponents('singleAxis')[0];
20577
-
20578
- if (__DEV__) {
20579
- if (!singleAxisModel) {
20580
- throw new Error('singleAxis should be specified.');
20581
- }
20582
- }
20583
-
20584
- result.coordSysDims = ['single'];
20585
- axisMap.set('single', singleAxisModel);
20586
-
20587
- if (isCategory(singleAxisModel)) {
20588
- categoryAxisMap.set('single', singleAxisModel);
20589
- result.firstCategoryDimIndex = 0;
20590
- }
20591
- },
20592
-
20593
- polar: function (seriesModel, result, axisMap, categoryAxisMap) {
20594
- var polarModel = seriesModel.getReferringComponents('polar')[0];
20595
- var radiusAxisModel = polarModel.findAxisModel('radiusAxis');
20596
- var angleAxisModel = polarModel.findAxisModel('angleAxis');
20597
-
20598
- if (__DEV__) {
20599
- if (!angleAxisModel) {
20600
- throw new Error('angleAxis option not found');
20601
- }
20602
- if (!radiusAxisModel) {
20603
- throw new Error('radiusAxis option not found');
20604
- }
20605
- }
20606
-
20607
- result.coordSysDims = ['radius', 'angle'];
20608
- axisMap.set('radius', radiusAxisModel);
20609
- axisMap.set('angle', angleAxisModel);
20610
-
20611
- if (isCategory(radiusAxisModel)) {
20612
- categoryAxisMap.set('radius', radiusAxisModel);
20613
- result.firstCategoryDimIndex = 0;
20614
- }
20615
- if (isCategory(angleAxisModel)) {
20616
- categoryAxisMap.set('angle', angleAxisModel);
20617
- result.firstCategoryDimIndex = 1;
20618
- }
20619
- },
20620
-
20621
- geo: function (seriesModel, result, axisMap, categoryAxisMap) {
20622
- result.coordSysDims = ['lng', 'lat'];
20623
- },
20624
-
20625
- parallel: function (seriesModel, result, axisMap, categoryAxisMap) {
20626
- var ecModel = seriesModel.ecModel;
20627
- var parallelModel = ecModel.getComponent(
20628
- 'parallel', seriesModel.get('parallelIndex')
20629
- );
20630
- var coordSysDims = result.coordSysDims = parallelModel.dimensions.slice();
20631
-
20632
- each$1(parallelModel.parallelAxisIndex, function (axisIndex, index) {
20633
- var axisModel = ecModel.getComponent('parallelAxis', axisIndex);
20634
- var axisDim = coordSysDims[index];
20635
- axisMap.set(axisDim, axisModel);
20636
-
20637
- if (isCategory(axisModel) && result.firstCategoryDimIndex == null) {
20638
- categoryAxisMap.set(axisDim, axisModel);
20639
- result.firstCategoryDimIndex = index;
20640
- }
20641
- });
20642
- }
20643
- };
20644
-
20645
- function isCategory(axisModel) {
20646
- return axisModel.get('type') === 'category';
20647
- }
20648
-
20649
- /*
20650
- * Licensed to the Apache Software Foundation (ASF) under one
20651
- * or more contributor license agreements. See the NOTICE file
20652
- * distributed with this work for additional information
20653
- * regarding copyright ownership. The ASF licenses this file
20654
- * to you under the Apache License, Version 2.0 (the
20655
- * "License"); you may not use this file except in compliance
20656
- * with the License. You may obtain a copy of the License at
20657
- *
20658
- * http://www.apache.org/licenses/LICENSE-2.0
20659
- *
20660
- * Unless required by applicable law or agreed to in writing,
20661
- * software distributed under the License is distributed on an
20662
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20663
- * KIND, either express or implied. See the License for the
20664
- * specific language governing permissions and limitations
20665
- * under the License.
20666
- */
20667
-
20668
20815
  // Avoid typo.
20669
20816
  var SOURCE_FORMAT_ORIGINAL = 'original';
20670
20817
  var SOURCE_FORMAT_ARRAY_ROWS = 'arrayRows';
@@ -20834,6 +20981,13 @@ enableClassCheck(Source);
20834
20981
  * under the License.
20835
20982
  */
20836
20983
 
20984
+ // The result of `guessOrdinal`.
20985
+ var BE_ORDINAL = {
20986
+ Must: 1, // Encounter string but not '-' and not number-like.
20987
+ Might: 2, // Encounter string but number-like.
20988
+ Not: 3 // Other cases
20989
+ };
20990
+
20837
20991
  var inner$3 = makeInner();
20838
20992
 
20839
20993
  /**
@@ -20967,14 +21121,6 @@ function prepareSource(seriesModel) {
20967
21121
  data, sourceFormat, seriesLayoutBy, sourceHeader, dimensionsDefine
20968
21122
  );
20969
21123
 
20970
- // Note: dataset option does not have `encode`.
20971
- var encodeDefine = seriesOption.encode;
20972
- if (!encodeDefine && datasetModel) {
20973
- encodeDefine = makeDefaultEncode(
20974
- seriesModel, datasetModel, data, sourceFormat, seriesLayoutBy, completeResult
20975
- );
20976
- }
20977
-
20978
21124
  inner$3(seriesModel).source = new Source({
20979
21125
  data: data,
20980
21126
  fromDataset: fromDataset,
@@ -20983,7 +21129,8 @@ function prepareSource(seriesModel) {
20983
21129
  dimensionsDefine: completeResult.dimensionsDefine,
20984
21130
  startIndex: completeResult.startIndex,
20985
21131
  dimensionsDetectCount: completeResult.dimensionsDetectCount,
20986
- encodeDefine: encodeDefine
21132
+ // Note: dataset option does not have `encode`.
21133
+ encodeDefine: seriesOption.encode
20987
21134
  });
20988
21135
  }
20989
21136
 
@@ -20995,7 +21142,6 @@ function completeBySourceData(data, sourceFormat, seriesLayoutBy, sourceHeader,
20995
21142
 
20996
21143
  var dimensionsDetectCount;
20997
21144
  var startIndex;
20998
- var findPotentialName;
20999
21145
 
21000
21146
  if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) {
21001
21147
  // Rule: Most of the first line are string: it is header.
@@ -21038,13 +21184,11 @@ function completeBySourceData(data, sourceFormat, seriesLayoutBy, sourceHeader,
21038
21184
  else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) {
21039
21185
  if (!dimensionsDefine) {
21040
21186
  dimensionsDefine = objectRowsCollectDimensions(data);
21041
- findPotentialName = true;
21042
21187
  }
21043
21188
  }
21044
21189
  else if (sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) {
21045
21190
  if (!dimensionsDefine) {
21046
21191
  dimensionsDefine = [];
21047
- findPotentialName = true;
21048
21192
  each$1(data, function (colArr, key) {
21049
21193
  dimensionsDefine.push(key);
21050
21194
  });
@@ -21060,21 +21204,10 @@ function completeBySourceData(data, sourceFormat, seriesLayoutBy, sourceHeader,
21060
21204
  }
21061
21205
  }
21062
21206
 
21063
- var potentialNameDimIndex;
21064
- if (findPotentialName) {
21065
- each$1(dimensionsDefine, function (dim, idx) {
21066
- if ((isObject$1(dim) ? dim.name : dim) === 'name') {
21067
- potentialNameDimIndex = idx;
21068
- }
21069
- });
21070
- }
21071
-
21072
21207
  return {
21073
21208
  startIndex: startIndex,
21074
21209
  dimensionsDefine: normalizeDimensionsDefine(dimensionsDefine),
21075
- dimensionsDetectCount: dimensionsDetectCount,
21076
- potentialNameDimIndex: potentialNameDimIndex
21077
- // TODO: potentialIdDimIdx
21210
+ dimensionsDetectCount: dimensionsDetectCount
21078
21211
  };
21079
21212
  }
21080
21213
 
@@ -21148,103 +21281,198 @@ function objectRowsCollectDimensions(data) {
21148
21281
  }
21149
21282
  }
21150
21283
 
21151
- // ??? TODO merge to completedimensions, where also has
21152
- // default encode making logic. And the default rule
21153
- // should depends on series? consider 'map'.
21154
- function makeDefaultEncode(
21155
- seriesModel, datasetModel, data, sourceFormat, seriesLayoutBy, completeResult
21156
- ) {
21157
- var coordSysDefine = getCoordSysDefineBySeries(seriesModel);
21284
+ /**
21285
+ * [The strategy of the arrengment of data dimensions for dataset]:
21286
+ * "value way": all axes are non-category axes. So series one by one take
21287
+ * several (the number is coordSysDims.length) dimensions from dataset.
21288
+ * The result of data arrengment of data dimensions like:
21289
+ * | ser0_x | ser0_y | ser1_x | ser1_y | ser2_x | ser2_y |
21290
+ * "category way": at least one axis is category axis. So the the first data
21291
+ * dimension is always mapped to the first category axis and shared by
21292
+ * all of the series. The other data dimensions are taken by series like
21293
+ * "value way" does.
21294
+ * The result of data arrengment of data dimensions like:
21295
+ * | ser_shared_x | ser0_y | ser1_y | ser2_y |
21296
+ *
21297
+ * @param {Array.<Object|string>} coordDimensions [{name: <string>, type: <string>, dimsDef: <Array>}, ...]
21298
+ * @param {module:model/Series} seriesModel
21299
+ * @param {module:data/Source} source
21300
+ * @return {Object} encode Never be `null/undefined`.
21301
+ */
21302
+ function makeSeriesEncodeForAxisCoordSys(coordDimensions, seriesModel, source) {
21158
21303
  var encode = {};
21159
- // var encodeTooltip = [];
21160
- // var encodeLabel = [];
21304
+
21305
+ var datasetModel = getDatasetModel(seriesModel);
21306
+ // Currently only make default when using dataset, util more reqirements occur.
21307
+ if (!datasetModel || !coordDimensions) {
21308
+ return encode;
21309
+ }
21310
+
21161
21311
  var encodeItemName = [];
21162
21312
  var encodeSeriesName = [];
21163
- var seriesType = seriesModel.subType;
21164
-
21165
- // ??? TODO refactor: provide by series itself.
21166
- // Consider the case: 'map' series is based on geo coordSys,
21167
- // 'graph', 'heatmap' can be based on cartesian. But can not
21168
- // give default rule simply here.
21169
- var nSeriesMap = createHashMap(['pie', 'map', 'funnel']);
21170
- var cSeriesMap = createHashMap([
21171
- 'line', 'bar', 'pictorialBar', 'scatter', 'effectScatter', 'candlestick', 'boxplot'
21172
- ]);
21173
-
21174
- // Usually in this case series will use the first data
21175
- // dimension as the "value" dimension, or other default
21176
- // processes respectively.
21177
- if (coordSysDefine && cSeriesMap.get(seriesType) != null) {
21178
- var ecModel = seriesModel.ecModel;
21179
- var datasetMap = inner$3(ecModel).datasetMap;
21180
- var key = datasetModel.uid + '_' + seriesLayoutBy;
21181
- var datasetRecord = datasetMap.get(key)
21182
- || datasetMap.set(key, {categoryWayDim: 1, valueWayDim: 0});
21183
21313
 
21184
- // TODO
21185
- // Auto detect first time axis and do arrangement.
21186
- each$1(coordSysDefine.coordSysDims, function (coordDim) {
21187
- // In value way.
21188
- if (coordSysDefine.firstCategoryDimIndex == null) {
21189
- var dataDim = datasetRecord.valueWayDim++;
21190
- encode[coordDim] = dataDim;
21191
-
21192
- // ??? TODO give a better default series name rule?
21193
- // especially when encode x y specified.
21194
- // consider: when mutiple series share one dimension
21195
- // category axis, series name should better use
21196
- // the other dimsion name. On the other hand, use
21197
- // both dimensions name.
21198
-
21199
- encodeSeriesName.push(dataDim);
21200
- // encodeTooltip.push(dataDim);
21201
- // encodeLabel.push(dataDim);
21202
- }
21203
- // In category way, category axis.
21204
- else if (coordSysDefine.categoryAxisMap.get(coordDim)) {
21205
- encode[coordDim] = 0;
21206
- encodeItemName.push(0);
21207
- }
21208
- // In category way, non-category axis.
21209
- else {
21210
- var dataDim = datasetRecord.categoryWayDim++;
21211
- encode[coordDim] = dataDim;
21212
- // encodeTooltip.push(dataDim);
21213
- // encodeLabel.push(dataDim);
21214
- encodeSeriesName.push(dataDim);
21314
+ var ecModel = seriesModel.ecModel;
21315
+ var datasetMap = inner$3(ecModel).datasetMap;
21316
+ var key = datasetModel.uid + '_' + source.seriesLayoutBy;
21317
+
21318
+ var baseCategoryDimIndex;
21319
+ var categoryWayValueDimStart;
21320
+ coordDimensions = coordDimensions.slice();
21321
+ each$1(coordDimensions, function (coordDimInfo, coordDimIdx) {
21322
+ !isObject$1(coordDimInfo) && (coordDimensions[coordDimIdx] = {name: coordDimInfo});
21323
+ if (coordDimInfo.type === 'ordinal' && baseCategoryDimIndex == null) {
21324
+ baseCategoryDimIndex = coordDimIdx;
21325
+ categoryWayValueDimStart = getDataDimCountOnCoordDim(coordDimensions[coordDimIdx]);
21326
+ }
21327
+ encode[coordDimInfo.name] = [];
21328
+ });
21329
+
21330
+ var datasetRecord = datasetMap.get(key)
21331
+ || datasetMap.set(key, {categoryWayDim: categoryWayValueDimStart, valueWayDim: 0});
21332
+
21333
+ // TODO
21334
+ // Auto detect first time axis and do arrangement.
21335
+ each$1(coordDimensions, function (coordDimInfo, coordDimIdx) {
21336
+ var coordDimName = coordDimInfo.name;
21337
+ var count = getDataDimCountOnCoordDim(coordDimInfo);
21338
+
21339
+ // In value way.
21340
+ if (baseCategoryDimIndex == null) {
21341
+ var start = datasetRecord.valueWayDim;
21342
+ pushDim(encode[coordDimName], start, count);
21343
+ pushDim(encodeSeriesName, start, count);
21344
+ datasetRecord.valueWayDim += count;
21345
+
21346
+ // ??? TODO give a better default series name rule?
21347
+ // especially when encode x y specified.
21348
+ // consider: when mutiple series share one dimension
21349
+ // category axis, series name should better use
21350
+ // the other dimsion name. On the other hand, use
21351
+ // both dimensions name.
21352
+ }
21353
+ // In category way, the first category axis.
21354
+ else if (baseCategoryDimIndex === coordDimIdx) {
21355
+ pushDim(encode[coordDimName], 0, count);
21356
+ pushDim(encodeItemName, 0, count);
21357
+ }
21358
+ // In category way, the other axis.
21359
+ else {
21360
+ var start = datasetRecord.categoryWayDim;
21361
+ pushDim(encode[coordDimName], start, count);
21362
+ pushDim(encodeSeriesName, start, count);
21363
+ datasetRecord.categoryWayDim += count;
21364
+ }
21365
+ });
21366
+
21367
+ function pushDim(dimIdxArr, idxFrom, idxCount) {
21368
+ for (var i = 0; i < idxCount; i++) {
21369
+ dimIdxArr.push(idxFrom + i);
21370
+ }
21371
+ }
21372
+
21373
+ function getDataDimCountOnCoordDim(coordDimInfo) {
21374
+ var dimsDef = coordDimInfo.dimsDef;
21375
+ return dimsDef ? dimsDef.length : 1;
21376
+ }
21377
+
21378
+ encodeItemName.length && (encode.itemName = encodeItemName);
21379
+ encodeSeriesName.length && (encode.seriesName = encodeSeriesName);
21380
+
21381
+ return encode;
21382
+ }
21383
+
21384
+ /**
21385
+ * Work for data like [{name: ..., value: ...}, ...].
21386
+ *
21387
+ * @param {module:model/Series} seriesModel
21388
+ * @param {module:data/Source} source
21389
+ * @return {Object} encode Never be `null/undefined`.
21390
+ */
21391
+ function makeSeriesEncodeForNameBased(seriesModel, source, dimCount) {
21392
+ var encode = {};
21393
+
21394
+ var datasetModel = getDatasetModel(seriesModel);
21395
+ // Currently only make default when using dataset, util more reqirements occur.
21396
+ if (!datasetModel) {
21397
+ return encode;
21398
+ }
21399
+
21400
+ var sourceFormat = source.sourceFormat;
21401
+ var dimensionsDefine = source.dimensionsDefine;
21402
+
21403
+ var potentialNameDimIndex;
21404
+ if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS || sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) {
21405
+ each$1(dimensionsDefine, function (dim, idx) {
21406
+ if ((isObject$1(dim) ? dim.name : dim) === 'name') {
21407
+ potentialNameDimIndex = idx;
21215
21408
  }
21216
21409
  });
21217
21410
  }
21218
- // Do not make a complex rule! Hard to code maintain and not necessary.
21219
- // ??? TODO refactor: provide by series itself.
21220
- // [{name: ..., value: ...}, ...] like:
21221
- else if (nSeriesMap.get(seriesType) != null) {
21222
- // Find the first not ordinal. (5 is an experience value)
21223
- var firstNotOrdinal;
21224
- for (var i = 0; i < 5 && firstNotOrdinal == null; i++) {
21225
- if (!doGuessOrdinal(
21226
- data, sourceFormat, seriesLayoutBy,
21227
- completeResult.dimensionsDefine, completeResult.startIndex, i
21228
- )) {
21229
- firstNotOrdinal = i;
21411
+
21412
+ // idxResult: {v, n}.
21413
+ var idxResult = (function () {
21414
+
21415
+ var idxRes0 = {};
21416
+ var idxRes1 = {};
21417
+ var guessRecords = [];
21418
+
21419
+ // 5 is an experience value.
21420
+ for (var i = 0, len = Math.min(5, dimCount); i < len; i++) {
21421
+ var guessResult = doGuessOrdinal(
21422
+ source.data, sourceFormat, source.seriesLayoutBy,
21423
+ dimensionsDefine, source.startIndex, i
21424
+ );
21425
+ guessRecords.push(guessResult);
21426
+ var isPureNumber = guessResult === BE_ORDINAL.Not;
21427
+
21428
+ // [Strategy of idxRes0]: find the first BE_ORDINAL.Not as the value dim,
21429
+ // and then find a name dim with the priority:
21430
+ // "BE_ORDINAL.Might|BE_ORDINAL.Must" > "other dim" > "the value dim itself".
21431
+ if (isPureNumber && idxRes0.v == null && i !== potentialNameDimIndex) {
21432
+ idxRes0.v = i;
21433
+ }
21434
+ if (idxRes0.n == null
21435
+ || (idxRes0.n === idxRes0.v)
21436
+ || (!isPureNumber && guessRecords[idxRes0.n] === BE_ORDINAL.Not)
21437
+ ) {
21438
+ idxRes0.n = i;
21439
+ }
21440
+ if (fulfilled(idxRes0) && guessRecords[idxRes0.n] !== BE_ORDINAL.Not) {
21441
+ return idxRes0;
21442
+ }
21443
+
21444
+ // [Strategy of idxRes1]: if idxRes0 not satisfied (that is, no BE_ORDINAL.Not),
21445
+ // find the first BE_ORDINAL.Might as the value dim,
21446
+ // and then find a name dim with the priority:
21447
+ // "other dim" > "the value dim itself".
21448
+ // That is for backward compat: number-like (e.g., `'3'`, `'55'`) can be
21449
+ // treated as number.
21450
+ if (!isPureNumber) {
21451
+ if (guessResult === BE_ORDINAL.Might && idxRes1.v == null && i !== potentialNameDimIndex) {
21452
+ idxRes1.v = i;
21453
+ }
21454
+ if (idxRes1.n == null || (idxRes1.n === idxRes1.v)) {
21455
+ idxRes1.n = i;
21456
+ }
21230
21457
  }
21231
21458
  }
21232
- if (firstNotOrdinal != null) {
21233
- encode.value = firstNotOrdinal;
21234
- var nameDimIndex = completeResult.potentialNameDimIndex
21235
- || Math.max(firstNotOrdinal - 1, 0);
21236
- // By default, label use itemName in charts.
21237
- // So we dont set encodeLabel here.
21238
- encodeSeriesName.push(nameDimIndex);
21239
- encodeItemName.push(nameDimIndex);
21240
- // encodeTooltip.push(firstNotOrdinal);
21459
+
21460
+ function fulfilled(idxResult) {
21461
+ return idxResult.v != null && idxResult.n != null;
21241
21462
  }
21242
- }
21243
21463
 
21244
- // encodeTooltip.length && (encode.tooltip = encodeTooltip);
21245
- // encodeLabel.length && (encode.label = encodeLabel);
21246
- encodeItemName.length && (encode.itemName = encodeItemName);
21247
- encodeSeriesName.length && (encode.seriesName = encodeSeriesName);
21464
+ return fulfilled(idxRes0) ? idxRes0 : fulfilled(idxRes1) ? idxRes1 : null;
21465
+ })();
21466
+
21467
+ if (idxResult) {
21468
+ encode.value = idxResult.v;
21469
+ // `potentialNameDimIndex` has highest priority.
21470
+ var nameDimIndex = potentialNameDimIndex != null ? potentialNameDimIndex : idxResult.n;
21471
+ // By default, label use itemName in charts.
21472
+ // So we dont set encodeLabel here.
21473
+ encode.itemName = [nameDimIndex];
21474
+ encode.seriesName = [nameDimIndex];
21475
+ }
21248
21476
 
21249
21477
  return encode;
21250
21478
  }
@@ -21272,7 +21500,7 @@ function getDatasetModel(seriesModel) {
21272
21500
  *
21273
21501
  * @param {module:echars/data/Source} source
21274
21502
  * @param {number} dimIndex
21275
- * @return {boolean} Whether ordinal.
21503
+ * @return {BE_ORDINAL} guess result.
21276
21504
  */
21277
21505
  function guessOrdinal(source, dimIndex) {
21278
21506
  return doGuessOrdinal(
@@ -21286,6 +21514,7 @@ function guessOrdinal(source, dimIndex) {
21286
21514
  }
21287
21515
 
21288
21516
  // dimIndex may be overflow source data.
21517
+ // return {BE_ORDINAL}
21289
21518
  function doGuessOrdinal(
21290
21519
  data, sourceFormat, seriesLayoutBy, dimensionsDefine, startIndex, dimIndex
21291
21520
  ) {
@@ -21294,15 +21523,26 @@ function doGuessOrdinal(
21294
21523
  var maxLoop = 5;
21295
21524
 
21296
21525
  if (isTypedArray(data)) {
21297
- return false;
21526
+ return BE_ORDINAL.Not;
21298
21527
  }
21299
21528
 
21300
21529
  // When sourceType is 'objectRows' or 'keyedColumns', dimensionsDefine
21301
21530
  // always exists in source.
21302
21531
  var dimName;
21532
+ var dimType;
21303
21533
  if (dimensionsDefine) {
21304
- dimName = dimensionsDefine[dimIndex];
21305
- dimName = isObject$1(dimName) ? dimName.name : dimName;
21534
+ var dimDefItem = dimensionsDefine[dimIndex];
21535
+ if (isObject$1(dimDefItem)) {
21536
+ dimName = dimDefItem.name;
21537
+ dimType = dimDefItem.type;
21538
+ }
21539
+ else if (isString(dimDefItem)) {
21540
+ dimName = dimDefItem;
21541
+ }
21542
+ }
21543
+
21544
+ if (dimType != null) {
21545
+ return dimType === 'ordinal' ? BE_ORDINAL.Must : BE_ORDINAL.Not;
21306
21546
  }
21307
21547
 
21308
21548
  if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) {
@@ -21325,7 +21565,7 @@ function doGuessOrdinal(
21325
21565
  }
21326
21566
  else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) {
21327
21567
  if (!dimName) {
21328
- return;
21568
+ return BE_ORDINAL.Not;
21329
21569
  }
21330
21570
  for (var i = 0; i < data.length && i < maxLoop; i++) {
21331
21571
  var item = data[i];
@@ -21336,11 +21576,11 @@ function doGuessOrdinal(
21336
21576
  }
21337
21577
  else if (sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) {
21338
21578
  if (!dimName) {
21339
- return;
21579
+ return BE_ORDINAL.Not;
21340
21580
  }
21341
21581
  var sample = data[dimName];
21342
21582
  if (!sample || isTypedArray(sample)) {
21343
- return false;
21583
+ return BE_ORDINAL.Not;
21344
21584
  }
21345
21585
  for (var i = 0; i < sample.length && i < maxLoop; i++) {
21346
21586
  if ((result = detectValue(sample[i])) != null) {
@@ -21353,7 +21593,7 @@ function doGuessOrdinal(
21353
21593
  var item = data[i];
21354
21594
  var val = getDataItemValue(item);
21355
21595
  if (!isArray(val)) {
21356
- return false;
21596
+ return BE_ORDINAL.Not;
21357
21597
  }
21358
21598
  if ((result = detectValue(val[dimIndex])) != null) {
21359
21599
  return result;
@@ -21362,17 +21602,18 @@ function doGuessOrdinal(
21362
21602
  }
21363
21603
 
21364
21604
  function detectValue(val) {
21605
+ var beStr = isString(val);
21365
21606
  // Consider usage convenience, '1', '2' will be treated as "number".
21366
21607
  // `isFinit('')` get `true`.
21367
21608
  if (val != null && isFinite(val) && val !== '') {
21368
- return false;
21609
+ return beStr ? BE_ORDINAL.Might : BE_ORDINAL.Not;
21369
21610
  }
21370
- else if (isString(val) && val !== '-') {
21371
- return true;
21611
+ else if (beStr && val !== '-') {
21612
+ return BE_ORDINAL.Must;
21372
21613
  }
21373
21614
  }
21374
21615
 
21375
- return false;
21616
+ return BE_ORDINAL.Not;
21376
21617
  }
21377
21618
 
21378
21619
  /*
@@ -24119,11 +24360,11 @@ var SeriesModel = ComponentModel.extend({
24119
24360
  defaultOption: null,
24120
24361
 
24121
24362
  /**
24122
- * Data provided for legend
24123
- * @type {Function}
24363
+ * legend visual provider to the legend component
24364
+ * @type {Object}
24124
24365
  */
24125
24366
  // PENDING
24126
- legendDataProvider: null,
24367
+ legendVisualProvider: null,
24127
24368
 
24128
24369
  /**
24129
24370
  * Access path of color for visual
@@ -25247,25 +25488,30 @@ var seriesColor = {
25247
25488
  reset: function (seriesModel, ecModel) {
25248
25489
  var data = seriesModel.getData();
25249
25490
  var colorAccessPath = (seriesModel.visualColorAccessPath || 'itemStyle.color').split('.');
25250
- var color = seriesModel.get(colorAccessPath) // Set in itemStyle
25251
- || seriesModel.getColorFromPalette(
25491
+ // Set in itemStyle
25492
+ var color = seriesModel.get(colorAccessPath);
25493
+ var colorCallback = (isFunction$1(color) && !(color instanceof Gradient))
25494
+ ? color : null;
25495
+ // Default color
25496
+ if (!color || colorCallback) {
25497
+ color = seriesModel.getColorFromPalette(
25252
25498
  // TODO series count changed.
25253
25499
  seriesModel.name, null, ecModel.getSeriesCount()
25254
- ); // Default color
25500
+ );
25501
+ }
25255
25502
 
25256
- // FIXME Set color function or use the platte color
25257
25503
  data.setVisual('color', color);
25258
-
25504
+
25259
25505
  var borderColorAccessPath = (seriesModel.visualBorderColorAccessPath || 'itemStyle.borderColor').split('.');
25260
25506
  var borderColor = seriesModel.get(borderColorAccessPath);
25261
25507
  data.setVisual('borderColor', borderColor);
25262
25508
 
25263
25509
  // Only visible series has each data be visual encoded
25264
25510
  if (!ecModel.isSeriesFiltered(seriesModel)) {
25265
- if (typeof color === 'function' && !(color instanceof Gradient)) {
25511
+ if (colorCallback) {
25266
25512
  data.each(function (idx) {
25267
25513
  data.setItemVisual(
25268
- idx, 'color', color(seriesModel.getDataParams(idx))
25514
+ idx, 'color', colorCallback(seriesModel.getDataParams(idx))
25269
25515
  );
25270
25516
  });
25271
25517
  }
@@ -26350,6 +26596,9 @@ var theme = {
26350
26596
  },
26351
26597
  crossStyle: {
26352
26598
  color: contrastColor
26599
+ },
26600
+ label: {
26601
+ color: '#000'
26353
26602
  }
26354
26603
  }
26355
26604
  },
@@ -27320,10 +27569,10 @@ var isFunction = isFunction$1;
27320
27569
  var isObject = isObject$1;
27321
27570
  var parseClassType = ComponentModel.parseClassType;
27322
27571
 
27323
- var version = '4.5.0';
27572
+ var version = '4.6.0';
27324
27573
 
27325
27574
  var dependencies = {
27326
- zrender: '4.1.2'
27575
+ zrender: '4.2.0'
27327
27576
  };
27328
27577
 
27329
27578
  var TEST_FRAME_REMAIN_TIME = 1;
@@ -30030,6 +30279,138 @@ function mayLabelDimType(dimType) {
30030
30279
  * under the License.
30031
30280
  */
30032
30281
 
30282
+ /**
30283
+ * @class
30284
+ * @param {Object|DataDimensionInfo} [opt] All of the fields will be shallow copied.
30285
+ */
30286
+ function DataDimensionInfo(opt) {
30287
+ if (opt != null) {
30288
+ extend(this, opt);
30289
+ }
30290
+
30291
+ /**
30292
+ * Dimension name.
30293
+ * Mandatory.
30294
+ * @type {string}
30295
+ */
30296
+ // this.name;
30297
+
30298
+ /**
30299
+ * The origin name in dimsDef, see source helper.
30300
+ * If displayName given, the tooltip will displayed vertically.
30301
+ * Optional.
30302
+ * @type {string}
30303
+ */
30304
+ // this.displayName;
30305
+
30306
+ /**
30307
+ * Which coordSys dimension this dimension mapped to.
30308
+ * A `coordDim` can be a "coordSysDim" that the coordSys required
30309
+ * (for example, an item in `coordSysDims` of `model/referHelper#CoordSysInfo`),
30310
+ * or an generated "extra coord name" if does not mapped to any "coordSysDim"
30311
+ * (That is determined by whether `isExtraCoord` is `true`).
30312
+ * Mandatory.
30313
+ * @type {string}
30314
+ */
30315
+ // this.coordDim;
30316
+
30317
+ /**
30318
+ * The index of this dimension in `series.encode[coordDim]`.
30319
+ * Mandatory.
30320
+ * @type {number}
30321
+ */
30322
+ // this.coordDimIndex;
30323
+
30324
+ /**
30325
+ * Dimension type. The enumerable values are the key of
30326
+ * `dataCtors` of `data/List`.
30327
+ * Optional.
30328
+ * @type {string}
30329
+ */
30330
+ // this.type;
30331
+
30332
+ /**
30333
+ * This index of this dimension info in `data/List#_dimensionInfos`.
30334
+ * Mandatory after added to `data/List`.
30335
+ * @type {number}
30336
+ */
30337
+ // this.index;
30338
+
30339
+ /**
30340
+ * The format of `otherDims` is:
30341
+ * ```js
30342
+ * {
30343
+ * tooltip: number optional,
30344
+ * label: number optional,
30345
+ * itemName: number optional,
30346
+ * seriesName: number optional,
30347
+ * }
30348
+ * ```
30349
+ *
30350
+ * A `series.encode` can specified these fields:
30351
+ * ```js
30352
+ * encode: {
30353
+ * // "3, 1, 5" is the index of data dimension.
30354
+ * tooltip: [3, 1, 5],
30355
+ * label: [0, 3],
30356
+ * ...
30357
+ * }
30358
+ * ```
30359
+ * `otherDims` is the parse result of the `series.encode` above, like:
30360
+ * ```js
30361
+ * // Suppose the index of this data dimension is `3`.
30362
+ * this.otherDims = {
30363
+ * // `3` is at the index `0` of the `encode.tooltip`
30364
+ * tooltip: 0,
30365
+ * // `3` is at the index `1` of the `encode.tooltip`
30366
+ * label: 1
30367
+ * };
30368
+ * ```
30369
+ *
30370
+ * This prop should never be `null`/`undefined` after initialized.
30371
+ * @type {Object}
30372
+ */
30373
+ this.otherDims = {};
30374
+
30375
+ /**
30376
+ * Be `true` if this dimension is not mapped to any "coordSysDim" that the
30377
+ * "coordSys" required.
30378
+ * Mandatory.
30379
+ * @type {boolean}
30380
+ */
30381
+ // this.isExtraCoord;
30382
+
30383
+ /**
30384
+ * @type {module:data/OrdinalMeta}
30385
+ */
30386
+ // this.ordinalMeta;
30387
+
30388
+ /**
30389
+ * Whether to create inverted indices.
30390
+ * @type {boolean}
30391
+ */
30392
+ // this.createInvertedIndices;
30393
+ }
30394
+
30395
+ /*
30396
+ * Licensed to the Apache Software Foundation (ASF) under one
30397
+ * or more contributor license agreements. See the NOTICE file
30398
+ * distributed with this work for additional information
30399
+ * regarding copyright ownership. The ASF licenses this file
30400
+ * to you under the Apache License, Version 2.0 (the
30401
+ * "License"); you may not use this file except in compliance
30402
+ * with the License. You may obtain a copy of the License at
30403
+ *
30404
+ * http://www.apache.org/licenses/LICENSE-2.0
30405
+ *
30406
+ * Unless required by applicable law or agreed to in writing,
30407
+ * software distributed under the License is distributed on an
30408
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
30409
+ * KIND, either express or implied. See the License for the
30410
+ * specific language governing permissions and limitations
30411
+ * under the License.
30412
+ */
30413
+
30033
30414
  /* global Float64Array, Int32Array, Uint32Array, Uint16Array */
30034
30415
 
30035
30416
  /**
@@ -30107,13 +30488,9 @@ function transferProperties(target, source) {
30107
30488
  * @constructor
30108
30489
  * @alias module:echarts/data/List
30109
30490
  *
30110
- * @param {Array.<string|Object>} dimensions
30491
+ * @param {Array.<string|Object|module:data/DataDimensionInfo>} dimensions
30111
30492
  * For example, ['someDimName', {name: 'someDimName', type: 'someDimType'}, ...].
30112
30493
  * Dimensions should be concrete names like x, y, z, lng, lat, angle, radius
30113
- * Spetial fields: {
30114
- * ordinalMeta: <module:echarts/data/OrdinalMeta>
30115
- * createInvertedIndices: <boolean>
30116
- * }
30117
30494
  * @param {module:echarts/model/Model} hostModel
30118
30495
  */
30119
30496
  var List = function (dimensions, hostModel) {
@@ -30129,7 +30506,10 @@ var List = function (dimensions, hostModel) {
30129
30506
  var dimensionInfo = dimensions[i];
30130
30507
 
30131
30508
  if (isString(dimensionInfo)) {
30132
- dimensionInfo = {name: dimensionInfo};
30509
+ dimensionInfo = new DataDimensionInfo({name: dimensionInfo});
30510
+ }
30511
+ else if (!(dimensionInfo instanceof DataDimensionInfo)) {
30512
+ dimensionInfo = new DataDimensionInfo(dimensionInfo);
30133
30513
  }
30134
30514
 
30135
30515
  var dimensionName = dimensionInfo.name;
@@ -31149,7 +31529,8 @@ listProto.indexOfRawIndex = function (rawIndex) {
31149
31529
  * @param {string} dim
31150
31530
  * @param {number} value
31151
31531
  * @param {number} [maxDistance=Infinity]
31152
- * @return {Array.<number>} Considere multiple points has the same value.
31532
+ * @return {Array.<number>} If and only if multiple indices has
31533
+ * the same value, they are put to the result.
31153
31534
  */
31154
31535
  listProto.indicesOfNearest = function (dim, value, maxDistance) {
31155
31536
  var storage = this._storage;
@@ -31164,23 +31545,35 @@ listProto.indicesOfNearest = function (dim, value, maxDistance) {
31164
31545
  maxDistance = Infinity;
31165
31546
  }
31166
31547
 
31167
- var minDist = Number.MAX_VALUE;
31548
+ var minDist = Infinity;
31168
31549
  var minDiff = -1;
31550
+ var nearestIndicesLen = 0;
31551
+
31552
+ // Check the test case of `test/ut/spec/data/List.js`.
31169
31553
  for (var i = 0, len = this.count(); i < len; i++) {
31170
- var diff = value - this.get(dim, i /*, stack */);
31554
+ var diff = value - this.get(dim, i);
31171
31555
  var dist = Math.abs(diff);
31172
- if (diff <= maxDistance && dist <= minDist) {
31173
- // For the case of two data are same on xAxis, which has sequence data.
31174
- // Show the nearest index
31175
- // https://github.com/ecomfe/echarts/issues/2869
31176
- if (dist < minDist || (diff >= 0 && minDiff < 0)) {
31556
+ if (dist <= maxDistance) {
31557
+ // When the `value` is at the middle of `this.get(dim, i)` and `this.get(dim, i+1)`,
31558
+ // we'd better not push both of them to `nearestIndices`, otherwise it is easy to
31559
+ // get more than one item in `nearestIndices` (more specifically, in `tooltip`).
31560
+ // So we chose the one that `diff >= 0` in this csae.
31561
+ // But if `this.get(dim, i)` and `this.get(dim, j)` get the same value, both of them
31562
+ // should be push to `nearestIndices`.
31563
+ if (dist < minDist
31564
+ || (dist === minDist && diff >= 0 && minDiff < 0)
31565
+ ) {
31177
31566
  minDist = dist;
31178
31567
  minDiff = diff;
31179
- nearestIndices.length = 0;
31568
+ nearestIndicesLen = 0;
31569
+ }
31570
+ if (diff === minDiff) {
31571
+ nearestIndices[nearestIndicesLen++] = i;
31180
31572
  }
31181
- nearestIndices.push(i);
31182
31573
  }
31183
31574
  }
31575
+ nearestIndices.length = nearestIndicesLen;
31576
+
31184
31577
  return nearestIndices;
31185
31578
  };
31186
31579
 
@@ -32054,8 +32447,12 @@ listProto.CHANGABLE_METHODS = ['filterSelf', 'selectRange'];
32054
32447
  /**
32055
32448
  * @see {module:echarts/test/ut/spec/data/completeDimensions}
32056
32449
  *
32057
- * Complete the dimensions array, by user defined `dimension` and `encode`,
32058
- * and guessing from the data structure.
32450
+ * This method builds the relationship between:
32451
+ * + "what the coord sys or series requires (see `sysDims`)",
32452
+ * + "what the user defines (in `encode` and `dimensions`, see `opt.dimsDef` and `opt.encodeDef`)"
32453
+ * + "what the data source provids (see `source`)".
32454
+ *
32455
+ * Some guess strategy will be adapted if user does not define something.
32059
32456
  * If no 'value' dimension specified, the first no-named dimension will be
32060
32457
  * named as 'value'.
32061
32458
  *
@@ -32071,32 +32468,20 @@ listProto.CHANGABLE_METHODS = ['filterSelf', 'selectRange'];
32071
32468
  * @param {Array.<Object|string>} [opt.dimsDef] option.series.dimensions User defined dimensions
32072
32469
  * For example: ['asdf', {name, type}, ...].
32073
32470
  * @param {Object|HashMap} [opt.encodeDef] option.series.encode {x: 2, y: [3, 1], tooltip: [1, 2], label: 3}
32471
+ * @param {Function} [opt.encodeDefaulter] Called if no `opt.encodeDef` exists.
32472
+ * If not specified, auto find the next available data dim.
32473
+ * param source {module:data/Source}
32474
+ * param dimCount {number}
32475
+ * return {Object} encode Never be `null/undefined`.
32074
32476
  * @param {string} [opt.generateCoord] Generate coord dim with the given name.
32075
- * If not specified, extra dim names will be:
32076
- * 'value', 'value0', 'value1', ...
32477
+ * If not specified, extra dim names will be:
32478
+ * 'value', 'value0', 'value1', ...
32077
32479
  * @param {number} [opt.generateCoordCount] By default, the generated dim name is `generateCoord`.
32078
- * If `generateCoordCount` specified, the generated dim names will be:
32079
- * `generateCoord` + 0, `generateCoord` + 1, ...
32080
- * can be Infinity, indicate that use all of the remain columns.
32480
+ * If `generateCoordCount` specified, the generated dim names will be:
32481
+ * `generateCoord` + 0, `generateCoord` + 1, ...
32482
+ * can be Infinity, indicate that use all of the remain columns.
32081
32483
  * @param {number} [opt.dimCount] If not specified, guess by the first data item.
32082
- * @param {number} [opt.encodeDefaulter] If not specified, auto find the next available data dim.
32083
- * @return {Array.<Object>} [{
32084
- * name: string mandatory,
32085
- * displayName: string, the origin name in dimsDef, see source helper.
32086
- * If displayName given, the tooltip will displayed vertically.
32087
- * coordDim: string mandatory,
32088
- * coordDimIndex: number mandatory,
32089
- * type: string optional,
32090
- * otherDims: { never null/undefined
32091
- * tooltip: number optional,
32092
- * label: number optional,
32093
- * itemName: number optional,
32094
- * seriesName: number optional,
32095
- * },
32096
- * isExtraCoord: boolean true if coord is generated
32097
- * (not specified in encode and not series specified)
32098
- * other props ...
32099
- * }]
32484
+ * @return {Array.<module:data/DataDimensionInfo>}
32100
32485
  */
32101
32486
  function completeDimensions(sysDims, source, opt) {
32102
32487
  if (!Source.isInstance(source)) {
@@ -32106,7 +32491,6 @@ function completeDimensions(sysDims, source, opt) {
32106
32491
  opt = opt || {};
32107
32492
  sysDims = (sysDims || []).slice();
32108
32493
  var dimsDef = (opt.dimsDef || []).slice();
32109
- var encodeDef = createHashMap(opt.encodeDef);
32110
32494
  var dataDimNameMap = createHashMap();
32111
32495
  var coordDimNameMap = createHashMap();
32112
32496
  // var valueCandidate;
@@ -32120,7 +32504,7 @@ function completeDimensions(sysDims, source, opt) {
32120
32504
  {}, isObject$1(dimsDef[i]) ? dimsDef[i] : {name: dimsDef[i]}
32121
32505
  );
32122
32506
  var userDimName = dimDefItem.name;
32123
- var resultItem = result[i] = {otherDims: {}};
32507
+ var resultItem = result[i] = new DataDimensionInfo();
32124
32508
  // Name will be applied later for avoiding duplication.
32125
32509
  if (userDimName != null && dataDimNameMap.get(userDimName) == null) {
32126
32510
  // Only if `series.dimensions` is defined in option
@@ -32133,6 +32517,12 @@ function completeDimensions(sysDims, source, opt) {
32133
32517
  dimDefItem.displayName != null && (resultItem.displayName = dimDefItem.displayName);
32134
32518
  }
32135
32519
 
32520
+ var encodeDef = opt.encodeDef;
32521
+ if (!encodeDef && opt.encodeDefaulter) {
32522
+ encodeDef = opt.encodeDefaulter(source, dimCount);
32523
+ }
32524
+ encodeDef = createHashMap(encodeDef);
32525
+
32136
32526
  // Set `coordDim` and `coordDimIndex` by `encodeDef` and normalize `encodeDef`.
32137
32527
  encodeDef.each(function (dataDims, coordDim) {
32138
32528
  dataDims = normalizeToArray(dataDims).slice();
@@ -32234,7 +32624,7 @@ function completeDimensions(sysDims, source, opt) {
32234
32624
 
32235
32625
  // Set dim `name` and other `coordDim` and other props.
32236
32626
  for (var resultDimIdx = 0; resultDimIdx < dimCount; resultDimIdx++) {
32237
- var resultItem = result[resultDimIdx] = result[resultDimIdx] || {};
32627
+ var resultItem = result[resultDimIdx] = result[resultDimIdx] || new DataDimensionInfo();
32238
32628
  var coordDim = resultItem.coordDim;
32239
32629
 
32240
32630
  if (coordDim == null) {
@@ -32253,7 +32643,28 @@ function completeDimensions(sysDims, source, opt) {
32253
32643
  dataDimNameMap
32254
32644
  ));
32255
32645
 
32256
- if (resultItem.type == null && guessOrdinal(source, resultDimIdx, resultItem.name)) {
32646
+ if (resultItem.type == null
32647
+ && (
32648
+ guessOrdinal(source, resultDimIdx, resultItem.name) === BE_ORDINAL.Must
32649
+ // Consider the case:
32650
+ // {
32651
+ // dataset: {source: [
32652
+ // ['2001', 123],
32653
+ // ['2002', 456],
32654
+ // ...
32655
+ // ['The others', 987],
32656
+ // ]},
32657
+ // series: {type: 'pie'}
32658
+ // }
32659
+ // The first colum should better be treated as a "ordinal" although it
32660
+ // might not able to be detected as an "ordinal" by `guessOrdinal`.
32661
+ || (resultItem.isExtraCoord
32662
+ && (resultItem.otherDims.itemName != null
32663
+ || resultItem.otherDims.seriesName != null
32664
+ )
32665
+ )
32666
+ )
32667
+ ) {
32257
32668
  resultItem.type = 'ordinal';
32258
32669
  }
32259
32670
  }
@@ -32331,6 +32742,7 @@ function genName(name, map$$1, fromZero) {
32331
32742
  * @param {string} [opt.generateCoordCount]
32332
32743
  * @param {Array.<string|Object>} [opt.dimensionsDefine=source.dimensionsDefine] Overwrite source define.
32333
32744
  * @param {Object|HashMap} [opt.encodeDefine=source.encodeDefine] Overwrite source define.
32745
+ * @param {Function} [opt.encodeDefaulter] Make default encode if user not specified.
32334
32746
  * @return {Array.<Object>} dimensionsInfo
32335
32747
  */
32336
32748
  var createDimensions = function (source, opt) {
@@ -32339,6 +32751,7 @@ var createDimensions = function (source, opt) {
32339
32751
  dimsDef: opt.dimensionsDefine || source.dimensionsDefine,
32340
32752
  encodeDef: opt.encodeDefine || source.encodeDefine,
32341
32753
  dimCount: opt.dimensionsCount,
32754
+ encodeDefaulter: opt.encodeDefaulter,
32342
32755
  generateCoord: opt.generateCoord,
32343
32756
  generateCoordCount: opt.generateCoordCount
32344
32757
  });
@@ -32363,6 +32776,201 @@ var createDimensions = function (source, opt) {
32363
32776
  * under the License.
32364
32777
  */
32365
32778
 
32779
+ /**
32780
+ * Helper for model references.
32781
+ * There are many manners to refer axis/coordSys.
32782
+ */
32783
+
32784
+ // TODO
32785
+ // merge relevant logic to this file?
32786
+ // check: "modelHelper" of tooltip and "BrushTargetManager".
32787
+
32788
+ /**
32789
+ * @class
32790
+ * For example:
32791
+ * {
32792
+ * coordSysName: 'cartesian2d',
32793
+ * coordSysDims: ['x', 'y', ...],
32794
+ * axisMap: HashMap({
32795
+ * x: xAxisModel,
32796
+ * y: yAxisModel
32797
+ * }),
32798
+ * categoryAxisMap: HashMap({
32799
+ * x: xAxisModel,
32800
+ * y: undefined
32801
+ * }),
32802
+ * // The index of the first category axis in `coordSysDims`.
32803
+ * // `null/undefined` means no category axis exists.
32804
+ * firstCategoryDimIndex: 1,
32805
+ * // To replace user specified encode.
32806
+ * }
32807
+ */
32808
+ function CoordSysInfo(coordSysName) {
32809
+ /**
32810
+ * @type {string}
32811
+ */
32812
+ this.coordSysName = coordSysName;
32813
+ /**
32814
+ * @type {Array.<string>}
32815
+ */
32816
+ this.coordSysDims = [];
32817
+ /**
32818
+ * @type {module:zrender/core/util#HashMap}
32819
+ */
32820
+ this.axisMap = createHashMap();
32821
+ /**
32822
+ * @type {module:zrender/core/util#HashMap}
32823
+ */
32824
+ this.categoryAxisMap = createHashMap();
32825
+ /**
32826
+ * @type {number}
32827
+ */
32828
+ this.firstCategoryDimIndex = null;
32829
+ }
32830
+
32831
+ /**
32832
+ * @return {module:model/referHelper#CoordSysInfo}
32833
+ */
32834
+ function getCoordSysInfoBySeries(seriesModel) {
32835
+ var coordSysName = seriesModel.get('coordinateSystem');
32836
+ var result = new CoordSysInfo(coordSysName);
32837
+ var fetch = fetchers[coordSysName];
32838
+ if (fetch) {
32839
+ fetch(seriesModel, result, result.axisMap, result.categoryAxisMap);
32840
+ return result;
32841
+ }
32842
+ }
32843
+
32844
+ var fetchers = {
32845
+
32846
+ cartesian2d: function (seriesModel, result, axisMap, categoryAxisMap) {
32847
+ var xAxisModel = seriesModel.getReferringComponents('xAxis')[0];
32848
+ var yAxisModel = seriesModel.getReferringComponents('yAxis')[0];
32849
+
32850
+ if (__DEV__) {
32851
+ if (!xAxisModel) {
32852
+ throw new Error('xAxis "' + retrieve(
32853
+ seriesModel.get('xAxisIndex'),
32854
+ seriesModel.get('xAxisId'),
32855
+ 0
32856
+ ) + '" not found');
32857
+ }
32858
+ if (!yAxisModel) {
32859
+ throw new Error('yAxis "' + retrieve(
32860
+ seriesModel.get('xAxisIndex'),
32861
+ seriesModel.get('yAxisId'),
32862
+ 0
32863
+ ) + '" not found');
32864
+ }
32865
+ }
32866
+
32867
+ result.coordSysDims = ['x', 'y'];
32868
+ axisMap.set('x', xAxisModel);
32869
+ axisMap.set('y', yAxisModel);
32870
+
32871
+ if (isCategory(xAxisModel)) {
32872
+ categoryAxisMap.set('x', xAxisModel);
32873
+ result.firstCategoryDimIndex = 0;
32874
+ }
32875
+ if (isCategory(yAxisModel)) {
32876
+ categoryAxisMap.set('y', yAxisModel);
32877
+ result.firstCategoryDimIndex == null & (result.firstCategoryDimIndex = 1);
32878
+ }
32879
+ },
32880
+
32881
+ singleAxis: function (seriesModel, result, axisMap, categoryAxisMap) {
32882
+ var singleAxisModel = seriesModel.getReferringComponents('singleAxis')[0];
32883
+
32884
+ if (__DEV__) {
32885
+ if (!singleAxisModel) {
32886
+ throw new Error('singleAxis should be specified.');
32887
+ }
32888
+ }
32889
+
32890
+ result.coordSysDims = ['single'];
32891
+ axisMap.set('single', singleAxisModel);
32892
+
32893
+ if (isCategory(singleAxisModel)) {
32894
+ categoryAxisMap.set('single', singleAxisModel);
32895
+ result.firstCategoryDimIndex = 0;
32896
+ }
32897
+ },
32898
+
32899
+ polar: function (seriesModel, result, axisMap, categoryAxisMap) {
32900
+ var polarModel = seriesModel.getReferringComponents('polar')[0];
32901
+ var radiusAxisModel = polarModel.findAxisModel('radiusAxis');
32902
+ var angleAxisModel = polarModel.findAxisModel('angleAxis');
32903
+
32904
+ if (__DEV__) {
32905
+ if (!angleAxisModel) {
32906
+ throw new Error('angleAxis option not found');
32907
+ }
32908
+ if (!radiusAxisModel) {
32909
+ throw new Error('radiusAxis option not found');
32910
+ }
32911
+ }
32912
+
32913
+ result.coordSysDims = ['radius', 'angle'];
32914
+ axisMap.set('radius', radiusAxisModel);
32915
+ axisMap.set('angle', angleAxisModel);
32916
+
32917
+ if (isCategory(radiusAxisModel)) {
32918
+ categoryAxisMap.set('radius', radiusAxisModel);
32919
+ result.firstCategoryDimIndex = 0;
32920
+ }
32921
+ if (isCategory(angleAxisModel)) {
32922
+ categoryAxisMap.set('angle', angleAxisModel);
32923
+ result.firstCategoryDimIndex == null && (result.firstCategoryDimIndex = 1);
32924
+ }
32925
+ },
32926
+
32927
+ geo: function (seriesModel, result, axisMap, categoryAxisMap) {
32928
+ result.coordSysDims = ['lng', 'lat'];
32929
+ },
32930
+
32931
+ parallel: function (seriesModel, result, axisMap, categoryAxisMap) {
32932
+ var ecModel = seriesModel.ecModel;
32933
+ var parallelModel = ecModel.getComponent(
32934
+ 'parallel', seriesModel.get('parallelIndex')
32935
+ );
32936
+ var coordSysDims = result.coordSysDims = parallelModel.dimensions.slice();
32937
+
32938
+ each$1(parallelModel.parallelAxisIndex, function (axisIndex, index) {
32939
+ var axisModel = ecModel.getComponent('parallelAxis', axisIndex);
32940
+ var axisDim = coordSysDims[index];
32941
+ axisMap.set(axisDim, axisModel);
32942
+
32943
+ if (isCategory(axisModel) && result.firstCategoryDimIndex == null) {
32944
+ categoryAxisMap.set(axisDim, axisModel);
32945
+ result.firstCategoryDimIndex = index;
32946
+ }
32947
+ });
32948
+ }
32949
+ };
32950
+
32951
+ function isCategory(axisModel) {
32952
+ return axisModel.get('type') === 'category';
32953
+ }
32954
+
32955
+ /*
32956
+ * Licensed to the Apache Software Foundation (ASF) under one
32957
+ * or more contributor license agreements. See the NOTICE file
32958
+ * distributed with this work for additional information
32959
+ * regarding copyright ownership. The ASF licenses this file
32960
+ * to you under the Apache License, Version 2.0 (the
32961
+ * "License"); you may not use this file except in compliance
32962
+ * with the License. You may obtain a copy of the License at
32963
+ *
32964
+ * http://www.apache.org/licenses/LICENSE-2.0
32965
+ *
32966
+ * Unless required by applicable law or agreed to in writing,
32967
+ * software distributed under the License is distributed on an
32968
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
32969
+ * KIND, either express or implied. See the License for the
32970
+ * specific language governing permissions and limitations
32971
+ * under the License.
32972
+ */
32973
+
32366
32974
  /**
32367
32975
  * Note that it is too complicated to support 3d stack by value
32368
32976
  * (have to create two-dimension inverted index), so in 3d case
@@ -32529,6 +33137,7 @@ function getStackedDimension(data, targetDim) {
32529
33137
  * @param {module:echarts/model/Series} seriesModel
32530
33138
  * @param {Object} [opt]
32531
33139
  * @param {string} [opt.generateCoord]
33140
+ * @param {boolean} [opt.useEncodeDefaulter]
32532
33141
  */
32533
33142
  function createListFromArray(source, seriesModel, opt) {
32534
33143
  opt = opt || {};
@@ -32540,14 +33149,14 @@ function createListFromArray(source, seriesModel, opt) {
32540
33149
  var coordSysName = seriesModel.get('coordinateSystem');
32541
33150
  var registeredCoordSys = CoordinateSystemManager.get(coordSysName);
32542
33151
 
32543
- var coordSysDefine = getCoordSysDefineBySeries(seriesModel);
33152
+ var coordSysInfo = getCoordSysInfoBySeries(seriesModel);
32544
33153
 
32545
33154
  var coordSysDimDefs;
32546
33155
 
32547
- if (coordSysDefine) {
32548
- coordSysDimDefs = map(coordSysDefine.coordSysDims, function (dim) {
33156
+ if (coordSysInfo) {
33157
+ coordSysDimDefs = map(coordSysInfo.coordSysDims, function (dim) {
32549
33158
  var dimInfo = {name: dim};
32550
- var axisModel = coordSysDefine.axisMap.get(dim);
33159
+ var axisModel = coordSysInfo.axisMap.get(dim);
32551
33160
  if (axisModel) {
32552
33161
  var axisType = axisModel.get('type');
32553
33162
  dimInfo.type = getDimensionTypeByAxis(axisType);
@@ -32568,14 +33177,17 @@ function createListFromArray(source, seriesModel, opt) {
32568
33177
 
32569
33178
  var dimInfoList = createDimensions(source, {
32570
33179
  coordDimensions: coordSysDimDefs,
32571
- generateCoord: opt.generateCoord
33180
+ generateCoord: opt.generateCoord,
33181
+ encodeDefaulter: opt.useEncodeDefaulter
33182
+ ? curry(makeSeriesEncodeForAxisCoordSys, coordSysDimDefs, seriesModel)
33183
+ : null
32572
33184
  });
32573
33185
 
32574
33186
  var firstCategoryDimIndex;
32575
33187
  var hasNameEncode;
32576
- coordSysDefine && each$1(dimInfoList, function (dimInfo, dimIndex) {
33188
+ coordSysInfo && each$1(dimInfoList, function (dimInfo, dimIndex) {
32577
33189
  var coordDim = dimInfo.coordDim;
32578
- var categoryAxisModel = coordSysDefine.categoryAxisMap.get(coordDim);
33190
+ var categoryAxisModel = coordSysInfo.categoryAxisMap.get(coordDim);
32579
33191
  if (categoryAxisModel) {
32580
33192
  if (firstCategoryDimIndex == null) {
32581
33193
  firstCategoryDimIndex = dimIndex;
@@ -33147,44 +33759,6 @@ function fixExtent(niceTickExtent, extent) {
33147
33759
  }
33148
33760
  }
33149
33761
 
33150
- function intervalScaleGetTicks(interval, extent, niceTickExtent, intervalPrecision) {
33151
- var ticks = [];
33152
-
33153
- // If interval is 0, return [];
33154
- if (!interval) {
33155
- return ticks;
33156
- }
33157
-
33158
- // Consider this case: using dataZoom toolbox, zoom and zoom.
33159
- var safeLimit = 10000;
33160
-
33161
- if (extent[0] < niceTickExtent[0]) {
33162
- ticks.push(extent[0]);
33163
- }
33164
- var tick = niceTickExtent[0];
33165
-
33166
- while (tick <= niceTickExtent[1]) {
33167
- ticks.push(tick);
33168
- // Avoid rounding error
33169
- tick = roundNumber$1(tick + interval, intervalPrecision);
33170
- if (tick === ticks[ticks.length - 1]) {
33171
- // Consider out of safe float point, e.g.,
33172
- // -3711126.9907707 + 2e-10 === -3711126.9907707
33173
- break;
33174
- }
33175
- if (ticks.length > safeLimit) {
33176
- return [];
33177
- }
33178
- }
33179
- // Consider this case: the last item of ticks is smaller
33180
- // than niceTickExtent[1] and niceTickExtent[1] === extent[1].
33181
- if (extent[1] > (ticks.length ? ticks[ticks.length - 1] : niceTickExtent[1])) {
33182
- ticks.push(extent[1]);
33183
- }
33184
-
33185
- return ticks;
33186
- }
33187
-
33188
33762
  /*
33189
33763
  * Licensed to the Apache Software Foundation (ASF) under one
33190
33764
  * or more contributor license agreements. See the NOTICE file
@@ -33263,12 +33837,92 @@ var IntervalScale = Scale.extend({
33263
33837
  },
33264
33838
 
33265
33839
  /**
33840
+ * @param {boolean} [expandToNicedExtent=false] If expand the ticks to niced extent.
33266
33841
  * @return {Array.<number>}
33267
33842
  */
33268
- getTicks: function () {
33269
- return intervalScaleGetTicks(
33270
- this._interval, this._extent, this._niceExtent, this._intervalPrecision
33271
- );
33843
+ getTicks: function (expandToNicedExtent) {
33844
+ var interval = this._interval;
33845
+ var extent = this._extent;
33846
+ var niceTickExtent = this._niceExtent;
33847
+ var intervalPrecision = this._intervalPrecision;
33848
+
33849
+ var ticks = [];
33850
+ // If interval is 0, return [];
33851
+ if (!interval) {
33852
+ return ticks;
33853
+ }
33854
+
33855
+ // Consider this case: using dataZoom toolbox, zoom and zoom.
33856
+ var safeLimit = 10000;
33857
+
33858
+ if (extent[0] < niceTickExtent[0]) {
33859
+ if (expandToNicedExtent) {
33860
+ ticks.push(roundNumber(niceTickExtent[0] - interval));
33861
+ }
33862
+ else {
33863
+ ticks.push(extent[0]);
33864
+ }
33865
+ }
33866
+ var tick = niceTickExtent[0];
33867
+
33868
+ while (tick <= niceTickExtent[1]) {
33869
+ ticks.push(tick);
33870
+ // Avoid rounding error
33871
+ tick = roundNumber(tick + interval, intervalPrecision);
33872
+ if (tick === ticks[ticks.length - 1]) {
33873
+ // Consider out of safe float point, e.g.,
33874
+ // -3711126.9907707 + 2e-10 === -3711126.9907707
33875
+ break;
33876
+ }
33877
+ if (ticks.length > safeLimit) {
33878
+ return [];
33879
+ }
33880
+ }
33881
+ // Consider this case: the last item of ticks is smaller
33882
+ // than niceTickExtent[1] and niceTickExtent[1] === extent[1].
33883
+ var lastNiceTick = ticks.length ? ticks[ticks.length - 1] : niceTickExtent[1];
33884
+ if (extent[1] > lastNiceTick) {
33885
+ if (expandToNicedExtent) {
33886
+ ticks.push(lastNiceTick + interval);
33887
+ }
33888
+ else {
33889
+ ticks.push(extent[1]);
33890
+ }
33891
+ }
33892
+
33893
+ return ticks;
33894
+ },
33895
+
33896
+ /**
33897
+ * @param {number} [splitNumber=5]
33898
+ * @return {Array.<Array.<number>>}
33899
+ */
33900
+ getMinorTicks: function (splitNumber) {
33901
+ var ticks = this.getTicks(true);
33902
+ var minorTicks = [];
33903
+ var extent = this.getExtent();
33904
+
33905
+ for (var i = 1; i < ticks.length; i++) {
33906
+ var nextTick = ticks[i];
33907
+ var prevTick = ticks[i - 1];
33908
+ var count = 0;
33909
+ var minorTicksGroup = [];
33910
+ var interval = nextTick - prevTick;
33911
+ var minorInterval = interval / splitNumber;
33912
+
33913
+ while (count < splitNumber - 1) {
33914
+ var minorTick = round$1(prevTick + (count + 1) * minorInterval);
33915
+
33916
+ // For the first and last interval. The count may be less than splitNumber.
33917
+ if (minorTick > extent[0] && minorTick < extent[1]) {
33918
+ minorTicksGroup.push(minorTick);
33919
+ }
33920
+ count++;
33921
+ }
33922
+ minorTicks.push(minorTicksGroup);
33923
+ }
33924
+
33925
+ return minorTicks;
33272
33926
  },
33273
33927
 
33274
33928
  /**
@@ -33607,7 +34261,6 @@ function doCalBarWidthAndOffset(seriesInfoList) {
33607
34261
  // only the attributes set on the last series will work.
33608
34262
  // Do not change this fact unless there will be a break change.
33609
34263
 
33610
- // TODO
33611
34264
  var barWidth = seriesInfo.barWidth;
33612
34265
  if (barWidth && !stacks[stackId].width) {
33613
34266
  // See #6312, do not restrict width.
@@ -33647,6 +34300,7 @@ function doCalBarWidthAndOffset(seriesInfoList) {
33647
34300
  each$1(stacks, function (column) {
33648
34301
  var maxWidth = column.maxWidth;
33649
34302
  var minWidth = column.minWidth;
34303
+
33650
34304
  if (!column.width) {
33651
34305
  var finalWidth = autoWidth;
33652
34306
  if (maxWidth && maxWidth < finalWidth) {
@@ -33662,7 +34316,7 @@ function doCalBarWidthAndOffset(seriesInfoList) {
33662
34316
  }
33663
34317
  if (finalWidth !== autoWidth) {
33664
34318
  column.width = finalWidth;
33665
- remainedWidth -= finalWidth;
34319
+ remainedWidth -= finalWidth + barGapPercent * finalWidth;
33666
34320
  autoWidthCount--;
33667
34321
  }
33668
34322
  }
@@ -33679,7 +34333,7 @@ function doCalBarWidthAndOffset(seriesInfoList) {
33679
34333
  finalWidth = Math.max(finalWidth, minWidth);
33680
34334
  }
33681
34335
  column.width = finalWidth;
33682
- remainedWidth -= finalWidth;
34336
+ remainedWidth -= finalWidth + barGapPercent * finalWidth;
33683
34337
  autoWidthCount--;
33684
34338
  }
33685
34339
  });
@@ -33687,8 +34341,10 @@ function doCalBarWidthAndOffset(seriesInfoList) {
33687
34341
  // Recalculate width again
33688
34342
  autoWidth = (remainedWidth - categoryGap)
33689
34343
  / (autoWidthCount + (autoWidthCount - 1) * barGapPercent);
34344
+
33690
34345
  autoWidth = Math.max(autoWidth, 0);
33691
34346
 
34347
+
33692
34348
  var widthSum = 0;
33693
34349
  var lastColumn;
33694
34350
  each$1(stacks, function (column, idx) {
@@ -33827,6 +34483,7 @@ function layout(seriesType, ecModel) {
33827
34483
  }
33828
34484
  stacked && (lastStackCoords[stackId][baseValue][sign] += height);
33829
34485
  }
34486
+
33830
34487
  data.setItemLayout(idx, {
33831
34488
  x: x,
33832
34489
  y: y,
@@ -34187,14 +34844,15 @@ var LogScale = Scale.extend({
34187
34844
  },
34188
34845
 
34189
34846
  /**
34847
+ * @param {boolean} [expandToNicedExtent=false] If expand the ticks to niced extent.
34190
34848
  * @return {Array.<number>}
34191
34849
  */
34192
- getTicks: function () {
34850
+ getTicks: function (expandToNicedExtent) {
34193
34851
  var originalScale = this._originalScale;
34194
34852
  var extent = this._extent;
34195
34853
  var originalExtent = originalScale.getExtent();
34196
34854
 
34197
- return map(intervalScaleProto$1.getTicks.call(this), function (val) {
34855
+ return map(intervalScaleProto$1.getTicks.call(this, expandToNicedExtent), function (val) {
34198
34856
  var powVal = round$1(mathPow$1(this.base, val));
34199
34857
 
34200
34858
  // Fix #4158
@@ -34209,6 +34867,12 @@ var LogScale = Scale.extend({
34209
34867
  }, this);
34210
34868
  },
34211
34869
 
34870
+ /**
34871
+ * @param {number} splitNumber
34872
+ * @return {Array.<Array.<number>>}
34873
+ */
34874
+ getMinorTicks: intervalScaleProto$1.getMinorTicks,
34875
+
34212
34876
  /**
34213
34877
  * @param {number} val
34214
34878
  * @return {string}
@@ -36072,7 +36736,7 @@ Axis.prototype = {
36072
36736
  * @return {boolean}
36073
36737
  */
36074
36738
  containData: function (data) {
36075
- return this.contain(this.dataToCoord(data));
36739
+ return this.scale.contain(data);
36076
36740
  },
36077
36741
 
36078
36742
  /**
@@ -36160,7 +36824,7 @@ Axis.prototype = {
36160
36824
  * `axis.getTicksCoords` considers `onBand`, which is used by
36161
36825
  * `boundaryGap:true` of category axis and splitLine and splitArea.
36162
36826
  * @param {Object} [opt]
36163
- * @param {number} [opt.tickModel=axis.model.getModel('axisTick')]
36827
+ * @param {Model} [opt.tickModel=axis.model.getModel('axisTick')]
36164
36828
  * @param {boolean} [opt.clamp] If `true`, the first and the last
36165
36829
  * tick must be at the axis end points. Otherwise, clip ticks
36166
36830
  * that outside the axis extent.
@@ -36192,6 +36856,33 @@ Axis.prototype = {
36192
36856
  return ticksCoords;
36193
36857
  },
36194
36858
 
36859
+ /**
36860
+ * @return {Array.<Array.<Object>>} [{ coord: ..., tickValue: ...}]
36861
+ */
36862
+ getMinorTicksCoords: function () {
36863
+ if (this.scale.type === 'ordinal') {
36864
+ // Category axis doesn't support minor ticks
36865
+ return [];
36866
+ }
36867
+
36868
+ var minorTickModel = this.model.getModel('minorTick');
36869
+ var splitNumber = minorTickModel.get('splitNumber');
36870
+ // Protection.
36871
+ if (!(splitNumber > 0 && splitNumber < 100)) {
36872
+ splitNumber = 5;
36873
+ }
36874
+ var minorTicks = this.scale.getMinorTicks(splitNumber);
36875
+ var minorTicksCoords = map(minorTicks, function (minorTicksGroup) {
36876
+ return map(minorTicksGroup, function (minorTick) {
36877
+ return {
36878
+ coord: this.dataToCoord(minorTick),
36879
+ tickValue: minorTick
36880
+ };
36881
+ }, this);
36882
+ }, this);
36883
+ return minorTicksCoords;
36884
+ },
36885
+
36195
36886
  /**
36196
36887
  * @return {Array.<Object>} [{
36197
36888
  * formattedLabel: string,
@@ -36434,7 +37125,7 @@ SeriesModel.extend({
36434
37125
  throw new Error('Line not support coordinateSystem besides cartesian and polar');
36435
37126
  }
36436
37127
  }
36437
- return createListFromArray(this.getSource(), this);
37128
+ return createListFromArray(this.getSource(), this, {useEncodeDefaulter: true});
36438
37129
  },
36439
37130
 
36440
37131
  defaultOption: {
@@ -38278,7 +38969,7 @@ Chart.extend({
38278
38969
  // FIXME step not support polar
38279
38970
  var step = !isCoordSysPolar && seriesModel.get('step');
38280
38971
  var clipShapeForSymbol;
38281
- if (coordSys && coordSys.getArea) {
38972
+ if (coordSys && coordSys.getArea && seriesModel.get('clip', true)) {
38282
38973
  clipShapeForSymbol = coordSys.getArea();
38283
38974
  // Avoid float number rounding error for symbol on the edge of axis extent.
38284
38975
  // See #7913 and `test/dataZoom-clip.html`.
@@ -38293,6 +38984,7 @@ Chart.extend({
38293
38984
  clipShapeForSymbol.r1 += 0.5;
38294
38985
  }
38295
38986
  }
38987
+ this._clipShapeForSymbol = clipShapeForSymbol;
38296
38988
  // Initialization animation or coordinate system changed
38297
38989
  if (
38298
38990
  !(polyline && prevCoordSys.type === coordSys.type && step === this._step)
@@ -38445,6 +39137,10 @@ Chart.extend({
38445
39137
  // Null data
38446
39138
  return;
38447
39139
  }
39140
+ // fix #11360: should't draw symbol outside clipShapeForSymbol
39141
+ if (this._clipShapeForSymbol && !this._clipShapeForSymbol.contain(pt[0], pt[1])) {
39142
+ return;
39143
+ }
38448
39144
  symbol = new SymbolClz$1(data, dataIndex);
38449
39145
  symbol.position = pt;
38450
39146
  symbol.setZ(
@@ -39500,7 +40196,7 @@ axisDefault.valueAxis = merge({
39500
40196
  // scale: false,
39501
40197
 
39502
40198
  // AxisTick and axisLabel and splitLine are caculated based on splitNumber.
39503
- splitNumber: 5
40199
+ splitNumber: 5,
39504
40200
 
39505
40201
  // Interval specifies the span of the ticks is mandatorily.
39506
40202
  // interval: null
@@ -39511,6 +40207,30 @@ axisDefault.valueAxis = merge({
39511
40207
  // Specify max interval when auto calculate tick interval.
39512
40208
  // maxInterval: null
39513
40209
 
40210
+ minorTick: {
40211
+ // Minor tick, not available for cateogry axis.
40212
+ show: false,
40213
+ // Split number of minor ticks. The value should be in range of (0, 100)
40214
+ splitNumber: 5,
40215
+ // Lenght of minor tick
40216
+ length: 3,
40217
+
40218
+ // Same inside with axisTick
40219
+
40220
+ // Line style
40221
+ lineStyle: {
40222
+ // Default to be same with axisTick
40223
+ }
40224
+ },
40225
+
40226
+ minorSplitLine: {
40227
+ show: false,
40228
+
40229
+ lineStyle: {
40230
+ color: '#eee',
40231
+ width: 1
40232
+ }
40233
+ }
39514
40234
  }, defaultOption);
39515
40235
 
39516
40236
  axisDefault.timeAxis = defaults({
@@ -40627,10 +41347,12 @@ var builders = {
40627
41347
  var axisModel = this.axisModel;
40628
41348
  var opt = this.opt;
40629
41349
 
40630
- var tickEls = buildAxisTick(this, axisModel, opt);
41350
+ var ticksEls = buildAxisMajorTicks(this, axisModel, opt);
40631
41351
  var labelEls = buildAxisLabel(this, axisModel, opt);
40632
41352
 
40633
- fixMinMaxLabelShow(axisModel, labelEls, tickEls);
41353
+ fixMinMaxLabelShow(axisModel, labelEls, ticksEls);
41354
+
41355
+ buildAxisMinorTicks(this, axisModel, opt);
40634
41356
  },
40635
41357
 
40636
41358
  /**
@@ -40949,42 +41671,27 @@ function isNameLocationCenter(nameLocation) {
40949
41671
  return nameLocation === 'middle' || nameLocation === 'center';
40950
41672
  }
40951
41673
 
40952
- function buildAxisTick(axisBuilder, axisModel, opt) {
40953
- var axis = axisModel.axis;
40954
-
40955
- if (!axisModel.get('axisTick.show') || axis.scale.isBlank()) {
40956
- return;
40957
- }
40958
-
40959
- var tickModel = axisModel.getModel('axisTick');
40960
-
40961
- var lineStyleModel = tickModel.getModel('lineStyle');
40962
- var tickLen = tickModel.get('length');
40963
-
40964
- var ticksCoords = axis.getTicksCoords();
40965
41674
 
41675
+ function createTicks(ticksCoords, tickTransform, tickEndCoord, tickLineStyle, aniid) {
41676
+ var tickEls = [];
40966
41677
  var pt1 = [];
40967
41678
  var pt2 = [];
40968
- var matrix = axisBuilder._transform;
40969
-
40970
- var tickEls = [];
40971
-
40972
41679
  for (var i = 0; i < ticksCoords.length; i++) {
40973
41680
  var tickCoord = ticksCoords[i].coord;
40974
41681
 
40975
41682
  pt1[0] = tickCoord;
40976
41683
  pt1[1] = 0;
40977
41684
  pt2[0] = tickCoord;
40978
- pt2[1] = opt.tickDirection * tickLen;
41685
+ pt2[1] = tickEndCoord;
40979
41686
 
40980
- if (matrix) {
40981
- applyTransform(pt1, pt1, matrix);
40982
- applyTransform(pt2, pt2, matrix);
41687
+ if (tickTransform) {
41688
+ applyTransform(pt1, pt1, tickTransform);
41689
+ applyTransform(pt2, pt2, tickTransform);
40983
41690
  }
40984
41691
  // Tick line, Not use group transform to have better line draw
40985
41692
  var tickEl = new Line({
40986
41693
  // Id for animation
40987
- anid: 'tick_' + ticksCoords[i].tickValue,
41694
+ anid: aniid + '_' + ticksCoords[i].tickValue,
40988
41695
  subPixelOptimize: true,
40989
41696
  shape: {
40990
41697
  x1: pt1[0],
@@ -40992,22 +41699,80 @@ function buildAxisTick(axisBuilder, axisModel, opt) {
40992
41699
  x2: pt2[0],
40993
41700
  y2: pt2[1]
40994
41701
  },
40995
- style: defaults(
40996
- lineStyleModel.getLineStyle(),
40997
- {
40998
- stroke: axisModel.get('axisLine.lineStyle.color')
40999
- }
41000
- ),
41702
+ style: tickLineStyle,
41001
41703
  z2: 2,
41002
41704
  silent: true
41003
41705
  });
41004
- axisBuilder.group.add(tickEl);
41005
41706
  tickEls.push(tickEl);
41006
41707
  }
41007
-
41008
41708
  return tickEls;
41009
41709
  }
41010
41710
 
41711
+ function buildAxisMajorTicks(axisBuilder, axisModel, opt) {
41712
+ var axis = axisModel.axis;
41713
+
41714
+ var tickModel = axisModel.getModel('axisTick');
41715
+
41716
+ if (!tickModel.get('show') || axis.scale.isBlank()) {
41717
+ return;
41718
+ }
41719
+
41720
+ var lineStyleModel = tickModel.getModel('lineStyle');
41721
+ var tickEndCoord = opt.tickDirection * tickModel.get('length');
41722
+
41723
+ var ticksCoords = axis.getTicksCoords();
41724
+
41725
+ var ticksEls = createTicks(ticksCoords, axisBuilder._transform, tickEndCoord, defaults(
41726
+ lineStyleModel.getLineStyle(),
41727
+ {
41728
+ stroke: axisModel.get('axisLine.lineStyle.color')
41729
+ }
41730
+ ), 'ticks');
41731
+
41732
+ for (var i = 0; i < ticksEls.length; i++) {
41733
+ axisBuilder.group.add(ticksEls[i]);
41734
+ }
41735
+
41736
+ return ticksEls;
41737
+ }
41738
+
41739
+ function buildAxisMinorTicks(axisBuilder, axisModel, opt) {
41740
+ var axis = axisModel.axis;
41741
+
41742
+ var minorTickModel = axisModel.getModel('minorTick');
41743
+
41744
+ if (!minorTickModel.get('show') || axis.scale.isBlank()) {
41745
+ return;
41746
+ }
41747
+
41748
+ var minorTicksCoords = axis.getMinorTicksCoords();
41749
+ if (!minorTicksCoords.length) {
41750
+ return;
41751
+ }
41752
+
41753
+ var lineStyleModel = minorTickModel.getModel('lineStyle');
41754
+ var tickEndCoord = opt.tickDirection * minorTickModel.get('length');
41755
+
41756
+ var minorTickLineStyle = defaults(
41757
+ lineStyleModel.getLineStyle(),
41758
+ defaults(
41759
+ axisModel.getModel('axisTick').getLineStyle(),
41760
+ {
41761
+ stroke: axisModel.get('axisLine.lineStyle.color')
41762
+ }
41763
+ )
41764
+ );
41765
+
41766
+ for (var i = 0; i < minorTicksCoords.length; i++) {
41767
+ var minorTicksEls = createTicks(
41768
+ minorTicksCoords[i], axisBuilder._transform, tickEndCoord, minorTickLineStyle, 'minorticks_' + i
41769
+ );
41770
+ for (var k = 0; k < minorTicksEls.length; k++) {
41771
+ axisBuilder.group.add(minorTicksEls[k]);
41772
+ }
41773
+ }
41774
+ }
41775
+
41011
41776
  function buildAxisLabel(axisBuilder, axisModel, opt) {
41012
41777
  var axis = axisModel.axis;
41013
41778
  var show = retrieve(opt.axisLabelShow, axisModel.get('axisLabel.show'));
@@ -41676,17 +42441,9 @@ var axisBuilderAttrs = [
41676
42441
  'axisLine', 'axisTickLabel', 'axisName'
41677
42442
  ];
41678
42443
  var selfBuilderAttrs = [
41679
- 'splitArea', 'splitLine'
42444
+ 'splitArea', 'splitLine', 'minorSplitLine'
41680
42445
  ];
41681
42446
 
41682
- // function getAlignWithLabel(model, axisModel) {
41683
- // var alignWithLabel = model.get('alignWithLabel');
41684
- // if (alignWithLabel === 'auto') {
41685
- // alignWithLabel = axisModel.get('axisTick.alignWithLabel');
41686
- // }
41687
- // return alignWithLabel;
41688
- // }
41689
-
41690
42447
  var CartesianAxisView = AxisView.extend({
41691
42448
 
41692
42449
  type: 'cartesianAxis',
@@ -41764,8 +42521,6 @@ var CartesianAxisView = AxisView.extend({
41764
42521
  var p1 = [];
41765
42522
  var p2 = [];
41766
42523
 
41767
- // Simple optimization
41768
- // Batching the lines if color are the same
41769
42524
  var lineStyle = lineStyleModel.getLineStyle();
41770
42525
  for (var i = 0; i < ticksCoords.length; i++) {
41771
42526
  var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);
@@ -41802,6 +42557,63 @@ var CartesianAxisView = AxisView.extend({
41802
42557
  }
41803
42558
  },
41804
42559
 
42560
+ /**
42561
+ * @param {module:echarts/coord/cartesian/AxisModel} axisModel
42562
+ * @param {module:echarts/coord/cartesian/GridModel} gridModel
42563
+ * @private
42564
+ */
42565
+ _minorSplitLine: function (axisModel, gridModel) {
42566
+ var axis = axisModel.axis;
42567
+
42568
+ var minorSplitLineModel = axisModel.getModel('minorSplitLine');
42569
+ var lineStyleModel = minorSplitLineModel.getModel('lineStyle');
42570
+
42571
+ var gridRect = gridModel.coordinateSystem.getRect();
42572
+ var isHorizontal = axis.isHorizontal();
42573
+
42574
+ var minorTicksCoords = axis.getMinorTicksCoords();
42575
+ if (!minorTicksCoords.length) {
42576
+ return;
42577
+ }
42578
+ var p1 = [];
42579
+ var p2 = [];
42580
+
42581
+ var lineStyle = lineStyleModel.getLineStyle();
42582
+
42583
+
42584
+ for (var i = 0; i < minorTicksCoords.length; i++) {
42585
+ for (var k = 0; k < minorTicksCoords[i].length; k++) {
42586
+ var tickCoord = axis.toGlobalCoord(minorTicksCoords[i][k].coord);
42587
+
42588
+ if (isHorizontal) {
42589
+ p1[0] = tickCoord;
42590
+ p1[1] = gridRect.y;
42591
+ p2[0] = tickCoord;
42592
+ p2[1] = gridRect.y + gridRect.height;
42593
+ }
42594
+ else {
42595
+ p1[0] = gridRect.x;
42596
+ p1[1] = tickCoord;
42597
+ p2[0] = gridRect.x + gridRect.width;
42598
+ p2[1] = tickCoord;
42599
+ }
42600
+
42601
+ this._axisGroup.add(new Line({
42602
+ anid: 'minor_line_' + minorTicksCoords[i][k].tickValue,
42603
+ subPixelOptimize: true,
42604
+ shape: {
42605
+ x1: p1[0],
42606
+ y1: p1[1],
42607
+ x2: p2[0],
42608
+ y2: p2[1]
42609
+ },
42610
+ style: lineStyle,
42611
+ silent: true
42612
+ }));
42613
+ }
42614
+ }
42615
+ },
42616
+
41805
42617
  /**
41806
42618
  * @param {module:echarts/coord/cartesian/AxisModel} axisModel
41807
42619
  * @param {module:echarts/coord/cartesian/GridModel} gridModel
@@ -42022,7 +42834,7 @@ var BaseBarSeries = SeriesModel.extend({
42022
42834
  type: 'series.__base_bar__',
42023
42835
 
42024
42836
  getInitialData: function (option, ecModel) {
42025
- return createListFromArray(this.getSource(), this);
42837
+ return createListFromArray(this.getSource(), this, {useEncodeDefaulter: true});
42026
42838
  },
42027
42839
 
42028
42840
  getMarkerPosition: function (value) {
@@ -42726,11 +43538,18 @@ var getLayout = {
42726
43538
  }
42727
43539
  };
42728
43540
 
43541
+ function isZeroOnPolar(layout) {
43542
+ return layout.startAngle != null
43543
+ && layout.endAngle != null
43544
+ && layout.startAngle === layout.endAngle;
43545
+ }
43546
+
42729
43547
  function updateStyle(
42730
43548
  el, data, dataIndex, itemModel, layout, seriesModel, isHorizontal, isPolar
42731
43549
  ) {
42732
43550
  var color = data.getItemVisual(dataIndex, 'color');
42733
43551
  var opacity = data.getItemVisual(dataIndex, 'opacity');
43552
+ var stroke = data.getVisual('borderColor');
42734
43553
  var itemStyleModel = itemModel.getModel('itemStyle');
42735
43554
  var hoverStyle = itemModel.getModel('emphasis.itemStyle').getBarItemStyle();
42736
43555
 
@@ -42740,7 +43559,8 @@ function updateStyle(
42740
43559
 
42741
43560
  el.useStyle(defaults(
42742
43561
  {
42743
- fill: color,
43562
+ stroke: isZeroOnPolar(layout) ? 'none' : stroke,
43563
+ fill: isZeroOnPolar(layout) ? 'none' : color,
42744
43564
  opacity: opacity
42745
43565
  },
42746
43566
  itemStyleModel.getBarItemStyle()
@@ -42759,7 +43579,9 @@ function updateStyle(
42759
43579
  seriesModel, dataIndex, labelPositionOutside
42760
43580
  );
42761
43581
  }
42762
-
43582
+ if (isZeroOnPolar(layout)) {
43583
+ hoverStyle.fill = hoverStyle.stroke = 'none';
43584
+ }
42763
43585
  setHoverStyle(el, hoverStyle);
42764
43586
  }
42765
43587
 
@@ -43080,6 +43902,60 @@ var dataSelectableMixin = {
43080
43902
  * under the License.
43081
43903
  */
43082
43904
 
43905
+
43906
+ /**
43907
+ * LegendVisualProvider is an bridge that pick encoded color from data and
43908
+ * provide to the legend component.
43909
+ * @param {Function} getDataWithEncodedVisual Function to get data after filtered. It stores all the encoding info
43910
+ * @param {Function} getRawData Function to get raw data before filtered.
43911
+ */
43912
+ function LegendVisualProvider(getDataWithEncodedVisual, getRawData) {
43913
+ this.getAllNames = function () {
43914
+ var rawData = getRawData();
43915
+ // We find the name from the raw data. In case it's filtered by the legend component.
43916
+ // Normally, the name can be found in rawData, but can't be found in filtered data will display as gray.
43917
+ return rawData.mapArray(rawData.getName);
43918
+ };
43919
+
43920
+ this.containName = function (name) {
43921
+ var rawData = getRawData();
43922
+ return rawData.indexOfName(name) >= 0;
43923
+ };
43924
+
43925
+ this.indexOfName = function (name) {
43926
+ // Only get data when necessary.
43927
+ // Because LegendVisualProvider constructor may be new in the stage that data is not prepared yet.
43928
+ // Invoking Series#getData immediately will throw an error.
43929
+ var dataWithEncodedVisual = getDataWithEncodedVisual();
43930
+ return dataWithEncodedVisual.indexOfName(name);
43931
+ };
43932
+
43933
+ this.getItemVisual = function (dataIndex, key) {
43934
+ // Get encoded visual properties from final filtered data.
43935
+ var dataWithEncodedVisual = getDataWithEncodedVisual();
43936
+ return dataWithEncodedVisual.getItemVisual(dataIndex, key);
43937
+ };
43938
+ }
43939
+
43940
+ /*
43941
+ * Licensed to the Apache Software Foundation (ASF) under one
43942
+ * or more contributor license agreements. See the NOTICE file
43943
+ * distributed with this work for additional information
43944
+ * regarding copyright ownership. The ASF licenses this file
43945
+ * to you under the Apache License, Version 2.0 (the
43946
+ * "License"); you may not use this file except in compliance
43947
+ * with the License. You may obtain a copy of the License at
43948
+ *
43949
+ * http://www.apache.org/licenses/LICENSE-2.0
43950
+ *
43951
+ * Unless required by applicable law or agreed to in writing,
43952
+ * software distributed under the License is distributed on an
43953
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
43954
+ * KIND, either express or implied. See the License for the
43955
+ * specific language governing permissions and limitations
43956
+ * under the License.
43957
+ */
43958
+
43083
43959
  var PieSeries = extendSeriesModel({
43084
43960
 
43085
43961
  type: 'series.pie',
@@ -43090,9 +43966,9 @@ var PieSeries = extendSeriesModel({
43090
43966
 
43091
43967
  // Enable legend selection for each data item
43092
43968
  // Use a function instead of direct access because data reference may changed
43093
- this.legendDataProvider = function () {
43094
- return this.getRawData();
43095
- };
43969
+ this.legendVisualProvider = new LegendVisualProvider(
43970
+ bind(this.getData, this), bind(this.getRawData, this)
43971
+ );
43096
43972
 
43097
43973
  this.updateSelectedMap(this._createSelectableList());
43098
43974
 
@@ -43107,7 +43983,10 @@ var PieSeries = extendSeriesModel({
43107
43983
  },
43108
43984
 
43109
43985
  getInitialData: function (option, ecModel) {
43110
- return createListSimply(this, ['value']);
43986
+ return createListSimply(this, {
43987
+ coordDimensions: ['value'],
43988
+ encodeDefaulter: curry(makeSeriesEncodeForNameBased, this)
43989
+ });
43111
43990
  },
43112
43991
 
43113
43992
  _createSelectableList: function () {
@@ -43196,12 +44075,28 @@ var PieSeries = extendSeriesModel({
43196
44075
 
43197
44076
  // cursor: null,
43198
44077
 
44078
+ left: 0,
44079
+ top: 0,
44080
+ right: 0,
44081
+ bottom: 0,
44082
+ width: null,
44083
+ height: null,
44084
+
43199
44085
  label: {
43200
44086
  // If rotate around circle
43201
44087
  rotate: false,
43202
44088
  show: true,
43203
44089
  // 'outer', 'inside', 'center'
43204
- position: 'outer'
44090
+ position: 'outer',
44091
+ // 'none', 'labelLine', 'edge'. Works only when position is 'outer'
44092
+ alignTo: 'none',
44093
+ // Closest distance between label and chart edge.
44094
+ // Works only position is 'outer' and alignTo is 'edge'.
44095
+ margin: '25%',
44096
+ // Works only position is 'outer' and alignTo is not 'edge'.
44097
+ bleedMargin: 10,
44098
+ // Distance between text and label line.
44099
+ distanceToLabelLine: 5
43205
44100
  // formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调
43206
44101
  // 默认使用全局文本样式,详见TEXTSTYLE
43207
44102
  // distance: 当position为inner时有效,为label位置到圆心的距离与圆半径(环状图为内外半径和)的比例系数
@@ -43507,7 +44402,7 @@ piePieceProto._updateLabel = function (data, idx, withAnimation) {
43507
44402
  {
43508
44403
  labelFetcher: data.hostModel,
43509
44404
  labelDataIndex: idx,
43510
- defaultText: data.getName(idx),
44405
+ defaultText: labelLayout.text,
43511
44406
  autoColor: visualColor,
43512
44407
  useInsideStyle: !!labelLayout.inside
43513
44408
  },
@@ -43803,33 +44698,20 @@ var dataColor = function (seriesType) {
43803
44698
  dataAll.getName(rawIdx) || (rawIdx + ''), seriesModel.__paletteScope,
43804
44699
  dataAll.count()
43805
44700
  );
43806
- // Legend may use the visual info in data before processed
43807
- dataAll.setItemVisual(rawIdx, 'color', color);
43808
-
43809
44701
  // Data is not filtered
43810
44702
  if (filteredIdx != null) {
43811
44703
  data.setItemVisual(filteredIdx, 'color', color);
43812
44704
  }
43813
44705
  }
43814
- else {
43815
- // Set data all color for legend
43816
- dataAll.setItemVisual(rawIdx, 'color', singleDataColor);
43817
- }
43818
44706
 
43819
44707
  if (!singleDataBorderColor) {
43820
44708
  var borderColor = itemModel.get('itemStyle.borderColor');
43821
- // Legend may use the visual info in data before processed
43822
- dataAll.setItemVisual(rawIdx, 'borderColor', borderColor);
43823
44709
 
43824
44710
  // Data is not filtered
43825
44711
  if (filteredIdx != null) {
43826
44712
  data.setItemVisual(filteredIdx, 'borderColor', borderColor);
43827
44713
  }
43828
44714
  }
43829
- else {
43830
- // Set data all borderColor for legend
43831
- dataAll.setItemVisual(rawIdx, 'borderColor', singleDataBorderColor);
43832
- }
43833
44715
  });
43834
44716
  }
43835
44717
  };
@@ -43858,13 +44740,17 @@ var dataColor = function (seriesType) {
43858
44740
 
43859
44741
  var RADIAN$1 = Math.PI / 180;
43860
44742
 
43861
- function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight) {
44743
+ function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight, viewLeft, viewTop, farthestX) {
43862
44744
  list.sort(function (a, b) {
43863
44745
  return a.y - b.y;
43864
44746
  });
43865
44747
 
43866
44748
  function shiftDown(start, end, delta, dir) {
43867
44749
  for (var j = start; j < end; j++) {
44750
+ if (list[j].y + delta > viewTop + viewHeight) {
44751
+ break;
44752
+ }
44753
+
43868
44754
  list[j].y += delta;
43869
44755
  if (j > start
43870
44756
  && j + 1 < end
@@ -43880,6 +44766,10 @@ function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight) {
43880
44766
 
43881
44767
  function shiftUp(end, delta) {
43882
44768
  for (var j = end; j >= 0; j--) {
44769
+ if (list[j].y - delta < viewTop) {
44770
+ break;
44771
+ }
44772
+
43883
44773
  list[j].y -= delta;
43884
44774
  if (j > 0
43885
44775
  && list[j].y > list[j - 1].y + list[j - 1].height
@@ -43899,6 +44789,10 @@ function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight) {
43899
44789
  : 0; // up
43900
44790
 
43901
44791
  for (var i = 0, l = list.length; i < l; i++) {
44792
+ if (list[i].labelAlignTo !== 'none') {
44793
+ continue;
44794
+ }
44795
+
43902
44796
  var deltaY = Math.abs(list[i].y - cy);
43903
44797
  var length = list[i].len;
43904
44798
  var length2 = list[i].len2;
@@ -43928,6 +44822,12 @@ function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight) {
43928
44822
  var upList = [];
43929
44823
  var downList = [];
43930
44824
  for (var i = 0; i < len; i++) {
44825
+ if (list[i].position === 'outer' && list[i].labelAlignTo === 'labelLine') {
44826
+ var dx = list[i].x - farthestX;
44827
+ list[i].linePoints[1][0] += dx;
44828
+ list[i].x = farthestX;
44829
+ }
44830
+
43931
44831
  delta = list[i].y - lastY;
43932
44832
  if (delta < 0) {
43933
44833
  shiftDown(i, len, -delta, dir);
@@ -43949,39 +44849,85 @@ function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight) {
43949
44849
  changeX(downList, true, cx, cy, r, dir);
43950
44850
  }
43951
44851
 
43952
- function avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight) {
44852
+ function avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight, viewLeft, viewTop) {
43953
44853
  var leftList = [];
43954
44854
  var rightList = [];
44855
+ var leftmostX = Number.MAX_VALUE;
44856
+ var rightmostX = -Number.MAX_VALUE;
43955
44857
  for (var i = 0; i < labelLayoutList.length; i++) {
43956
44858
  if (isPositionCenter(labelLayoutList[i])) {
43957
44859
  continue;
43958
44860
  }
43959
44861
  if (labelLayoutList[i].x < cx) {
44862
+ leftmostX = Math.min(leftmostX, labelLayoutList[i].x);
43960
44863
  leftList.push(labelLayoutList[i]);
43961
44864
  }
43962
44865
  else {
44866
+ rightmostX = Math.max(rightmostX, labelLayoutList[i].x);
43963
44867
  rightList.push(labelLayoutList[i]);
43964
44868
  }
43965
44869
  }
43966
44870
 
43967
- adjustSingleSide(rightList, cx, cy, r, 1, viewWidth, viewHeight);
43968
- adjustSingleSide(leftList, cx, cy, r, -1, viewWidth, viewHeight);
44871
+ adjustSingleSide(rightList, cx, cy, r, 1, viewWidth, viewHeight, viewLeft, viewTop, rightmostX);
44872
+ adjustSingleSide(leftList, cx, cy, r, -1, viewWidth, viewHeight, viewLeft, viewTop, leftmostX);
43969
44873
 
43970
44874
  for (var i = 0; i < labelLayoutList.length; i++) {
43971
- if (isPositionCenter(labelLayoutList[i])) {
44875
+ var layout = labelLayoutList[i];
44876
+ if (isPositionCenter(layout)) {
43972
44877
  continue;
43973
44878
  }
43974
- var linePoints = labelLayoutList[i].linePoints;
44879
+
44880
+ var linePoints = layout.linePoints;
43975
44881
  if (linePoints) {
44882
+ var isAlignToEdge = layout.labelAlignTo === 'edge';
44883
+
44884
+ var realTextWidth = layout.textRect.width;
44885
+ var targetTextWidth;
44886
+ if (isAlignToEdge) {
44887
+ if (layout.x < cx) {
44888
+ targetTextWidth = linePoints[2][0] - layout.labelDistance
44889
+ - viewLeft - layout.labelMargin;
44890
+ }
44891
+ else {
44892
+ targetTextWidth = viewLeft + viewWidth - layout.labelMargin
44893
+ - linePoints[2][0] - layout.labelDistance;
44894
+ }
44895
+ }
44896
+ else {
44897
+ if (layout.x < cx) {
44898
+ targetTextWidth = layout.x - viewLeft - layout.bleedMargin;
44899
+ }
44900
+ else {
44901
+ targetTextWidth = viewLeft + viewWidth - layout.x - layout.bleedMargin;
44902
+ }
44903
+ }
44904
+ if (targetTextWidth < layout.textRect.width) {
44905
+ layout.text = truncateText(layout.text, targetTextWidth, layout.font);
44906
+ if (layout.labelAlignTo === 'edge') {
44907
+ realTextWidth = getWidth(layout.text, layout.font);
44908
+ }
44909
+ }
44910
+
43976
44911
  var dist = linePoints[1][0] - linePoints[2][0];
43977
- if (labelLayoutList[i].x < cx) {
43978
- linePoints[2][0] = labelLayoutList[i].x + 3;
44912
+ if (isAlignToEdge) {
44913
+ if (layout.x < cx) {
44914
+ linePoints[2][0] = viewLeft + layout.labelMargin + realTextWidth + layout.labelDistance;
44915
+ }
44916
+ else {
44917
+ linePoints[2][0] = viewLeft + viewWidth - layout.labelMargin
44918
+ - realTextWidth - layout.labelDistance;
44919
+ }
43979
44920
  }
43980
44921
  else {
43981
- linePoints[2][0] = labelLayoutList[i].x - 3;
44922
+ if (layout.x < cx) {
44923
+ linePoints[2][0] = layout.x + layout.labelDistance;
44924
+ }
44925
+ else {
44926
+ linePoints[2][0] = layout.x - layout.labelDistance;
44927
+ }
44928
+ linePoints[1][0] = linePoints[2][0] + dist;
43982
44929
  }
43983
- linePoints[1][1] = linePoints[2][1] = labelLayoutList[i].y;
43984
- linePoints[1][0] = linePoints[2][0] + dist;
44930
+ linePoints[1][1] = linePoints[2][1] = layout.y;
43985
44931
  }
43986
44932
  }
43987
44933
  }
@@ -43991,7 +44937,7 @@ function isPositionCenter(layout) {
43991
44937
  return layout.position === 'center';
43992
44938
  }
43993
44939
 
43994
- var labelLayout = function (seriesModel, r, viewWidth, viewHeight, sum) {
44940
+ var labelLayout = function (seriesModel, r, viewWidth, viewHeight, viewLeft, viewTop) {
43995
44941
  var data = seriesModel.getData();
43996
44942
  var labelLayoutList = [];
43997
44943
  var cx;
@@ -44006,10 +44952,17 @@ var labelLayout = function (seriesModel, r, viewWidth, viewHeight, sum) {
44006
44952
  var labelModel = itemModel.getModel('label');
44007
44953
  // Use position in normal or emphasis
44008
44954
  var labelPosition = labelModel.get('position') || itemModel.get('emphasis.label.position');
44955
+ var labelDistance = labelModel.get('distanceToLabelLine');
44956
+ var labelAlignTo = labelModel.get('alignTo');
44957
+ var labelMargin = parsePercent$1(labelModel.get('margin'), viewWidth);
44958
+ var bleedMargin = labelModel.get('bleedMargin');
44959
+ var font = labelModel.getFont();
44009
44960
 
44010
44961
  var labelLineModel = itemModel.getModel('labelLine');
44011
44962
  var labelLineLen = labelLineModel.get('length');
44963
+ labelLineLen = parsePercent$1(labelLineLen, viewWidth);
44012
44964
  var labelLineLen2 = labelLineModel.get('length2');
44965
+ labelLineLen2 = parsePercent$1(labelLineLen2, viewWidth);
44013
44966
 
44014
44967
  if (layout.angle < minShowLabelRadian) {
44015
44968
  return;
@@ -44027,6 +44980,12 @@ var labelLayout = function (seriesModel, r, viewWidth, viewHeight, sum) {
44027
44980
  cx = layout.cx;
44028
44981
  cy = layout.cy;
44029
44982
 
44983
+ var text = seriesModel.getFormattedLabel(idx, 'normal')
44984
+ || data.getName(idx);
44985
+ var textRect = getBoundingRect(
44986
+ text, font, textAlign, 'top'
44987
+ );
44988
+
44030
44989
  var isLabelInside = labelPosition === 'inside' || labelPosition === 'inner';
44031
44990
  if (labelPosition === 'center') {
44032
44991
  textX = layout.cx;
@@ -44047,14 +45006,25 @@ var labelLayout = function (seriesModel, r, viewWidth, viewHeight, sum) {
44047
45006
  var x3 = x2 + ((dx < 0 ? -1 : 1) * labelLineLen2);
44048
45007
  var y3 = y2;
44049
45008
 
44050
- textX = x3 + (dx < 0 ? -5 : 5);
45009
+ if (labelAlignTo === 'edge') {
45010
+ // Adjust textX because text align of edge is opposite
45011
+ textX = dx < 0
45012
+ ? viewLeft + labelMargin
45013
+ : viewLeft + viewWidth - labelMargin;
45014
+ }
45015
+ else {
45016
+ textX = x3 + (dx < 0 ? -labelDistance : labelDistance);
45017
+ }
44051
45018
  textY = y3;
44052
45019
  linePoints = [[x1, y1], [x2, y2], [x3, y3]];
44053
45020
  }
44054
45021
 
44055
- textAlign = isLabelInside ? 'center' : (dx > 0 ? 'left' : 'right');
45022
+ textAlign = isLabelInside
45023
+ ? 'center'
45024
+ : (labelAlignTo === 'edge'
45025
+ ? (dx > 0 ? 'right' : 'left')
45026
+ : (dx > 0 ? 'left' : 'right'));
44056
45027
  }
44057
- var font = labelModel.getFont();
44058
45028
 
44059
45029
  var labelRotate;
44060
45030
  var rotate = labelModel.get('rotate');
@@ -44066,11 +45036,7 @@ var labelLayout = function (seriesModel, r, viewWidth, viewHeight, sum) {
44066
45036
  ? (dx < 0 ? -midAngle + Math.PI : -midAngle)
44067
45037
  : 0;
44068
45038
  }
44069
- var text = seriesModel.getFormattedLabel(idx, 'normal')
44070
- || data.getName(idx);
44071
- var textRect = getBoundingRect(
44072
- text, font, textAlign, 'top'
44073
- );
45039
+
44074
45040
  hasLabelRotate = !!labelRotate;
44075
45041
  layout.label = {
44076
45042
  x: textX,
@@ -44083,7 +45049,14 @@ var labelLayout = function (seriesModel, r, viewWidth, viewHeight, sum) {
44083
45049
  textAlign: textAlign,
44084
45050
  verticalAlign: 'middle',
44085
45051
  rotation: labelRotate,
44086
- inside: isLabelInside
45052
+ inside: isLabelInside,
45053
+ labelDistance: labelDistance,
45054
+ labelAlignTo: labelAlignTo,
45055
+ labelMargin:labelMargin,
45056
+ bleedMargin: bleedMargin,
45057
+ textRect: textRect,
45058
+ text: text,
45059
+ font: font
44087
45060
  };
44088
45061
 
44089
45062
  // Not layout the inside label
@@ -44092,7 +45065,7 @@ var labelLayout = function (seriesModel, r, viewWidth, viewHeight, sum) {
44092
45065
  }
44093
45066
  });
44094
45067
  if (!hasLabelRotate && seriesModel.get('avoidLabelOverlap')) {
44095
- avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight);
45068
+ avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight, viewLeft, viewTop);
44096
45069
  }
44097
45070
  };
44098
45071
 
@@ -44119,10 +45092,20 @@ var labelLayout = function (seriesModel, r, viewWidth, viewHeight, sum) {
44119
45092
  var PI2$4 = Math.PI * 2;
44120
45093
  var RADIAN = Math.PI / 180;
44121
45094
 
45095
+ function getViewRect(seriesModel, api) {
45096
+ return getLayoutRect(
45097
+ seriesModel.getBoxLayoutParams(), {
45098
+ width: api.getWidth(),
45099
+ height: api.getHeight()
45100
+ }
45101
+ );
45102
+ }
45103
+
44122
45104
  var pieLayout = function (seriesType, ecModel, api, payload) {
44123
45105
  ecModel.eachSeriesByType(seriesType, function (seriesModel) {
44124
45106
  var data = seriesModel.getData();
44125
45107
  var valueDim = data.mapDimension('value');
45108
+ var viewRect = getViewRect(seriesModel, api);
44126
45109
 
44127
45110
  var center = seriesModel.get('center');
44128
45111
  var radius = seriesModel.get('radius');
@@ -44134,11 +45117,11 @@ var pieLayout = function (seriesType, ecModel, api, payload) {
44134
45117
  center = [center, center];
44135
45118
  }
44136
45119
 
44137
- var width = api.getWidth();
44138
- var height = api.getHeight();
45120
+ var width = parsePercent$1(viewRect.width, api.getWidth());
45121
+ var height = parsePercent$1(viewRect.height, api.getHeight());
44139
45122
  var size = Math.min(width, height);
44140
- var cx = parsePercent$1(center[0], width);
44141
- var cy = parsePercent$1(center[1], height);
45123
+ var cx = parsePercent$1(center[0], width) + viewRect.x;
45124
+ var cy = parsePercent$1(center[1], height) + viewRect.y;
44142
45125
  var r0 = parsePercent$1(radius[0], size / 2);
44143
45126
  var r = parsePercent$1(radius[1], size / 2);
44144
45127
 
@@ -44184,7 +45167,8 @@ var pieLayout = function (seriesType, ecModel, api, payload) {
44184
45167
  r0: r0,
44185
45168
  r: roseType
44186
45169
  ? NaN
44187
- : r
45170
+ : r,
45171
+ viewRect: viewRect
44188
45172
  });
44189
45173
  return;
44190
45174
  }
@@ -44217,7 +45201,8 @@ var pieLayout = function (seriesType, ecModel, api, payload) {
44217
45201
  r0: r0,
44218
45202
  r: roseType
44219
45203
  ? linearMap(value, extent, [r0, r])
44220
- : r
45204
+ : r,
45205
+ viewRect: viewRect
44221
45206
  });
44222
45207
 
44223
45208
  currentAngle = endAngle;
@@ -44255,7 +45240,7 @@ var pieLayout = function (seriesType, ecModel, api, payload) {
44255
45240
  }
44256
45241
  }
44257
45242
 
44258
- labelLayout(seriesModel, r, width, height);
45243
+ labelLayout(seriesModel, r, viewRect.width, viewRect.height, viewRect.x, viewRect.y);
44259
45244
  });
44260
45245
  };
44261
45246
 
@@ -44366,7 +45351,7 @@ SeriesModel.extend({
44366
45351
  dependencies: ['grid', 'polar', 'geo', 'singleAxis', 'calendar'],
44367
45352
 
44368
45353
  getInitialData: function (option, ecModel) {
44369
- return createListFromArray(this.getSource(), this);
45354
+ return createListFromArray(this.getSource(), this, {useEncodeDefaulter: true});
44370
45355
  },
44371
45356
 
44372
45357
  brushSelector: 'point',
@@ -48786,9 +49771,9 @@ var LegendModel = extendComponentModel({
48786
49771
  availableNames.push(seriesName);
48787
49772
  var isPotential;
48788
49773
 
48789
- if (seriesModel.legendDataProvider) {
48790
- var data = seriesModel.legendDataProvider();
48791
- var names = data.mapArray(data.getName);
49774
+ if (seriesModel.legendVisualProvider) {
49775
+ var provider = seriesModel.legendVisualProvider;
49776
+ var names = provider.getAllNames();
48792
49777
 
48793
49778
  if (!ecModel.isSeriesFiltered(seriesModel)) {
48794
49779
  availableNames = availableNames.concat(names);
@@ -49377,7 +50362,7 @@ var LegendView = extendComponentView({
49377
50362
  return;
49378
50363
  }
49379
50364
 
49380
- // Series legend
50365
+ // Legend to control series.
49381
50366
  if (seriesModel) {
49382
50367
  var data = seriesModel.getData();
49383
50368
  var color = data.getVisual('color');
@@ -49406,29 +50391,31 @@ var LegendView = extendComponentView({
49406
50391
  selectMode
49407
50392
  );
49408
50393
 
49409
- itemGroup.on('click', curry$3(dispatchSelectAction, name, api))
50394
+ itemGroup.on('click', curry$3(dispatchSelectAction, name, null, api, excludeSeriesId))
49410
50395
  .on('mouseover', curry$3(dispatchHighlightAction, seriesModel.name, null, api, excludeSeriesId))
49411
50396
  .on('mouseout', curry$3(dispatchDownplayAction, seriesModel.name, null, api, excludeSeriesId));
49412
50397
 
49413
50398
  legendDrawnMap.set(name, true);
49414
50399
  }
49415
50400
  else {
49416
- // Data legend of pie, funnel
50401
+ // Legend to control data. In pie and funnel.
49417
50402
  ecModel.eachRawSeries(function (seriesModel) {
50403
+
49418
50404
  // In case multiple series has same data name
49419
50405
  if (legendDrawnMap.get(name)) {
49420
50406
  return;
49421
50407
  }
49422
50408
 
49423
- if (seriesModel.legendDataProvider) {
49424
- var data = seriesModel.legendDataProvider();
49425
- var idx = data.indexOfName(name);
49426
- if (idx < 0) {
50409
+ if (seriesModel.legendVisualProvider) {
50410
+ var provider = seriesModel.legendVisualProvider;
50411
+ if (!provider.containName(name)) {
49427
50412
  return;
49428
50413
  }
49429
50414
 
49430
- var color = data.getItemVisual(idx, 'color');
49431
- var borderColor = data.getItemVisual(idx, 'borderColor');
50415
+ var idx = provider.indexOfName(name);
50416
+
50417
+ var color = provider.getItemVisual(idx, 'color');
50418
+ var borderColor = provider.getItemVisual(idx, 'borderColor');
49432
50419
 
49433
50420
  var legendSymbolType = 'roundRect';
49434
50421
 
@@ -49440,7 +50427,7 @@ var LegendView = extendComponentView({
49440
50427
  );
49441
50428
 
49442
50429
  // FIXME: consider different series has items with the same name.
49443
- itemGroup.on('click', curry$3(dispatchSelectAction, name, api))
50430
+ itemGroup.on('click', curry$3(dispatchSelectAction, null, name, api, excludeSeriesId))
49444
50431
  // Should not specify the series name, consider legend controls
49445
50432
  // more than one pie series.
49446
50433
  .on('mouseover', curry$3(dispatchHighlightAction, null, name, api, excludeSeriesId))
@@ -49720,11 +50707,15 @@ function setSymbolStyle(symbol, symbolType, legendModelItemStyle, borderColor, i
49720
50707
  return symbol.setStyle(itemStyle);
49721
50708
  }
49722
50709
 
49723
- function dispatchSelectAction(name, api) {
50710
+ function dispatchSelectAction(seriesName, dataName, api, excludeSeriesId) {
50711
+ // downplay before unselect
50712
+ dispatchDownplayAction(seriesName, dataName, api, excludeSeriesId);
49724
50713
  api.dispatchAction({
49725
50714
  type: 'legendToggleSelect',
49726
- name: name
50715
+ name: seriesName != null ? seriesName : dataName
49727
50716
  });
50717
+ // highlight after select
50718
+ dispatchHighlightAction(seriesName, dataName, api, excludeSeriesId);
49728
50719
  }
49729
50720
 
49730
50721
  function dispatchHighlightAction(seriesName, dataName, api, excludeSeriesId) {
@@ -54967,10 +55958,6 @@ var SliderZoomView = DataZoomView.extend({
54967
55958
  draggable: true,
54968
55959
  cursor: getCursor(this._orient),
54969
55960
  drift: bind$3(this._onDragMove, this, 'all'),
54970
- onmousemove: function (e) {
54971
- // Fot mobile devicem, prevent screen slider on the button.
54972
- stop(e.event);
54973
- },
54974
55961
  ondragstart: bind$3(this._showDataInfo, this, true),
54975
55962
  ondragend: bind$3(this._onDragEnd, this),
54976
55963
  onmouseover: bind$3(this._showDataInfo, this, true),
@@ -55006,10 +55993,6 @@ var SliderZoomView = DataZoomView.extend({
55006
55993
  cursor: getCursor(this._orient),
55007
55994
  draggable: true,
55008
55995
  drift: bind$3(this._onDragMove, this, handleIndex),
55009
- onmousemove: function (e) {
55010
- // Fot mobile devicem, prevent screen slider on the button.
55011
- stop(e.event);
55012
- },
55013
55996
  ondragend: bind$3(this._onDragEnd, this),
55014
55997
  onmouseover: bind$3(this._showDataInfo, this, true),
55015
55998
  onmouseout: bind$3(this._showDataInfo, this, false)
@@ -55231,9 +56214,12 @@ var SliderZoomView = DataZoomView.extend({
55231
56214
  handleLabels[1].attr('invisible', !showOrHide);
55232
56215
  },
55233
56216
 
55234
- _onDragMove: function (handleIndex, dx, dy) {
56217
+ _onDragMove: function (handleIndex, dx, dy, event) {
55235
56218
  this._dragging = true;
55236
56219
 
56220
+ // For mobile device, prevent screen slider on the button.
56221
+ stop(event.event);
56222
+
55237
56223
  // Transform dx, dy to bar coordination.
55238
56224
  var barTransform = this._displayables.barGroup.getLocalTransform();
55239
56225
  var vertex = applyTransform$1([dx, dy], barTransform, true);
@@ -56554,6 +57540,11 @@ extendComponentView({
56554
57540
  var featureModel = new Model(featureOpt, toolboxModel, toolboxModel.ecModel);
56555
57541
  var feature;
56556
57542
 
57543
+ // FIX#11236, merge feature title from MagicType newOption. TODO: consider seriesIndex ?
57544
+ if (payload && payload.newTitle != null) {
57545
+ featureOpt.title = payload.newTitle;
57546
+ }
57547
+
56557
57548
  if (featureName && !oldName) { // Create
56558
57549
  if (isUserFeatureName(featureName)) {
56559
57550
  feature = {
@@ -56893,6 +57884,7 @@ register$2(
56893
57884
  */
56894
57885
 
56895
57886
  var magicTypeLang = lang.toolbox.magicType;
57887
+ var INNER_STACK_KEYWORD = '__ec_magicType_stack__';
56896
57888
 
56897
57889
  function MagicType(model) {
56898
57890
  this.model = model;
@@ -56906,8 +57898,7 @@ MagicType.defaultOption = {
56906
57898
  /* eslint-disable */
56907
57899
  line: 'M4.1,28.9h7.1l9.3-22l7.4,38l9.7-19.7l3,12.8h14.9M4.1,58h51.4',
56908
57900
  bar: 'M6.7,22.9h10V48h-10V22.9zM24.9,13h10v35h-10V13zM43.2,2h10v46h-10V2zM3.1,58h53.7',
56909
- 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
56910
- tiled: 'M2.3,2.2h22.8V25H2.3V2.2z M35,2.2h22.8V25H35V2.2zM2.3,35h22.8v22.8H2.3V35z M35,35h22.8v22.8H35V35z'
57901
+ 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
56911
57902
  /* eslint-enable */
56912
57903
  },
56913
57904
  // `line`, `bar`, `stack`, `tiled`
@@ -56958,26 +57949,20 @@ var seriesOptGenreator = {
56958
57949
  }
56959
57950
  },
56960
57951
  'stack': function (seriesType, seriesId, seriesModel, model) {
57952
+ var isStack = seriesModel.get('stack') === INNER_STACK_KEYWORD;
56961
57953
  if (seriesType === 'line' || seriesType === 'bar') {
57954
+ model.setIconStatus('stack', isStack ? 'normal' : 'emphasis');
56962
57955
  return merge({
56963
57956
  id: seriesId,
56964
- stack: '__ec_magicType_stack__'
57957
+ stack: isStack ? '' : INNER_STACK_KEYWORD
56965
57958
  }, model.get('option.stack') || {}, true);
56966
57959
  }
56967
- },
56968
- 'tiled': function (seriesType, seriesId, seriesModel, model) {
56969
- if (seriesType === 'line' || seriesType === 'bar') {
56970
- return merge({
56971
- id: seriesId,
56972
- stack: ''
56973
- }, model.get('option.tiled') || {}, true);
56974
- }
56975
57960
  }
56976
57961
  };
56977
57962
 
56978
57963
  var radioTypes = [
56979
57964
  ['line', 'bar'],
56980
- ['stack', 'tiled']
57965
+ ['stack']
56981
57966
  ];
56982
57967
 
56983
57968
  proto$3.onclick = function (ecModel, api, type) {
@@ -57042,10 +58027,21 @@ proto$3.onclick = function (ecModel, api, type) {
57042
58027
  }
57043
58028
  }, generateNewSeriesTypes
57044
58029
  );
58030
+
58031
+ var newTitle;
58032
+ // Change title of stack
58033
+ if (type === 'stack') {
58034
+ var isStack = newOption.series && newOption.series[0] && newOption.series[0].stack === INNER_STACK_KEYWORD;
58035
+ newTitle = isStack
58036
+ ? merge({ stack: magicTypeLang.title.tiled }, magicTypeLang.title)
58037
+ : clone(magicTypeLang.title);
58038
+ }
58039
+
57045
58040
  api.dispatchAction({
57046
58041
  type: 'changeMagicType',
57047
58042
  currentType: type,
57048
- newOption: newOption
58043
+ newOption: newOption,
58044
+ newTitle: newTitle
57049
58045
  });
57050
58046
  };
57051
58047
 
@@ -57658,12 +58654,6 @@ function BrushController(zr) {
57658
58654
  */
57659
58655
  this._dragging;
57660
58656
 
57661
- /**
57662
- * @private
57663
- * @type {Object}
57664
- */
57665
- this._lastMouseMovePoint = {};
57666
-
57667
58657
  /**
57668
58658
  * @private
57669
58659
  * @type {Array}
@@ -57708,7 +58698,8 @@ function BrushController(zr) {
57708
58698
  * @type {Object}
57709
58699
  */
57710
58700
  this._handlers = {};
57711
- each$16(mouseHandlers, function (handler, eventName) {
58701
+
58702
+ each$16(pointerHandlers, function (handler, eventName) {
57712
58703
  this._handlers[eventName] = bind(handler, this);
57713
58704
  }, this);
57714
58705
  }
@@ -57904,9 +58895,7 @@ function doEnableBrush(controller, brushOption) {
57904
58895
  take(zr, MUTEX_RESOURCE_KEY, controller._uid);
57905
58896
  }
57906
58897
 
57907
- each$16(controller._handlers, function (handler, eventName) {
57908
- zr.on(eventName, handler);
57909
- });
58898
+ mountHandlers(zr, controller._handlers);
57910
58899
 
57911
58900
  controller._brushType = brushOption.brushType;
57912
58901
  controller._brushOption = merge(clone(DEFAULT_BRUSH_OPT), brushOption, true);
@@ -57917,13 +58906,23 @@ function doDisableBrush(controller) {
57917
58906
 
57918
58907
  release(zr, MUTEX_RESOURCE_KEY, controller._uid);
57919
58908
 
57920
- each$16(controller._handlers, function (handler, eventName) {
57921
- zr.off(eventName, handler);
57922
- });
58909
+ unmountHandlers(zr, controller._handlers);
57923
58910
 
57924
58911
  controller._brushType = controller._brushOption = null;
57925
58912
  }
57926
58913
 
58914
+ function mountHandlers(zr, handlers) {
58915
+ each$16(handlers, function (handler, eventName) {
58916
+ zr.on(eventName, handler);
58917
+ });
58918
+ }
58919
+
58920
+ function unmountHandlers(zr, handlers) {
58921
+ each$16(handlers, function (handler, eventName) {
58922
+ zr.off(eventName, handler);
58923
+ });
58924
+ }
58925
+
57927
58926
  function createCover(controller, brushOption) {
57928
58927
  var cover = coverRenderers[brushOption.brushType].createCover(controller, brushOption);
57929
58928
  cover.__brushOption = brushOption;
@@ -58237,8 +59236,14 @@ function pointsToRect(points) {
58237
59236
  }
58238
59237
 
58239
59238
  function resetCursor(controller, e, localCursorPoint) {
58240
- // Check active
58241
- if (!controller._brushType) {
59239
+ if (
59240
+ // Check active
59241
+ !controller._brushType
59242
+ // resetCursor should be always called when mouse is in zr area,
59243
+ // but not called when mouse is out of zr area to avoid bad influence
59244
+ // if `mousemove`, `mouseup` are triggered from `document` event.
59245
+ || isOutsideZrArea(controller, e)
59246
+ ) {
58242
59247
  return;
58243
59248
  }
58244
59249
 
@@ -58342,7 +59347,7 @@ function determineBrushType(brushType, panel) {
58342
59347
  return brushType;
58343
59348
  }
58344
59349
 
58345
- var mouseHandlers = {
59350
+ var pointerHandlers = {
58346
59351
 
58347
59352
  mousedown: function (e) {
58348
59353
  if (this._dragging) {
@@ -58367,56 +59372,34 @@ var mouseHandlers = {
58367
59372
  },
58368
59373
 
58369
59374
  mousemove: function (e) {
58370
- var lastPoint = this._lastMouseMovePoint;
58371
- lastPoint.x = e.offsetX;
58372
- lastPoint.y = e.offsetY;
59375
+ var x = e.offsetX;
59376
+ var y = e.offsetY;
58373
59377
 
58374
- var localCursorPoint = this.group.transformCoordToLocal(lastPoint.x, lastPoint.y);
59378
+ var localCursorPoint = this.group.transformCoordToLocal(x, y);
58375
59379
 
58376
59380
  resetCursor(this, e, localCursorPoint);
58377
59381
 
58378
59382
  if (this._dragging) {
58379
-
58380
59383
  preventDefault(e);
58381
-
58382
59384
  var eventParams = updateCoverByMouse(this, e, localCursorPoint, false);
58383
-
58384
59385
  eventParams && trigger$1(this, eventParams);
58385
59386
  }
58386
59387
  },
58387
59388
 
58388
59389
  mouseup: function (e) {
58389
59390
  handleDragEnd(this, e);
58390
- },
58391
-
58392
- globalout: function (e) {
58393
- handleDragEnd(this, e, true);
58394
59391
  }
58395
59392
  };
58396
59393
 
58397
- function handleDragEnd(controller, e, isGlobalOut) {
58398
- if (controller._dragging) {
58399
59394
 
58400
- // Just be worried about bring some side effect to the world
58401
- // out of echarts, we do not `preventDefault` for globalout.
58402
- !isGlobalOut && preventDefault(e);
59395
+ function handleDragEnd(controller, e) {
59396
+ if (controller._dragging) {
59397
+ preventDefault(e);
58403
59398
 
58404
- var pointerX = e.offsetX;
58405
- var pointerY = e.offsetY;
58406
- var lastPoint = controller._lastMouseMovePoint;
58407
- if (isGlobalOut) {
58408
- pointerX = lastPoint.x;
58409
- pointerY = lastPoint.y;
58410
- }
59399
+ var x = e.offsetX;
59400
+ var y = e.offsetY;
58411
59401
 
58412
- var localCursorPoint = controller.group.transformCoordToLocal(pointerX, pointerY);
58413
- // FIXME
58414
- // Here `e` is used only in `onIrrelevantElement` finally. And it's OK
58415
- // that pass the `e` of `globalout` to `onIrrelevantElement`. But it is
58416
- // not a good design of these interfaces. However, we do not refactor
58417
- // these code now because the implementation of `onIrrelevantElement`
58418
- // need to be discussed and probably be changed in future, becuase it
58419
- // slows down the performance of zrender in some cases.
59402
+ var localCursorPoint = controller.group.transformCoordToLocal(x, y);
58420
59403
  var eventParams = updateCoverByMouse(controller, e, localCursorPoint, true);
58421
59404
 
58422
59405
  controller._dragging = false;
@@ -58428,6 +59411,12 @@ function handleDragEnd(controller, e, isGlobalOut) {
58428
59411
  }
58429
59412
  }
58430
59413
 
59414
+ function isOutsideZrArea(controller, x, y) {
59415
+ var zr = controller._zr;
59416
+ return x < 0 || x > zr.getWidth() || y < 0 || y > zr.getHeight();
59417
+ }
59418
+
59419
+
58431
59420
  /**
58432
59421
  * key: brushType
58433
59422
  * @type {Object}
@@ -61204,6 +62193,9 @@ svgPath.brush = function (el) {
61204
62193
  if (style.text != null) {
61205
62194
  svgTextDrawRectText(el, el.getBoundingRect());
61206
62195
  }
62196
+ else {
62197
+ removeOldTextNode(el);
62198
+ }
61207
62199
  };
61208
62200
 
61209
62201
  /***************************************************
@@ -61251,6 +62243,9 @@ svgImage.brush = function (el) {
61251
62243
  if (style.text != null) {
61252
62244
  svgTextDrawRectText(el, el.getBoundingRect());
61253
62245
  }
62246
+ else {
62247
+ removeOldTextNode(el);
62248
+ }
61254
62249
  };
61255
62250
 
61256
62251
  /***************************************************
@@ -61451,6 +62446,18 @@ function updateTextLocation(tspan, textAlign, x, y) {
61451
62446
  attr(tspan, 'y', y);
61452
62447
  }
61453
62448
 
62449
+ function removeOldTextNode(el) {
62450
+ if (el && el.__textSvgEl) {
62451
+ // textSvgEl may has no parentNode if el has been removed temporary.
62452
+ if (el.__textSvgEl.parentNode) {
62453
+ el.__textSvgEl.parentNode.removeChild(el.__textSvgEl);
62454
+ }
62455
+ el.__textSvgEl = null;
62456
+ el.__tspanList = [];
62457
+ el.__text = null;
62458
+ }
62459
+ }
62460
+
61454
62461
  svgText.drawRectText = svgTextDrawRectText;
61455
62462
 
61456
62463
  svgText.brush = function (el) {
@@ -61458,6 +62465,9 @@ svgText.brush = function (el) {
61458
62465
  if (style.text != null) {
61459
62466
  svgTextDrawRectText(el, false);
61460
62467
  }
62468
+ else {
62469
+ removeOldTextNode(el);
62470
+ }
61461
62471
  };
61462
62472
 
61463
62473
  // Myers' Diff Algorithm
@@ -62712,8 +63722,8 @@ SVGPainter.prototype = {
62712
63722
  else if (!item.removed) {
62713
63723
  for (var k = 0; k < item.count; k++) {
62714
63724
  var displayable = newVisibleList[item.indices[k]];
62715
- prevSvgElement = getTextSvgElement(displayable)
62716
- || getSvgElement(displayable) || prevSvgElement;
63725
+ var svgElement = getSvgElement(displayable);
63726
+ var textSvgElement = getTextSvgElement(displayable);
62717
63727
 
62718
63728
  var svgElement = getSvgElement(displayable);
62719
63729
  var textSvgElement = getTextSvgElement(displayable);
@@ -62727,6 +63737,12 @@ SVGPainter.prototype = {
62727
63737
  .addWithoutUpdate(svgElement || textSvgElement, displayable);
62728
63738
 
62729
63739
  this.clipPathManager.markUsed(displayable);
63740
+
63741
+ if (textSvgElement) { // Insert text.
63742
+ insertAfter(svgRoot, textSvgElement, svgElement);
63743
+ }
63744
+ prevSvgElement = svgElement
63745
+ || textSvgElement || prevSvgElement;
62730
63746
  }
62731
63747
  }
62732
63748
  }