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
  }
@@ -26324,6 +26570,9 @@ var theme = {
26324
26570
  },
26325
26571
  crossStyle: {
26326
26572
  color: contrastColor
26573
+ },
26574
+ label: {
26575
+ color: '#000'
26327
26576
  }
26328
26577
  }
26329
26578
  },
@@ -27294,10 +27543,10 @@ var isFunction = isFunction$1;
27294
27543
  var isObject = isObject$1;
27295
27544
  var parseClassType = ComponentModel.parseClassType;
27296
27545
 
27297
- var version = '4.5.0';
27546
+ var version = '4.6.0';
27298
27547
 
27299
27548
  var dependencies = {
27300
- zrender: '4.1.2'
27549
+ zrender: '4.2.0'
27301
27550
  };
27302
27551
 
27303
27552
  var TEST_FRAME_REMAIN_TIME = 1;
@@ -30004,6 +30253,138 @@ function mayLabelDimType(dimType) {
30004
30253
  * under the License.
30005
30254
  */
30006
30255
 
30256
+ /**
30257
+ * @class
30258
+ * @param {Object|DataDimensionInfo} [opt] All of the fields will be shallow copied.
30259
+ */
30260
+ function DataDimensionInfo(opt) {
30261
+ if (opt != null) {
30262
+ extend(this, opt);
30263
+ }
30264
+
30265
+ /**
30266
+ * Dimension name.
30267
+ * Mandatory.
30268
+ * @type {string}
30269
+ */
30270
+ // this.name;
30271
+
30272
+ /**
30273
+ * The origin name in dimsDef, see source helper.
30274
+ * If displayName given, the tooltip will displayed vertically.
30275
+ * Optional.
30276
+ * @type {string}
30277
+ */
30278
+ // this.displayName;
30279
+
30280
+ /**
30281
+ * Which coordSys dimension this dimension mapped to.
30282
+ * A `coordDim` can be a "coordSysDim" that the coordSys required
30283
+ * (for example, an item in `coordSysDims` of `model/referHelper#CoordSysInfo`),
30284
+ * or an generated "extra coord name" if does not mapped to any "coordSysDim"
30285
+ * (That is determined by whether `isExtraCoord` is `true`).
30286
+ * Mandatory.
30287
+ * @type {string}
30288
+ */
30289
+ // this.coordDim;
30290
+
30291
+ /**
30292
+ * The index of this dimension in `series.encode[coordDim]`.
30293
+ * Mandatory.
30294
+ * @type {number}
30295
+ */
30296
+ // this.coordDimIndex;
30297
+
30298
+ /**
30299
+ * Dimension type. The enumerable values are the key of
30300
+ * `dataCtors` of `data/List`.
30301
+ * Optional.
30302
+ * @type {string}
30303
+ */
30304
+ // this.type;
30305
+
30306
+ /**
30307
+ * This index of this dimension info in `data/List#_dimensionInfos`.
30308
+ * Mandatory after added to `data/List`.
30309
+ * @type {number}
30310
+ */
30311
+ // this.index;
30312
+
30313
+ /**
30314
+ * The format of `otherDims` is:
30315
+ * ```js
30316
+ * {
30317
+ * tooltip: number optional,
30318
+ * label: number optional,
30319
+ * itemName: number optional,
30320
+ * seriesName: number optional,
30321
+ * }
30322
+ * ```
30323
+ *
30324
+ * A `series.encode` can specified these fields:
30325
+ * ```js
30326
+ * encode: {
30327
+ * // "3, 1, 5" is the index of data dimension.
30328
+ * tooltip: [3, 1, 5],
30329
+ * label: [0, 3],
30330
+ * ...
30331
+ * }
30332
+ * ```
30333
+ * `otherDims` is the parse result of the `series.encode` above, like:
30334
+ * ```js
30335
+ * // Suppose the index of this data dimension is `3`.
30336
+ * this.otherDims = {
30337
+ * // `3` is at the index `0` of the `encode.tooltip`
30338
+ * tooltip: 0,
30339
+ * // `3` is at the index `1` of the `encode.tooltip`
30340
+ * label: 1
30341
+ * };
30342
+ * ```
30343
+ *
30344
+ * This prop should never be `null`/`undefined` after initialized.
30345
+ * @type {Object}
30346
+ */
30347
+ this.otherDims = {};
30348
+
30349
+ /**
30350
+ * Be `true` if this dimension is not mapped to any "coordSysDim" that the
30351
+ * "coordSys" required.
30352
+ * Mandatory.
30353
+ * @type {boolean}
30354
+ */
30355
+ // this.isExtraCoord;
30356
+
30357
+ /**
30358
+ * @type {module:data/OrdinalMeta}
30359
+ */
30360
+ // this.ordinalMeta;
30361
+
30362
+ /**
30363
+ * Whether to create inverted indices.
30364
+ * @type {boolean}
30365
+ */
30366
+ // this.createInvertedIndices;
30367
+ }
30368
+
30369
+ /*
30370
+ * Licensed to the Apache Software Foundation (ASF) under one
30371
+ * or more contributor license agreements. See the NOTICE file
30372
+ * distributed with this work for additional information
30373
+ * regarding copyright ownership. The ASF licenses this file
30374
+ * to you under the Apache License, Version 2.0 (the
30375
+ * "License"); you may not use this file except in compliance
30376
+ * with the License. You may obtain a copy of the License at
30377
+ *
30378
+ * http://www.apache.org/licenses/LICENSE-2.0
30379
+ *
30380
+ * Unless required by applicable law or agreed to in writing,
30381
+ * software distributed under the License is distributed on an
30382
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
30383
+ * KIND, either express or implied. See the License for the
30384
+ * specific language governing permissions and limitations
30385
+ * under the License.
30386
+ */
30387
+
30007
30388
  /* global Float64Array, Int32Array, Uint32Array, Uint16Array */
30008
30389
 
30009
30390
  /**
@@ -30081,13 +30462,9 @@ function transferProperties(target, source) {
30081
30462
  * @constructor
30082
30463
  * @alias module:echarts/data/List
30083
30464
  *
30084
- * @param {Array.<string|Object>} dimensions
30465
+ * @param {Array.<string|Object|module:data/DataDimensionInfo>} dimensions
30085
30466
  * For example, ['someDimName', {name: 'someDimName', type: 'someDimType'}, ...].
30086
30467
  * Dimensions should be concrete names like x, y, z, lng, lat, angle, radius
30087
- * Spetial fields: {
30088
- * ordinalMeta: <module:echarts/data/OrdinalMeta>
30089
- * createInvertedIndices: <boolean>
30090
- * }
30091
30468
  * @param {module:echarts/model/Model} hostModel
30092
30469
  */
30093
30470
  var List = function (dimensions, hostModel) {
@@ -30103,7 +30480,10 @@ var List = function (dimensions, hostModel) {
30103
30480
  var dimensionInfo = dimensions[i];
30104
30481
 
30105
30482
  if (isString(dimensionInfo)) {
30106
- dimensionInfo = {name: dimensionInfo};
30483
+ dimensionInfo = new DataDimensionInfo({name: dimensionInfo});
30484
+ }
30485
+ else if (!(dimensionInfo instanceof DataDimensionInfo)) {
30486
+ dimensionInfo = new DataDimensionInfo(dimensionInfo);
30107
30487
  }
30108
30488
 
30109
30489
  var dimensionName = dimensionInfo.name;
@@ -31123,7 +31503,8 @@ listProto.indexOfRawIndex = function (rawIndex) {
31123
31503
  * @param {string} dim
31124
31504
  * @param {number} value
31125
31505
  * @param {number} [maxDistance=Infinity]
31126
- * @return {Array.<number>} Considere multiple points has the same value.
31506
+ * @return {Array.<number>} If and only if multiple indices has
31507
+ * the same value, they are put to the result.
31127
31508
  */
31128
31509
  listProto.indicesOfNearest = function (dim, value, maxDistance) {
31129
31510
  var storage = this._storage;
@@ -31138,23 +31519,35 @@ listProto.indicesOfNearest = function (dim, value, maxDistance) {
31138
31519
  maxDistance = Infinity;
31139
31520
  }
31140
31521
 
31141
- var minDist = Number.MAX_VALUE;
31522
+ var minDist = Infinity;
31142
31523
  var minDiff = -1;
31524
+ var nearestIndicesLen = 0;
31525
+
31526
+ // Check the test case of `test/ut/spec/data/List.js`.
31143
31527
  for (var i = 0, len = this.count(); i < len; i++) {
31144
- var diff = value - this.get(dim, i /*, stack */);
31528
+ var diff = value - this.get(dim, i);
31145
31529
  var dist = Math.abs(diff);
31146
- if (diff <= maxDistance && dist <= minDist) {
31147
- // For the case of two data are same on xAxis, which has sequence data.
31148
- // Show the nearest index
31149
- // https://github.com/ecomfe/echarts/issues/2869
31150
- if (dist < minDist || (diff >= 0 && minDiff < 0)) {
31530
+ if (dist <= maxDistance) {
31531
+ // When the `value` is at the middle of `this.get(dim, i)` and `this.get(dim, i+1)`,
31532
+ // we'd better not push both of them to `nearestIndices`, otherwise it is easy to
31533
+ // get more than one item in `nearestIndices` (more specifically, in `tooltip`).
31534
+ // So we chose the one that `diff >= 0` in this csae.
31535
+ // But if `this.get(dim, i)` and `this.get(dim, j)` get the same value, both of them
31536
+ // should be push to `nearestIndices`.
31537
+ if (dist < minDist
31538
+ || (dist === minDist && diff >= 0 && minDiff < 0)
31539
+ ) {
31151
31540
  minDist = dist;
31152
31541
  minDiff = diff;
31153
- nearestIndices.length = 0;
31542
+ nearestIndicesLen = 0;
31543
+ }
31544
+ if (diff === minDiff) {
31545
+ nearestIndices[nearestIndicesLen++] = i;
31154
31546
  }
31155
- nearestIndices.push(i);
31156
31547
  }
31157
31548
  }
31549
+ nearestIndices.length = nearestIndicesLen;
31550
+
31158
31551
  return nearestIndices;
31159
31552
  };
31160
31553
 
@@ -32028,8 +32421,12 @@ listProto.CHANGABLE_METHODS = ['filterSelf', 'selectRange'];
32028
32421
  /**
32029
32422
  * @see {module:echarts/test/ut/spec/data/completeDimensions}
32030
32423
  *
32031
- * Complete the dimensions array, by user defined `dimension` and `encode`,
32032
- * and guessing from the data structure.
32424
+ * This method builds the relationship between:
32425
+ * + "what the coord sys or series requires (see `sysDims`)",
32426
+ * + "what the user defines (in `encode` and `dimensions`, see `opt.dimsDef` and `opt.encodeDef`)"
32427
+ * + "what the data source provids (see `source`)".
32428
+ *
32429
+ * Some guess strategy will be adapted if user does not define something.
32033
32430
  * If no 'value' dimension specified, the first no-named dimension will be
32034
32431
  * named as 'value'.
32035
32432
  *
@@ -32045,32 +32442,20 @@ listProto.CHANGABLE_METHODS = ['filterSelf', 'selectRange'];
32045
32442
  * @param {Array.<Object|string>} [opt.dimsDef] option.series.dimensions User defined dimensions
32046
32443
  * For example: ['asdf', {name, type}, ...].
32047
32444
  * @param {Object|HashMap} [opt.encodeDef] option.series.encode {x: 2, y: [3, 1], tooltip: [1, 2], label: 3}
32445
+ * @param {Function} [opt.encodeDefaulter] Called if no `opt.encodeDef` exists.
32446
+ * If not specified, auto find the next available data dim.
32447
+ * param source {module:data/Source}
32448
+ * param dimCount {number}
32449
+ * return {Object} encode Never be `null/undefined`.
32048
32450
  * @param {string} [opt.generateCoord] Generate coord dim with the given name.
32049
- * If not specified, extra dim names will be:
32050
- * 'value', 'value0', 'value1', ...
32451
+ * If not specified, extra dim names will be:
32452
+ * 'value', 'value0', 'value1', ...
32051
32453
  * @param {number} [opt.generateCoordCount] By default, the generated dim name is `generateCoord`.
32052
- * If `generateCoordCount` specified, the generated dim names will be:
32053
- * `generateCoord` + 0, `generateCoord` + 1, ...
32054
- * can be Infinity, indicate that use all of the remain columns.
32454
+ * If `generateCoordCount` specified, the generated dim names will be:
32455
+ * `generateCoord` + 0, `generateCoord` + 1, ...
32456
+ * can be Infinity, indicate that use all of the remain columns.
32055
32457
  * @param {number} [opt.dimCount] If not specified, guess by the first data item.
32056
- * @param {number} [opt.encodeDefaulter] If not specified, auto find the next available data dim.
32057
- * @return {Array.<Object>} [{
32058
- * name: string mandatory,
32059
- * displayName: string, the origin name in dimsDef, see source helper.
32060
- * If displayName given, the tooltip will displayed vertically.
32061
- * coordDim: string mandatory,
32062
- * coordDimIndex: number mandatory,
32063
- * type: string optional,
32064
- * otherDims: { never null/undefined
32065
- * tooltip: number optional,
32066
- * label: number optional,
32067
- * itemName: number optional,
32068
- * seriesName: number optional,
32069
- * },
32070
- * isExtraCoord: boolean true if coord is generated
32071
- * (not specified in encode and not series specified)
32072
- * other props ...
32073
- * }]
32458
+ * @return {Array.<module:data/DataDimensionInfo>}
32074
32459
  */
32075
32460
  function completeDimensions(sysDims, source, opt) {
32076
32461
  if (!Source.isInstance(source)) {
@@ -32080,7 +32465,6 @@ function completeDimensions(sysDims, source, opt) {
32080
32465
  opt = opt || {};
32081
32466
  sysDims = (sysDims || []).slice();
32082
32467
  var dimsDef = (opt.dimsDef || []).slice();
32083
- var encodeDef = createHashMap(opt.encodeDef);
32084
32468
  var dataDimNameMap = createHashMap();
32085
32469
  var coordDimNameMap = createHashMap();
32086
32470
  // var valueCandidate;
@@ -32094,7 +32478,7 @@ function completeDimensions(sysDims, source, opt) {
32094
32478
  {}, isObject$1(dimsDef[i]) ? dimsDef[i] : {name: dimsDef[i]}
32095
32479
  );
32096
32480
  var userDimName = dimDefItem.name;
32097
- var resultItem = result[i] = {otherDims: {}};
32481
+ var resultItem = result[i] = new DataDimensionInfo();
32098
32482
  // Name will be applied later for avoiding duplication.
32099
32483
  if (userDimName != null && dataDimNameMap.get(userDimName) == null) {
32100
32484
  // Only if `series.dimensions` is defined in option
@@ -32107,6 +32491,12 @@ function completeDimensions(sysDims, source, opt) {
32107
32491
  dimDefItem.displayName != null && (resultItem.displayName = dimDefItem.displayName);
32108
32492
  }
32109
32493
 
32494
+ var encodeDef = opt.encodeDef;
32495
+ if (!encodeDef && opt.encodeDefaulter) {
32496
+ encodeDef = opt.encodeDefaulter(source, dimCount);
32497
+ }
32498
+ encodeDef = createHashMap(encodeDef);
32499
+
32110
32500
  // Set `coordDim` and `coordDimIndex` by `encodeDef` and normalize `encodeDef`.
32111
32501
  encodeDef.each(function (dataDims, coordDim) {
32112
32502
  dataDims = normalizeToArray(dataDims).slice();
@@ -32208,7 +32598,7 @@ function completeDimensions(sysDims, source, opt) {
32208
32598
 
32209
32599
  // Set dim `name` and other `coordDim` and other props.
32210
32600
  for (var resultDimIdx = 0; resultDimIdx < dimCount; resultDimIdx++) {
32211
- var resultItem = result[resultDimIdx] = result[resultDimIdx] || {};
32601
+ var resultItem = result[resultDimIdx] = result[resultDimIdx] || new DataDimensionInfo();
32212
32602
  var coordDim = resultItem.coordDim;
32213
32603
 
32214
32604
  if (coordDim == null) {
@@ -32227,7 +32617,28 @@ function completeDimensions(sysDims, source, opt) {
32227
32617
  dataDimNameMap
32228
32618
  ));
32229
32619
 
32230
- if (resultItem.type == null && guessOrdinal(source, resultDimIdx, resultItem.name)) {
32620
+ if (resultItem.type == null
32621
+ && (
32622
+ guessOrdinal(source, resultDimIdx, resultItem.name) === BE_ORDINAL.Must
32623
+ // Consider the case:
32624
+ // {
32625
+ // dataset: {source: [
32626
+ // ['2001', 123],
32627
+ // ['2002', 456],
32628
+ // ...
32629
+ // ['The others', 987],
32630
+ // ]},
32631
+ // series: {type: 'pie'}
32632
+ // }
32633
+ // The first colum should better be treated as a "ordinal" although it
32634
+ // might not able to be detected as an "ordinal" by `guessOrdinal`.
32635
+ || (resultItem.isExtraCoord
32636
+ && (resultItem.otherDims.itemName != null
32637
+ || resultItem.otherDims.seriesName != null
32638
+ )
32639
+ )
32640
+ )
32641
+ ) {
32231
32642
  resultItem.type = 'ordinal';
32232
32643
  }
32233
32644
  }
@@ -32305,6 +32716,7 @@ function genName(name, map$$1, fromZero) {
32305
32716
  * @param {string} [opt.generateCoordCount]
32306
32717
  * @param {Array.<string|Object>} [opt.dimensionsDefine=source.dimensionsDefine] Overwrite source define.
32307
32718
  * @param {Object|HashMap} [opt.encodeDefine=source.encodeDefine] Overwrite source define.
32719
+ * @param {Function} [opt.encodeDefaulter] Make default encode if user not specified.
32308
32720
  * @return {Array.<Object>} dimensionsInfo
32309
32721
  */
32310
32722
  var createDimensions = function (source, opt) {
@@ -32313,6 +32725,7 @@ var createDimensions = function (source, opt) {
32313
32725
  dimsDef: opt.dimensionsDefine || source.dimensionsDefine,
32314
32726
  encodeDef: opt.encodeDefine || source.encodeDefine,
32315
32727
  dimCount: opt.dimensionsCount,
32728
+ encodeDefaulter: opt.encodeDefaulter,
32316
32729
  generateCoord: opt.generateCoord,
32317
32730
  generateCoordCount: opt.generateCoordCount
32318
32731
  });
@@ -32337,6 +32750,201 @@ var createDimensions = function (source, opt) {
32337
32750
  * under the License.
32338
32751
  */
32339
32752
 
32753
+ /**
32754
+ * Helper for model references.
32755
+ * There are many manners to refer axis/coordSys.
32756
+ */
32757
+
32758
+ // TODO
32759
+ // merge relevant logic to this file?
32760
+ // check: "modelHelper" of tooltip and "BrushTargetManager".
32761
+
32762
+ /**
32763
+ * @class
32764
+ * For example:
32765
+ * {
32766
+ * coordSysName: 'cartesian2d',
32767
+ * coordSysDims: ['x', 'y', ...],
32768
+ * axisMap: HashMap({
32769
+ * x: xAxisModel,
32770
+ * y: yAxisModel
32771
+ * }),
32772
+ * categoryAxisMap: HashMap({
32773
+ * x: xAxisModel,
32774
+ * y: undefined
32775
+ * }),
32776
+ * // The index of the first category axis in `coordSysDims`.
32777
+ * // `null/undefined` means no category axis exists.
32778
+ * firstCategoryDimIndex: 1,
32779
+ * // To replace user specified encode.
32780
+ * }
32781
+ */
32782
+ function CoordSysInfo(coordSysName) {
32783
+ /**
32784
+ * @type {string}
32785
+ */
32786
+ this.coordSysName = coordSysName;
32787
+ /**
32788
+ * @type {Array.<string>}
32789
+ */
32790
+ this.coordSysDims = [];
32791
+ /**
32792
+ * @type {module:zrender/core/util#HashMap}
32793
+ */
32794
+ this.axisMap = createHashMap();
32795
+ /**
32796
+ * @type {module:zrender/core/util#HashMap}
32797
+ */
32798
+ this.categoryAxisMap = createHashMap();
32799
+ /**
32800
+ * @type {number}
32801
+ */
32802
+ this.firstCategoryDimIndex = null;
32803
+ }
32804
+
32805
+ /**
32806
+ * @return {module:model/referHelper#CoordSysInfo}
32807
+ */
32808
+ function getCoordSysInfoBySeries(seriesModel) {
32809
+ var coordSysName = seriesModel.get('coordinateSystem');
32810
+ var result = new CoordSysInfo(coordSysName);
32811
+ var fetch = fetchers[coordSysName];
32812
+ if (fetch) {
32813
+ fetch(seriesModel, result, result.axisMap, result.categoryAxisMap);
32814
+ return result;
32815
+ }
32816
+ }
32817
+
32818
+ var fetchers = {
32819
+
32820
+ cartesian2d: function (seriesModel, result, axisMap, categoryAxisMap) {
32821
+ var xAxisModel = seriesModel.getReferringComponents('xAxis')[0];
32822
+ var yAxisModel = seriesModel.getReferringComponents('yAxis')[0];
32823
+
32824
+ if (__DEV__) {
32825
+ if (!xAxisModel) {
32826
+ throw new Error('xAxis "' + retrieve(
32827
+ seriesModel.get('xAxisIndex'),
32828
+ seriesModel.get('xAxisId'),
32829
+ 0
32830
+ ) + '" not found');
32831
+ }
32832
+ if (!yAxisModel) {
32833
+ throw new Error('yAxis "' + retrieve(
32834
+ seriesModel.get('xAxisIndex'),
32835
+ seriesModel.get('yAxisId'),
32836
+ 0
32837
+ ) + '" not found');
32838
+ }
32839
+ }
32840
+
32841
+ result.coordSysDims = ['x', 'y'];
32842
+ axisMap.set('x', xAxisModel);
32843
+ axisMap.set('y', yAxisModel);
32844
+
32845
+ if (isCategory(xAxisModel)) {
32846
+ categoryAxisMap.set('x', xAxisModel);
32847
+ result.firstCategoryDimIndex = 0;
32848
+ }
32849
+ if (isCategory(yAxisModel)) {
32850
+ categoryAxisMap.set('y', yAxisModel);
32851
+ result.firstCategoryDimIndex == null & (result.firstCategoryDimIndex = 1);
32852
+ }
32853
+ },
32854
+
32855
+ singleAxis: function (seriesModel, result, axisMap, categoryAxisMap) {
32856
+ var singleAxisModel = seriesModel.getReferringComponents('singleAxis')[0];
32857
+
32858
+ if (__DEV__) {
32859
+ if (!singleAxisModel) {
32860
+ throw new Error('singleAxis should be specified.');
32861
+ }
32862
+ }
32863
+
32864
+ result.coordSysDims = ['single'];
32865
+ axisMap.set('single', singleAxisModel);
32866
+
32867
+ if (isCategory(singleAxisModel)) {
32868
+ categoryAxisMap.set('single', singleAxisModel);
32869
+ result.firstCategoryDimIndex = 0;
32870
+ }
32871
+ },
32872
+
32873
+ polar: function (seriesModel, result, axisMap, categoryAxisMap) {
32874
+ var polarModel = seriesModel.getReferringComponents('polar')[0];
32875
+ var radiusAxisModel = polarModel.findAxisModel('radiusAxis');
32876
+ var angleAxisModel = polarModel.findAxisModel('angleAxis');
32877
+
32878
+ if (__DEV__) {
32879
+ if (!angleAxisModel) {
32880
+ throw new Error('angleAxis option not found');
32881
+ }
32882
+ if (!radiusAxisModel) {
32883
+ throw new Error('radiusAxis option not found');
32884
+ }
32885
+ }
32886
+
32887
+ result.coordSysDims = ['radius', 'angle'];
32888
+ axisMap.set('radius', radiusAxisModel);
32889
+ axisMap.set('angle', angleAxisModel);
32890
+
32891
+ if (isCategory(radiusAxisModel)) {
32892
+ categoryAxisMap.set('radius', radiusAxisModel);
32893
+ result.firstCategoryDimIndex = 0;
32894
+ }
32895
+ if (isCategory(angleAxisModel)) {
32896
+ categoryAxisMap.set('angle', angleAxisModel);
32897
+ result.firstCategoryDimIndex == null && (result.firstCategoryDimIndex = 1);
32898
+ }
32899
+ },
32900
+
32901
+ geo: function (seriesModel, result, axisMap, categoryAxisMap) {
32902
+ result.coordSysDims = ['lng', 'lat'];
32903
+ },
32904
+
32905
+ parallel: function (seriesModel, result, axisMap, categoryAxisMap) {
32906
+ var ecModel = seriesModel.ecModel;
32907
+ var parallelModel = ecModel.getComponent(
32908
+ 'parallel', seriesModel.get('parallelIndex')
32909
+ );
32910
+ var coordSysDims = result.coordSysDims = parallelModel.dimensions.slice();
32911
+
32912
+ each$1(parallelModel.parallelAxisIndex, function (axisIndex, index) {
32913
+ var axisModel = ecModel.getComponent('parallelAxis', axisIndex);
32914
+ var axisDim = coordSysDims[index];
32915
+ axisMap.set(axisDim, axisModel);
32916
+
32917
+ if (isCategory(axisModel) && result.firstCategoryDimIndex == null) {
32918
+ categoryAxisMap.set(axisDim, axisModel);
32919
+ result.firstCategoryDimIndex = index;
32920
+ }
32921
+ });
32922
+ }
32923
+ };
32924
+
32925
+ function isCategory(axisModel) {
32926
+ return axisModel.get('type') === 'category';
32927
+ }
32928
+
32929
+ /*
32930
+ * Licensed to the Apache Software Foundation (ASF) under one
32931
+ * or more contributor license agreements. See the NOTICE file
32932
+ * distributed with this work for additional information
32933
+ * regarding copyright ownership. The ASF licenses this file
32934
+ * to you under the Apache License, Version 2.0 (the
32935
+ * "License"); you may not use this file except in compliance
32936
+ * with the License. You may obtain a copy of the License at
32937
+ *
32938
+ * http://www.apache.org/licenses/LICENSE-2.0
32939
+ *
32940
+ * Unless required by applicable law or agreed to in writing,
32941
+ * software distributed under the License is distributed on an
32942
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
32943
+ * KIND, either express or implied. See the License for the
32944
+ * specific language governing permissions and limitations
32945
+ * under the License.
32946
+ */
32947
+
32340
32948
  /**
32341
32949
  * Note that it is too complicated to support 3d stack by value
32342
32950
  * (have to create two-dimension inverted index), so in 3d case
@@ -32503,6 +33111,7 @@ function getStackedDimension(data, targetDim) {
32503
33111
  * @param {module:echarts/model/Series} seriesModel
32504
33112
  * @param {Object} [opt]
32505
33113
  * @param {string} [opt.generateCoord]
33114
+ * @param {boolean} [opt.useEncodeDefaulter]
32506
33115
  */
32507
33116
  function createListFromArray(source, seriesModel, opt) {
32508
33117
  opt = opt || {};
@@ -32514,14 +33123,14 @@ function createListFromArray(source, seriesModel, opt) {
32514
33123
  var coordSysName = seriesModel.get('coordinateSystem');
32515
33124
  var registeredCoordSys = CoordinateSystemManager.get(coordSysName);
32516
33125
 
32517
- var coordSysDefine = getCoordSysDefineBySeries(seriesModel);
33126
+ var coordSysInfo = getCoordSysInfoBySeries(seriesModel);
32518
33127
 
32519
33128
  var coordSysDimDefs;
32520
33129
 
32521
- if (coordSysDefine) {
32522
- coordSysDimDefs = map(coordSysDefine.coordSysDims, function (dim) {
33130
+ if (coordSysInfo) {
33131
+ coordSysDimDefs = map(coordSysInfo.coordSysDims, function (dim) {
32523
33132
  var dimInfo = {name: dim};
32524
- var axisModel = coordSysDefine.axisMap.get(dim);
33133
+ var axisModel = coordSysInfo.axisMap.get(dim);
32525
33134
  if (axisModel) {
32526
33135
  var axisType = axisModel.get('type');
32527
33136
  dimInfo.type = getDimensionTypeByAxis(axisType);
@@ -32542,14 +33151,17 @@ function createListFromArray(source, seriesModel, opt) {
32542
33151
 
32543
33152
  var dimInfoList = createDimensions(source, {
32544
33153
  coordDimensions: coordSysDimDefs,
32545
- generateCoord: opt.generateCoord
33154
+ generateCoord: opt.generateCoord,
33155
+ encodeDefaulter: opt.useEncodeDefaulter
33156
+ ? curry(makeSeriesEncodeForAxisCoordSys, coordSysDimDefs, seriesModel)
33157
+ : null
32546
33158
  });
32547
33159
 
32548
33160
  var firstCategoryDimIndex;
32549
33161
  var hasNameEncode;
32550
- coordSysDefine && each$1(dimInfoList, function (dimInfo, dimIndex) {
33162
+ coordSysInfo && each$1(dimInfoList, function (dimInfo, dimIndex) {
32551
33163
  var coordDim = dimInfo.coordDim;
32552
- var categoryAxisModel = coordSysDefine.categoryAxisMap.get(coordDim);
33164
+ var categoryAxisModel = coordSysInfo.categoryAxisMap.get(coordDim);
32553
33165
  if (categoryAxisModel) {
32554
33166
  if (firstCategoryDimIndex == null) {
32555
33167
  firstCategoryDimIndex = dimIndex;
@@ -33121,44 +33733,6 @@ function fixExtent(niceTickExtent, extent) {
33121
33733
  }
33122
33734
  }
33123
33735
 
33124
- function intervalScaleGetTicks(interval, extent, niceTickExtent, intervalPrecision) {
33125
- var ticks = [];
33126
-
33127
- // If interval is 0, return [];
33128
- if (!interval) {
33129
- return ticks;
33130
- }
33131
-
33132
- // Consider this case: using dataZoom toolbox, zoom and zoom.
33133
- var safeLimit = 10000;
33134
-
33135
- if (extent[0] < niceTickExtent[0]) {
33136
- ticks.push(extent[0]);
33137
- }
33138
- var tick = niceTickExtent[0];
33139
-
33140
- while (tick <= niceTickExtent[1]) {
33141
- ticks.push(tick);
33142
- // Avoid rounding error
33143
- tick = roundNumber$1(tick + interval, intervalPrecision);
33144
- if (tick === ticks[ticks.length - 1]) {
33145
- // Consider out of safe float point, e.g.,
33146
- // -3711126.9907707 + 2e-10 === -3711126.9907707
33147
- break;
33148
- }
33149
- if (ticks.length > safeLimit) {
33150
- return [];
33151
- }
33152
- }
33153
- // Consider this case: the last item of ticks is smaller
33154
- // than niceTickExtent[1] and niceTickExtent[1] === extent[1].
33155
- if (extent[1] > (ticks.length ? ticks[ticks.length - 1] : niceTickExtent[1])) {
33156
- ticks.push(extent[1]);
33157
- }
33158
-
33159
- return ticks;
33160
- }
33161
-
33162
33736
  /*
33163
33737
  * Licensed to the Apache Software Foundation (ASF) under one
33164
33738
  * or more contributor license agreements. See the NOTICE file
@@ -33237,12 +33811,92 @@ var IntervalScale = Scale.extend({
33237
33811
  },
33238
33812
 
33239
33813
  /**
33814
+ * @param {boolean} [expandToNicedExtent=false] If expand the ticks to niced extent.
33240
33815
  * @return {Array.<number>}
33241
33816
  */
33242
- getTicks: function () {
33243
- return intervalScaleGetTicks(
33244
- this._interval, this._extent, this._niceExtent, this._intervalPrecision
33245
- );
33817
+ getTicks: function (expandToNicedExtent) {
33818
+ var interval = this._interval;
33819
+ var extent = this._extent;
33820
+ var niceTickExtent = this._niceExtent;
33821
+ var intervalPrecision = this._intervalPrecision;
33822
+
33823
+ var ticks = [];
33824
+ // If interval is 0, return [];
33825
+ if (!interval) {
33826
+ return ticks;
33827
+ }
33828
+
33829
+ // Consider this case: using dataZoom toolbox, zoom and zoom.
33830
+ var safeLimit = 10000;
33831
+
33832
+ if (extent[0] < niceTickExtent[0]) {
33833
+ if (expandToNicedExtent) {
33834
+ ticks.push(roundNumber(niceTickExtent[0] - interval));
33835
+ }
33836
+ else {
33837
+ ticks.push(extent[0]);
33838
+ }
33839
+ }
33840
+ var tick = niceTickExtent[0];
33841
+
33842
+ while (tick <= niceTickExtent[1]) {
33843
+ ticks.push(tick);
33844
+ // Avoid rounding error
33845
+ tick = roundNumber(tick + interval, intervalPrecision);
33846
+ if (tick === ticks[ticks.length - 1]) {
33847
+ // Consider out of safe float point, e.g.,
33848
+ // -3711126.9907707 + 2e-10 === -3711126.9907707
33849
+ break;
33850
+ }
33851
+ if (ticks.length > safeLimit) {
33852
+ return [];
33853
+ }
33854
+ }
33855
+ // Consider this case: the last item of ticks is smaller
33856
+ // than niceTickExtent[1] and niceTickExtent[1] === extent[1].
33857
+ var lastNiceTick = ticks.length ? ticks[ticks.length - 1] : niceTickExtent[1];
33858
+ if (extent[1] > lastNiceTick) {
33859
+ if (expandToNicedExtent) {
33860
+ ticks.push(lastNiceTick + interval);
33861
+ }
33862
+ else {
33863
+ ticks.push(extent[1]);
33864
+ }
33865
+ }
33866
+
33867
+ return ticks;
33868
+ },
33869
+
33870
+ /**
33871
+ * @param {number} [splitNumber=5]
33872
+ * @return {Array.<Array.<number>>}
33873
+ */
33874
+ getMinorTicks: function (splitNumber) {
33875
+ var ticks = this.getTicks(true);
33876
+ var minorTicks = [];
33877
+ var extent = this.getExtent();
33878
+
33879
+ for (var i = 1; i < ticks.length; i++) {
33880
+ var nextTick = ticks[i];
33881
+ var prevTick = ticks[i - 1];
33882
+ var count = 0;
33883
+ var minorTicksGroup = [];
33884
+ var interval = nextTick - prevTick;
33885
+ var minorInterval = interval / splitNumber;
33886
+
33887
+ while (count < splitNumber - 1) {
33888
+ var minorTick = round$1(prevTick + (count + 1) * minorInterval);
33889
+
33890
+ // For the first and last interval. The count may be less than splitNumber.
33891
+ if (minorTick > extent[0] && minorTick < extent[1]) {
33892
+ minorTicksGroup.push(minorTick);
33893
+ }
33894
+ count++;
33895
+ }
33896
+ minorTicks.push(minorTicksGroup);
33897
+ }
33898
+
33899
+ return minorTicks;
33246
33900
  },
33247
33901
 
33248
33902
  /**
@@ -33581,7 +34235,6 @@ function doCalBarWidthAndOffset(seriesInfoList) {
33581
34235
  // only the attributes set on the last series will work.
33582
34236
  // Do not change this fact unless there will be a break change.
33583
34237
 
33584
- // TODO
33585
34238
  var barWidth = seriesInfo.barWidth;
33586
34239
  if (barWidth && !stacks[stackId].width) {
33587
34240
  // See #6312, do not restrict width.
@@ -33621,6 +34274,7 @@ function doCalBarWidthAndOffset(seriesInfoList) {
33621
34274
  each$1(stacks, function (column) {
33622
34275
  var maxWidth = column.maxWidth;
33623
34276
  var minWidth = column.minWidth;
34277
+
33624
34278
  if (!column.width) {
33625
34279
  var finalWidth = autoWidth;
33626
34280
  if (maxWidth && maxWidth < finalWidth) {
@@ -33636,7 +34290,7 @@ function doCalBarWidthAndOffset(seriesInfoList) {
33636
34290
  }
33637
34291
  if (finalWidth !== autoWidth) {
33638
34292
  column.width = finalWidth;
33639
- remainedWidth -= finalWidth;
34293
+ remainedWidth -= finalWidth + barGapPercent * finalWidth;
33640
34294
  autoWidthCount--;
33641
34295
  }
33642
34296
  }
@@ -33653,7 +34307,7 @@ function doCalBarWidthAndOffset(seriesInfoList) {
33653
34307
  finalWidth = Math.max(finalWidth, minWidth);
33654
34308
  }
33655
34309
  column.width = finalWidth;
33656
- remainedWidth -= finalWidth;
34310
+ remainedWidth -= finalWidth + barGapPercent * finalWidth;
33657
34311
  autoWidthCount--;
33658
34312
  }
33659
34313
  });
@@ -33661,8 +34315,10 @@ function doCalBarWidthAndOffset(seriesInfoList) {
33661
34315
  // Recalculate width again
33662
34316
  autoWidth = (remainedWidth - categoryGap)
33663
34317
  / (autoWidthCount + (autoWidthCount - 1) * barGapPercent);
34318
+
33664
34319
  autoWidth = Math.max(autoWidth, 0);
33665
34320
 
34321
+
33666
34322
  var widthSum = 0;
33667
34323
  var lastColumn;
33668
34324
  each$1(stacks, function (column, idx) {
@@ -33801,6 +34457,7 @@ function layout(seriesType, ecModel) {
33801
34457
  }
33802
34458
  stacked && (lastStackCoords[stackId][baseValue][sign] += height);
33803
34459
  }
34460
+
33804
34461
  data.setItemLayout(idx, {
33805
34462
  x: x,
33806
34463
  y: y,
@@ -34161,14 +34818,15 @@ var LogScale = Scale.extend({
34161
34818
  },
34162
34819
 
34163
34820
  /**
34821
+ * @param {boolean} [expandToNicedExtent=false] If expand the ticks to niced extent.
34164
34822
  * @return {Array.<number>}
34165
34823
  */
34166
- getTicks: function () {
34824
+ getTicks: function (expandToNicedExtent) {
34167
34825
  var originalScale = this._originalScale;
34168
34826
  var extent = this._extent;
34169
34827
  var originalExtent = originalScale.getExtent();
34170
34828
 
34171
- return map(intervalScaleProto$1.getTicks.call(this), function (val) {
34829
+ return map(intervalScaleProto$1.getTicks.call(this, expandToNicedExtent), function (val) {
34172
34830
  var powVal = round$1(mathPow$1(this.base, val));
34173
34831
 
34174
34832
  // Fix #4158
@@ -34183,6 +34841,12 @@ var LogScale = Scale.extend({
34183
34841
  }, this);
34184
34842
  },
34185
34843
 
34844
+ /**
34845
+ * @param {number} splitNumber
34846
+ * @return {Array.<Array.<number>>}
34847
+ */
34848
+ getMinorTicks: intervalScaleProto$1.getMinorTicks,
34849
+
34186
34850
  /**
34187
34851
  * @param {number} val
34188
34852
  * @return {string}
@@ -36046,7 +36710,7 @@ Axis.prototype = {
36046
36710
  * @return {boolean}
36047
36711
  */
36048
36712
  containData: function (data) {
36049
- return this.contain(this.dataToCoord(data));
36713
+ return this.scale.contain(data);
36050
36714
  },
36051
36715
 
36052
36716
  /**
@@ -36134,7 +36798,7 @@ Axis.prototype = {
36134
36798
  * `axis.getTicksCoords` considers `onBand`, which is used by
36135
36799
  * `boundaryGap:true` of category axis and splitLine and splitArea.
36136
36800
  * @param {Object} [opt]
36137
- * @param {number} [opt.tickModel=axis.model.getModel('axisTick')]
36801
+ * @param {Model} [opt.tickModel=axis.model.getModel('axisTick')]
36138
36802
  * @param {boolean} [opt.clamp] If `true`, the first and the last
36139
36803
  * tick must be at the axis end points. Otherwise, clip ticks
36140
36804
  * that outside the axis extent.
@@ -36166,6 +36830,33 @@ Axis.prototype = {
36166
36830
  return ticksCoords;
36167
36831
  },
36168
36832
 
36833
+ /**
36834
+ * @return {Array.<Array.<Object>>} [{ coord: ..., tickValue: ...}]
36835
+ */
36836
+ getMinorTicksCoords: function () {
36837
+ if (this.scale.type === 'ordinal') {
36838
+ // Category axis doesn't support minor ticks
36839
+ return [];
36840
+ }
36841
+
36842
+ var minorTickModel = this.model.getModel('minorTick');
36843
+ var splitNumber = minorTickModel.get('splitNumber');
36844
+ // Protection.
36845
+ if (!(splitNumber > 0 && splitNumber < 100)) {
36846
+ splitNumber = 5;
36847
+ }
36848
+ var minorTicks = this.scale.getMinorTicks(splitNumber);
36849
+ var minorTicksCoords = map(minorTicks, function (minorTicksGroup) {
36850
+ return map(minorTicksGroup, function (minorTick) {
36851
+ return {
36852
+ coord: this.dataToCoord(minorTick),
36853
+ tickValue: minorTick
36854
+ };
36855
+ }, this);
36856
+ }, this);
36857
+ return minorTicksCoords;
36858
+ },
36859
+
36169
36860
  /**
36170
36861
  * @return {Array.<Object>} [{
36171
36862
  * formattedLabel: string,
@@ -36408,7 +37099,7 @@ SeriesModel.extend({
36408
37099
  throw new Error('Line not support coordinateSystem besides cartesian and polar');
36409
37100
  }
36410
37101
  }
36411
- return createListFromArray(this.getSource(), this);
37102
+ return createListFromArray(this.getSource(), this, {useEncodeDefaulter: true});
36412
37103
  },
36413
37104
 
36414
37105
  defaultOption: {
@@ -38252,7 +38943,7 @@ Chart.extend({
38252
38943
  // FIXME step not support polar
38253
38944
  var step = !isCoordSysPolar && seriesModel.get('step');
38254
38945
  var clipShapeForSymbol;
38255
- if (coordSys && coordSys.getArea) {
38946
+ if (coordSys && coordSys.getArea && seriesModel.get('clip', true)) {
38256
38947
  clipShapeForSymbol = coordSys.getArea();
38257
38948
  // Avoid float number rounding error for symbol on the edge of axis extent.
38258
38949
  // See #7913 and `test/dataZoom-clip.html`.
@@ -38267,6 +38958,7 @@ Chart.extend({
38267
38958
  clipShapeForSymbol.r1 += 0.5;
38268
38959
  }
38269
38960
  }
38961
+ this._clipShapeForSymbol = clipShapeForSymbol;
38270
38962
  // Initialization animation or coordinate system changed
38271
38963
  if (
38272
38964
  !(polyline && prevCoordSys.type === coordSys.type && step === this._step)
@@ -38419,6 +39111,10 @@ Chart.extend({
38419
39111
  // Null data
38420
39112
  return;
38421
39113
  }
39114
+ // fix #11360: should't draw symbol outside clipShapeForSymbol
39115
+ if (this._clipShapeForSymbol && !this._clipShapeForSymbol.contain(pt[0], pt[1])) {
39116
+ return;
39117
+ }
38422
39118
  symbol = new SymbolClz$1(data, dataIndex);
38423
39119
  symbol.position = pt;
38424
39120
  symbol.setZ(
@@ -39474,7 +40170,7 @@ axisDefault.valueAxis = merge({
39474
40170
  // scale: false,
39475
40171
 
39476
40172
  // AxisTick and axisLabel and splitLine are caculated based on splitNumber.
39477
- splitNumber: 5
40173
+ splitNumber: 5,
39478
40174
 
39479
40175
  // Interval specifies the span of the ticks is mandatorily.
39480
40176
  // interval: null
@@ -39485,6 +40181,30 @@ axisDefault.valueAxis = merge({
39485
40181
  // Specify max interval when auto calculate tick interval.
39486
40182
  // maxInterval: null
39487
40183
 
40184
+ minorTick: {
40185
+ // Minor tick, not available for cateogry axis.
40186
+ show: false,
40187
+ // Split number of minor ticks. The value should be in range of (0, 100)
40188
+ splitNumber: 5,
40189
+ // Lenght of minor tick
40190
+ length: 3,
40191
+
40192
+ // Same inside with axisTick
40193
+
40194
+ // Line style
40195
+ lineStyle: {
40196
+ // Default to be same with axisTick
40197
+ }
40198
+ },
40199
+
40200
+ minorSplitLine: {
40201
+ show: false,
40202
+
40203
+ lineStyle: {
40204
+ color: '#eee',
40205
+ width: 1
40206
+ }
40207
+ }
39488
40208
  }, defaultOption);
39489
40209
 
39490
40210
  axisDefault.timeAxis = defaults({
@@ -40601,10 +41321,12 @@ var builders = {
40601
41321
  var axisModel = this.axisModel;
40602
41322
  var opt = this.opt;
40603
41323
 
40604
- var tickEls = buildAxisTick(this, axisModel, opt);
41324
+ var ticksEls = buildAxisMajorTicks(this, axisModel, opt);
40605
41325
  var labelEls = buildAxisLabel(this, axisModel, opt);
40606
41326
 
40607
- fixMinMaxLabelShow(axisModel, labelEls, tickEls);
41327
+ fixMinMaxLabelShow(axisModel, labelEls, ticksEls);
41328
+
41329
+ buildAxisMinorTicks(this, axisModel, opt);
40608
41330
  },
40609
41331
 
40610
41332
  /**
@@ -40923,42 +41645,27 @@ function isNameLocationCenter(nameLocation) {
40923
41645
  return nameLocation === 'middle' || nameLocation === 'center';
40924
41646
  }
40925
41647
 
40926
- function buildAxisTick(axisBuilder, axisModel, opt) {
40927
- var axis = axisModel.axis;
40928
-
40929
- if (!axisModel.get('axisTick.show') || axis.scale.isBlank()) {
40930
- return;
40931
- }
40932
-
40933
- var tickModel = axisModel.getModel('axisTick');
40934
-
40935
- var lineStyleModel = tickModel.getModel('lineStyle');
40936
- var tickLen = tickModel.get('length');
40937
-
40938
- var ticksCoords = axis.getTicksCoords();
40939
41648
 
41649
+ function createTicks(ticksCoords, tickTransform, tickEndCoord, tickLineStyle, aniid) {
41650
+ var tickEls = [];
40940
41651
  var pt1 = [];
40941
41652
  var pt2 = [];
40942
- var matrix = axisBuilder._transform;
40943
-
40944
- var tickEls = [];
40945
-
40946
41653
  for (var i = 0; i < ticksCoords.length; i++) {
40947
41654
  var tickCoord = ticksCoords[i].coord;
40948
41655
 
40949
41656
  pt1[0] = tickCoord;
40950
41657
  pt1[1] = 0;
40951
41658
  pt2[0] = tickCoord;
40952
- pt2[1] = opt.tickDirection * tickLen;
41659
+ pt2[1] = tickEndCoord;
40953
41660
 
40954
- if (matrix) {
40955
- applyTransform(pt1, pt1, matrix);
40956
- applyTransform(pt2, pt2, matrix);
41661
+ if (tickTransform) {
41662
+ applyTransform(pt1, pt1, tickTransform);
41663
+ applyTransform(pt2, pt2, tickTransform);
40957
41664
  }
40958
41665
  // Tick line, Not use group transform to have better line draw
40959
41666
  var tickEl = new Line({
40960
41667
  // Id for animation
40961
- anid: 'tick_' + ticksCoords[i].tickValue,
41668
+ anid: aniid + '_' + ticksCoords[i].tickValue,
40962
41669
  subPixelOptimize: true,
40963
41670
  shape: {
40964
41671
  x1: pt1[0],
@@ -40966,22 +41673,80 @@ function buildAxisTick(axisBuilder, axisModel, opt) {
40966
41673
  x2: pt2[0],
40967
41674
  y2: pt2[1]
40968
41675
  },
40969
- style: defaults(
40970
- lineStyleModel.getLineStyle(),
40971
- {
40972
- stroke: axisModel.get('axisLine.lineStyle.color')
40973
- }
40974
- ),
41676
+ style: tickLineStyle,
40975
41677
  z2: 2,
40976
41678
  silent: true
40977
41679
  });
40978
- axisBuilder.group.add(tickEl);
40979
41680
  tickEls.push(tickEl);
40980
41681
  }
40981
-
40982
41682
  return tickEls;
40983
41683
  }
40984
41684
 
41685
+ function buildAxisMajorTicks(axisBuilder, axisModel, opt) {
41686
+ var axis = axisModel.axis;
41687
+
41688
+ var tickModel = axisModel.getModel('axisTick');
41689
+
41690
+ if (!tickModel.get('show') || axis.scale.isBlank()) {
41691
+ return;
41692
+ }
41693
+
41694
+ var lineStyleModel = tickModel.getModel('lineStyle');
41695
+ var tickEndCoord = opt.tickDirection * tickModel.get('length');
41696
+
41697
+ var ticksCoords = axis.getTicksCoords();
41698
+
41699
+ var ticksEls = createTicks(ticksCoords, axisBuilder._transform, tickEndCoord, defaults(
41700
+ lineStyleModel.getLineStyle(),
41701
+ {
41702
+ stroke: axisModel.get('axisLine.lineStyle.color')
41703
+ }
41704
+ ), 'ticks');
41705
+
41706
+ for (var i = 0; i < ticksEls.length; i++) {
41707
+ axisBuilder.group.add(ticksEls[i]);
41708
+ }
41709
+
41710
+ return ticksEls;
41711
+ }
41712
+
41713
+ function buildAxisMinorTicks(axisBuilder, axisModel, opt) {
41714
+ var axis = axisModel.axis;
41715
+
41716
+ var minorTickModel = axisModel.getModel('minorTick');
41717
+
41718
+ if (!minorTickModel.get('show') || axis.scale.isBlank()) {
41719
+ return;
41720
+ }
41721
+
41722
+ var minorTicksCoords = axis.getMinorTicksCoords();
41723
+ if (!minorTicksCoords.length) {
41724
+ return;
41725
+ }
41726
+
41727
+ var lineStyleModel = minorTickModel.getModel('lineStyle');
41728
+ var tickEndCoord = opt.tickDirection * minorTickModel.get('length');
41729
+
41730
+ var minorTickLineStyle = defaults(
41731
+ lineStyleModel.getLineStyle(),
41732
+ defaults(
41733
+ axisModel.getModel('axisTick').getLineStyle(),
41734
+ {
41735
+ stroke: axisModel.get('axisLine.lineStyle.color')
41736
+ }
41737
+ )
41738
+ );
41739
+
41740
+ for (var i = 0; i < minorTicksCoords.length; i++) {
41741
+ var minorTicksEls = createTicks(
41742
+ minorTicksCoords[i], axisBuilder._transform, tickEndCoord, minorTickLineStyle, 'minorticks_' + i
41743
+ );
41744
+ for (var k = 0; k < minorTicksEls.length; k++) {
41745
+ axisBuilder.group.add(minorTicksEls[k]);
41746
+ }
41747
+ }
41748
+ }
41749
+
40985
41750
  function buildAxisLabel(axisBuilder, axisModel, opt) {
40986
41751
  var axis = axisModel.axis;
40987
41752
  var show = retrieve(opt.axisLabelShow, axisModel.get('axisLabel.show'));
@@ -41650,17 +42415,9 @@ var axisBuilderAttrs = [
41650
42415
  'axisLine', 'axisTickLabel', 'axisName'
41651
42416
  ];
41652
42417
  var selfBuilderAttrs = [
41653
- 'splitArea', 'splitLine'
42418
+ 'splitArea', 'splitLine', 'minorSplitLine'
41654
42419
  ];
41655
42420
 
41656
- // function getAlignWithLabel(model, axisModel) {
41657
- // var alignWithLabel = model.get('alignWithLabel');
41658
- // if (alignWithLabel === 'auto') {
41659
- // alignWithLabel = axisModel.get('axisTick.alignWithLabel');
41660
- // }
41661
- // return alignWithLabel;
41662
- // }
41663
-
41664
42421
  var CartesianAxisView = AxisView.extend({
41665
42422
 
41666
42423
  type: 'cartesianAxis',
@@ -41738,8 +42495,6 @@ var CartesianAxisView = AxisView.extend({
41738
42495
  var p1 = [];
41739
42496
  var p2 = [];
41740
42497
 
41741
- // Simple optimization
41742
- // Batching the lines if color are the same
41743
42498
  var lineStyle = lineStyleModel.getLineStyle();
41744
42499
  for (var i = 0; i < ticksCoords.length; i++) {
41745
42500
  var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord);
@@ -41776,6 +42531,63 @@ var CartesianAxisView = AxisView.extend({
41776
42531
  }
41777
42532
  },
41778
42533
 
42534
+ /**
42535
+ * @param {module:echarts/coord/cartesian/AxisModel} axisModel
42536
+ * @param {module:echarts/coord/cartesian/GridModel} gridModel
42537
+ * @private
42538
+ */
42539
+ _minorSplitLine: function (axisModel, gridModel) {
42540
+ var axis = axisModel.axis;
42541
+
42542
+ var minorSplitLineModel = axisModel.getModel('minorSplitLine');
42543
+ var lineStyleModel = minorSplitLineModel.getModel('lineStyle');
42544
+
42545
+ var gridRect = gridModel.coordinateSystem.getRect();
42546
+ var isHorizontal = axis.isHorizontal();
42547
+
42548
+ var minorTicksCoords = axis.getMinorTicksCoords();
42549
+ if (!minorTicksCoords.length) {
42550
+ return;
42551
+ }
42552
+ var p1 = [];
42553
+ var p2 = [];
42554
+
42555
+ var lineStyle = lineStyleModel.getLineStyle();
42556
+
42557
+
42558
+ for (var i = 0; i < minorTicksCoords.length; i++) {
42559
+ for (var k = 0; k < minorTicksCoords[i].length; k++) {
42560
+ var tickCoord = axis.toGlobalCoord(minorTicksCoords[i][k].coord);
42561
+
42562
+ if (isHorizontal) {
42563
+ p1[0] = tickCoord;
42564
+ p1[1] = gridRect.y;
42565
+ p2[0] = tickCoord;
42566
+ p2[1] = gridRect.y + gridRect.height;
42567
+ }
42568
+ else {
42569
+ p1[0] = gridRect.x;
42570
+ p1[1] = tickCoord;
42571
+ p2[0] = gridRect.x + gridRect.width;
42572
+ p2[1] = tickCoord;
42573
+ }
42574
+
42575
+ this._axisGroup.add(new Line({
42576
+ anid: 'minor_line_' + minorTicksCoords[i][k].tickValue,
42577
+ subPixelOptimize: true,
42578
+ shape: {
42579
+ x1: p1[0],
42580
+ y1: p1[1],
42581
+ x2: p2[0],
42582
+ y2: p2[1]
42583
+ },
42584
+ style: lineStyle,
42585
+ silent: true
42586
+ }));
42587
+ }
42588
+ }
42589
+ },
42590
+
41779
42591
  /**
41780
42592
  * @param {module:echarts/coord/cartesian/AxisModel} axisModel
41781
42593
  * @param {module:echarts/coord/cartesian/GridModel} gridModel
@@ -41996,7 +42808,7 @@ var BaseBarSeries = SeriesModel.extend({
41996
42808
  type: 'series.__base_bar__',
41997
42809
 
41998
42810
  getInitialData: function (option, ecModel) {
41999
- return createListFromArray(this.getSource(), this);
42811
+ return createListFromArray(this.getSource(), this, {useEncodeDefaulter: true});
42000
42812
  },
42001
42813
 
42002
42814
  getMarkerPosition: function (value) {
@@ -42700,11 +43512,18 @@ var getLayout = {
42700
43512
  }
42701
43513
  };
42702
43514
 
43515
+ function isZeroOnPolar(layout) {
43516
+ return layout.startAngle != null
43517
+ && layout.endAngle != null
43518
+ && layout.startAngle === layout.endAngle;
43519
+ }
43520
+
42703
43521
  function updateStyle(
42704
43522
  el, data, dataIndex, itemModel, layout, seriesModel, isHorizontal, isPolar
42705
43523
  ) {
42706
43524
  var color = data.getItemVisual(dataIndex, 'color');
42707
43525
  var opacity = data.getItemVisual(dataIndex, 'opacity');
43526
+ var stroke = data.getVisual('borderColor');
42708
43527
  var itemStyleModel = itemModel.getModel('itemStyle');
42709
43528
  var hoverStyle = itemModel.getModel('emphasis.itemStyle').getBarItemStyle();
42710
43529
 
@@ -42714,7 +43533,8 @@ function updateStyle(
42714
43533
 
42715
43534
  el.useStyle(defaults(
42716
43535
  {
42717
- fill: color,
43536
+ stroke: isZeroOnPolar(layout) ? 'none' : stroke,
43537
+ fill: isZeroOnPolar(layout) ? 'none' : color,
42718
43538
  opacity: opacity
42719
43539
  },
42720
43540
  itemStyleModel.getBarItemStyle()
@@ -42733,7 +43553,9 @@ function updateStyle(
42733
43553
  seriesModel, dataIndex, labelPositionOutside
42734
43554
  );
42735
43555
  }
42736
-
43556
+ if (isZeroOnPolar(layout)) {
43557
+ hoverStyle.fill = hoverStyle.stroke = 'none';
43558
+ }
42737
43559
  setHoverStyle(el, hoverStyle);
42738
43560
  }
42739
43561
 
@@ -43054,6 +43876,60 @@ var dataSelectableMixin = {
43054
43876
  * under the License.
43055
43877
  */
43056
43878
 
43879
+
43880
+ /**
43881
+ * LegendVisualProvider is an bridge that pick encoded color from data and
43882
+ * provide to the legend component.
43883
+ * @param {Function} getDataWithEncodedVisual Function to get data after filtered. It stores all the encoding info
43884
+ * @param {Function} getRawData Function to get raw data before filtered.
43885
+ */
43886
+ function LegendVisualProvider(getDataWithEncodedVisual, getRawData) {
43887
+ this.getAllNames = function () {
43888
+ var rawData = getRawData();
43889
+ // We find the name from the raw data. In case it's filtered by the legend component.
43890
+ // Normally, the name can be found in rawData, but can't be found in filtered data will display as gray.
43891
+ return rawData.mapArray(rawData.getName);
43892
+ };
43893
+
43894
+ this.containName = function (name) {
43895
+ var rawData = getRawData();
43896
+ return rawData.indexOfName(name) >= 0;
43897
+ };
43898
+
43899
+ this.indexOfName = function (name) {
43900
+ // Only get data when necessary.
43901
+ // Because LegendVisualProvider constructor may be new in the stage that data is not prepared yet.
43902
+ // Invoking Series#getData immediately will throw an error.
43903
+ var dataWithEncodedVisual = getDataWithEncodedVisual();
43904
+ return dataWithEncodedVisual.indexOfName(name);
43905
+ };
43906
+
43907
+ this.getItemVisual = function (dataIndex, key) {
43908
+ // Get encoded visual properties from final filtered data.
43909
+ var dataWithEncodedVisual = getDataWithEncodedVisual();
43910
+ return dataWithEncodedVisual.getItemVisual(dataIndex, key);
43911
+ };
43912
+ }
43913
+
43914
+ /*
43915
+ * Licensed to the Apache Software Foundation (ASF) under one
43916
+ * or more contributor license agreements. See the NOTICE file
43917
+ * distributed with this work for additional information
43918
+ * regarding copyright ownership. The ASF licenses this file
43919
+ * to you under the Apache License, Version 2.0 (the
43920
+ * "License"); you may not use this file except in compliance
43921
+ * with the License. You may obtain a copy of the License at
43922
+ *
43923
+ * http://www.apache.org/licenses/LICENSE-2.0
43924
+ *
43925
+ * Unless required by applicable law or agreed to in writing,
43926
+ * software distributed under the License is distributed on an
43927
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
43928
+ * KIND, either express or implied. See the License for the
43929
+ * specific language governing permissions and limitations
43930
+ * under the License.
43931
+ */
43932
+
43057
43933
  var PieSeries = extendSeriesModel({
43058
43934
 
43059
43935
  type: 'series.pie',
@@ -43064,9 +43940,9 @@ var PieSeries = extendSeriesModel({
43064
43940
 
43065
43941
  // Enable legend selection for each data item
43066
43942
  // Use a function instead of direct access because data reference may changed
43067
- this.legendDataProvider = function () {
43068
- return this.getRawData();
43069
- };
43943
+ this.legendVisualProvider = new LegendVisualProvider(
43944
+ bind(this.getData, this), bind(this.getRawData, this)
43945
+ );
43070
43946
 
43071
43947
  this.updateSelectedMap(this._createSelectableList());
43072
43948
 
@@ -43081,7 +43957,10 @@ var PieSeries = extendSeriesModel({
43081
43957
  },
43082
43958
 
43083
43959
  getInitialData: function (option, ecModel) {
43084
- return createListSimply(this, ['value']);
43960
+ return createListSimply(this, {
43961
+ coordDimensions: ['value'],
43962
+ encodeDefaulter: curry(makeSeriesEncodeForNameBased, this)
43963
+ });
43085
43964
  },
43086
43965
 
43087
43966
  _createSelectableList: function () {
@@ -43170,12 +44049,28 @@ var PieSeries = extendSeriesModel({
43170
44049
 
43171
44050
  // cursor: null,
43172
44051
 
44052
+ left: 0,
44053
+ top: 0,
44054
+ right: 0,
44055
+ bottom: 0,
44056
+ width: null,
44057
+ height: null,
44058
+
43173
44059
  label: {
43174
44060
  // If rotate around circle
43175
44061
  rotate: false,
43176
44062
  show: true,
43177
44063
  // 'outer', 'inside', 'center'
43178
- position: 'outer'
44064
+ position: 'outer',
44065
+ // 'none', 'labelLine', 'edge'. Works only when position is 'outer'
44066
+ alignTo: 'none',
44067
+ // Closest distance between label and chart edge.
44068
+ // Works only position is 'outer' and alignTo is 'edge'.
44069
+ margin: '25%',
44070
+ // Works only position is 'outer' and alignTo is not 'edge'.
44071
+ bleedMargin: 10,
44072
+ // Distance between text and label line.
44073
+ distanceToLabelLine: 5
43179
44074
  // formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调
43180
44075
  // 默认使用全局文本样式,详见TEXTSTYLE
43181
44076
  // distance: 当position为inner时有效,为label位置到圆心的距离与圆半径(环状图为内外半径和)的比例系数
@@ -43481,7 +44376,7 @@ piePieceProto._updateLabel = function (data, idx, withAnimation) {
43481
44376
  {
43482
44377
  labelFetcher: data.hostModel,
43483
44378
  labelDataIndex: idx,
43484
- defaultText: data.getName(idx),
44379
+ defaultText: labelLayout.text,
43485
44380
  autoColor: visualColor,
43486
44381
  useInsideStyle: !!labelLayout.inside
43487
44382
  },
@@ -43777,33 +44672,20 @@ var dataColor = function (seriesType) {
43777
44672
  dataAll.getName(rawIdx) || (rawIdx + ''), seriesModel.__paletteScope,
43778
44673
  dataAll.count()
43779
44674
  );
43780
- // Legend may use the visual info in data before processed
43781
- dataAll.setItemVisual(rawIdx, 'color', color);
43782
-
43783
44675
  // Data is not filtered
43784
44676
  if (filteredIdx != null) {
43785
44677
  data.setItemVisual(filteredIdx, 'color', color);
43786
44678
  }
43787
44679
  }
43788
- else {
43789
- // Set data all color for legend
43790
- dataAll.setItemVisual(rawIdx, 'color', singleDataColor);
43791
- }
43792
44680
 
43793
44681
  if (!singleDataBorderColor) {
43794
44682
  var borderColor = itemModel.get('itemStyle.borderColor');
43795
- // Legend may use the visual info in data before processed
43796
- dataAll.setItemVisual(rawIdx, 'borderColor', borderColor);
43797
44683
 
43798
44684
  // Data is not filtered
43799
44685
  if (filteredIdx != null) {
43800
44686
  data.setItemVisual(filteredIdx, 'borderColor', borderColor);
43801
44687
  }
43802
44688
  }
43803
- else {
43804
- // Set data all borderColor for legend
43805
- dataAll.setItemVisual(rawIdx, 'borderColor', singleDataBorderColor);
43806
- }
43807
44689
  });
43808
44690
  }
43809
44691
  };
@@ -43832,13 +44714,17 @@ var dataColor = function (seriesType) {
43832
44714
 
43833
44715
  var RADIAN$1 = Math.PI / 180;
43834
44716
 
43835
- function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight) {
44717
+ function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight, viewLeft, viewTop, farthestX) {
43836
44718
  list.sort(function (a, b) {
43837
44719
  return a.y - b.y;
43838
44720
  });
43839
44721
 
43840
44722
  function shiftDown(start, end, delta, dir) {
43841
44723
  for (var j = start; j < end; j++) {
44724
+ if (list[j].y + delta > viewTop + viewHeight) {
44725
+ break;
44726
+ }
44727
+
43842
44728
  list[j].y += delta;
43843
44729
  if (j > start
43844
44730
  && j + 1 < end
@@ -43854,6 +44740,10 @@ function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight) {
43854
44740
 
43855
44741
  function shiftUp(end, delta) {
43856
44742
  for (var j = end; j >= 0; j--) {
44743
+ if (list[j].y - delta < viewTop) {
44744
+ break;
44745
+ }
44746
+
43857
44747
  list[j].y -= delta;
43858
44748
  if (j > 0
43859
44749
  && list[j].y > list[j - 1].y + list[j - 1].height
@@ -43873,6 +44763,10 @@ function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight) {
43873
44763
  : 0; // up
43874
44764
 
43875
44765
  for (var i = 0, l = list.length; i < l; i++) {
44766
+ if (list[i].labelAlignTo !== 'none') {
44767
+ continue;
44768
+ }
44769
+
43876
44770
  var deltaY = Math.abs(list[i].y - cy);
43877
44771
  var length = list[i].len;
43878
44772
  var length2 = list[i].len2;
@@ -43902,6 +44796,12 @@ function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight) {
43902
44796
  var upList = [];
43903
44797
  var downList = [];
43904
44798
  for (var i = 0; i < len; i++) {
44799
+ if (list[i].position === 'outer' && list[i].labelAlignTo === 'labelLine') {
44800
+ var dx = list[i].x - farthestX;
44801
+ list[i].linePoints[1][0] += dx;
44802
+ list[i].x = farthestX;
44803
+ }
44804
+
43905
44805
  delta = list[i].y - lastY;
43906
44806
  if (delta < 0) {
43907
44807
  shiftDown(i, len, -delta, dir);
@@ -43923,39 +44823,85 @@ function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight) {
43923
44823
  changeX(downList, true, cx, cy, r, dir);
43924
44824
  }
43925
44825
 
43926
- function avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight) {
44826
+ function avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight, viewLeft, viewTop) {
43927
44827
  var leftList = [];
43928
44828
  var rightList = [];
44829
+ var leftmostX = Number.MAX_VALUE;
44830
+ var rightmostX = -Number.MAX_VALUE;
43929
44831
  for (var i = 0; i < labelLayoutList.length; i++) {
43930
44832
  if (isPositionCenter(labelLayoutList[i])) {
43931
44833
  continue;
43932
44834
  }
43933
44835
  if (labelLayoutList[i].x < cx) {
44836
+ leftmostX = Math.min(leftmostX, labelLayoutList[i].x);
43934
44837
  leftList.push(labelLayoutList[i]);
43935
44838
  }
43936
44839
  else {
44840
+ rightmostX = Math.max(rightmostX, labelLayoutList[i].x);
43937
44841
  rightList.push(labelLayoutList[i]);
43938
44842
  }
43939
44843
  }
43940
44844
 
43941
- adjustSingleSide(rightList, cx, cy, r, 1, viewWidth, viewHeight);
43942
- adjustSingleSide(leftList, cx, cy, r, -1, viewWidth, viewHeight);
44845
+ adjustSingleSide(rightList, cx, cy, r, 1, viewWidth, viewHeight, viewLeft, viewTop, rightmostX);
44846
+ adjustSingleSide(leftList, cx, cy, r, -1, viewWidth, viewHeight, viewLeft, viewTop, leftmostX);
43943
44847
 
43944
44848
  for (var i = 0; i < labelLayoutList.length; i++) {
43945
- if (isPositionCenter(labelLayoutList[i])) {
44849
+ var layout = labelLayoutList[i];
44850
+ if (isPositionCenter(layout)) {
43946
44851
  continue;
43947
44852
  }
43948
- var linePoints = labelLayoutList[i].linePoints;
44853
+
44854
+ var linePoints = layout.linePoints;
43949
44855
  if (linePoints) {
44856
+ var isAlignToEdge = layout.labelAlignTo === 'edge';
44857
+
44858
+ var realTextWidth = layout.textRect.width;
44859
+ var targetTextWidth;
44860
+ if (isAlignToEdge) {
44861
+ if (layout.x < cx) {
44862
+ targetTextWidth = linePoints[2][0] - layout.labelDistance
44863
+ - viewLeft - layout.labelMargin;
44864
+ }
44865
+ else {
44866
+ targetTextWidth = viewLeft + viewWidth - layout.labelMargin
44867
+ - linePoints[2][0] - layout.labelDistance;
44868
+ }
44869
+ }
44870
+ else {
44871
+ if (layout.x < cx) {
44872
+ targetTextWidth = layout.x - viewLeft - layout.bleedMargin;
44873
+ }
44874
+ else {
44875
+ targetTextWidth = viewLeft + viewWidth - layout.x - layout.bleedMargin;
44876
+ }
44877
+ }
44878
+ if (targetTextWidth < layout.textRect.width) {
44879
+ layout.text = truncateText(layout.text, targetTextWidth, layout.font);
44880
+ if (layout.labelAlignTo === 'edge') {
44881
+ realTextWidth = getWidth(layout.text, layout.font);
44882
+ }
44883
+ }
44884
+
43950
44885
  var dist = linePoints[1][0] - linePoints[2][0];
43951
- if (labelLayoutList[i].x < cx) {
43952
- linePoints[2][0] = labelLayoutList[i].x + 3;
44886
+ if (isAlignToEdge) {
44887
+ if (layout.x < cx) {
44888
+ linePoints[2][0] = viewLeft + layout.labelMargin + realTextWidth + layout.labelDistance;
44889
+ }
44890
+ else {
44891
+ linePoints[2][0] = viewLeft + viewWidth - layout.labelMargin
44892
+ - realTextWidth - layout.labelDistance;
44893
+ }
43953
44894
  }
43954
44895
  else {
43955
- linePoints[2][0] = labelLayoutList[i].x - 3;
44896
+ if (layout.x < cx) {
44897
+ linePoints[2][0] = layout.x + layout.labelDistance;
44898
+ }
44899
+ else {
44900
+ linePoints[2][0] = layout.x - layout.labelDistance;
44901
+ }
44902
+ linePoints[1][0] = linePoints[2][0] + dist;
43956
44903
  }
43957
- linePoints[1][1] = linePoints[2][1] = labelLayoutList[i].y;
43958
- linePoints[1][0] = linePoints[2][0] + dist;
44904
+ linePoints[1][1] = linePoints[2][1] = layout.y;
43959
44905
  }
43960
44906
  }
43961
44907
  }
@@ -43965,7 +44911,7 @@ function isPositionCenter(layout) {
43965
44911
  return layout.position === 'center';
43966
44912
  }
43967
44913
 
43968
- var labelLayout = function (seriesModel, r, viewWidth, viewHeight, sum) {
44914
+ var labelLayout = function (seriesModel, r, viewWidth, viewHeight, viewLeft, viewTop) {
43969
44915
  var data = seriesModel.getData();
43970
44916
  var labelLayoutList = [];
43971
44917
  var cx;
@@ -43980,10 +44926,17 @@ var labelLayout = function (seriesModel, r, viewWidth, viewHeight, sum) {
43980
44926
  var labelModel = itemModel.getModel('label');
43981
44927
  // Use position in normal or emphasis
43982
44928
  var labelPosition = labelModel.get('position') || itemModel.get('emphasis.label.position');
44929
+ var labelDistance = labelModel.get('distanceToLabelLine');
44930
+ var labelAlignTo = labelModel.get('alignTo');
44931
+ var labelMargin = parsePercent$1(labelModel.get('margin'), viewWidth);
44932
+ var bleedMargin = labelModel.get('bleedMargin');
44933
+ var font = labelModel.getFont();
43983
44934
 
43984
44935
  var labelLineModel = itemModel.getModel('labelLine');
43985
44936
  var labelLineLen = labelLineModel.get('length');
44937
+ labelLineLen = parsePercent$1(labelLineLen, viewWidth);
43986
44938
  var labelLineLen2 = labelLineModel.get('length2');
44939
+ labelLineLen2 = parsePercent$1(labelLineLen2, viewWidth);
43987
44940
 
43988
44941
  if (layout.angle < minShowLabelRadian) {
43989
44942
  return;
@@ -44001,6 +44954,12 @@ var labelLayout = function (seriesModel, r, viewWidth, viewHeight, sum) {
44001
44954
  cx = layout.cx;
44002
44955
  cy = layout.cy;
44003
44956
 
44957
+ var text = seriesModel.getFormattedLabel(idx, 'normal')
44958
+ || data.getName(idx);
44959
+ var textRect = getBoundingRect(
44960
+ text, font, textAlign, 'top'
44961
+ );
44962
+
44004
44963
  var isLabelInside = labelPosition === 'inside' || labelPosition === 'inner';
44005
44964
  if (labelPosition === 'center') {
44006
44965
  textX = layout.cx;
@@ -44021,14 +44980,25 @@ var labelLayout = function (seriesModel, r, viewWidth, viewHeight, sum) {
44021
44980
  var x3 = x2 + ((dx < 0 ? -1 : 1) * labelLineLen2);
44022
44981
  var y3 = y2;
44023
44982
 
44024
- textX = x3 + (dx < 0 ? -5 : 5);
44983
+ if (labelAlignTo === 'edge') {
44984
+ // Adjust textX because text align of edge is opposite
44985
+ textX = dx < 0
44986
+ ? viewLeft + labelMargin
44987
+ : viewLeft + viewWidth - labelMargin;
44988
+ }
44989
+ else {
44990
+ textX = x3 + (dx < 0 ? -labelDistance : labelDistance);
44991
+ }
44025
44992
  textY = y3;
44026
44993
  linePoints = [[x1, y1], [x2, y2], [x3, y3]];
44027
44994
  }
44028
44995
 
44029
- textAlign = isLabelInside ? 'center' : (dx > 0 ? 'left' : 'right');
44996
+ textAlign = isLabelInside
44997
+ ? 'center'
44998
+ : (labelAlignTo === 'edge'
44999
+ ? (dx > 0 ? 'right' : 'left')
45000
+ : (dx > 0 ? 'left' : 'right'));
44030
45001
  }
44031
- var font = labelModel.getFont();
44032
45002
 
44033
45003
  var labelRotate;
44034
45004
  var rotate = labelModel.get('rotate');
@@ -44040,11 +45010,7 @@ var labelLayout = function (seriesModel, r, viewWidth, viewHeight, sum) {
44040
45010
  ? (dx < 0 ? -midAngle + Math.PI : -midAngle)
44041
45011
  : 0;
44042
45012
  }
44043
- var text = seriesModel.getFormattedLabel(idx, 'normal')
44044
- || data.getName(idx);
44045
- var textRect = getBoundingRect(
44046
- text, font, textAlign, 'top'
44047
- );
45013
+
44048
45014
  hasLabelRotate = !!labelRotate;
44049
45015
  layout.label = {
44050
45016
  x: textX,
@@ -44057,7 +45023,14 @@ var labelLayout = function (seriesModel, r, viewWidth, viewHeight, sum) {
44057
45023
  textAlign: textAlign,
44058
45024
  verticalAlign: 'middle',
44059
45025
  rotation: labelRotate,
44060
- inside: isLabelInside
45026
+ inside: isLabelInside,
45027
+ labelDistance: labelDistance,
45028
+ labelAlignTo: labelAlignTo,
45029
+ labelMargin:labelMargin,
45030
+ bleedMargin: bleedMargin,
45031
+ textRect: textRect,
45032
+ text: text,
45033
+ font: font
44061
45034
  };
44062
45035
 
44063
45036
  // Not layout the inside label
@@ -44066,7 +45039,7 @@ var labelLayout = function (seriesModel, r, viewWidth, viewHeight, sum) {
44066
45039
  }
44067
45040
  });
44068
45041
  if (!hasLabelRotate && seriesModel.get('avoidLabelOverlap')) {
44069
- avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight);
45042
+ avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight, viewLeft, viewTop);
44070
45043
  }
44071
45044
  };
44072
45045
 
@@ -44093,10 +45066,20 @@ var labelLayout = function (seriesModel, r, viewWidth, viewHeight, sum) {
44093
45066
  var PI2$4 = Math.PI * 2;
44094
45067
  var RADIAN = Math.PI / 180;
44095
45068
 
45069
+ function getViewRect(seriesModel, api) {
45070
+ return getLayoutRect(
45071
+ seriesModel.getBoxLayoutParams(), {
45072
+ width: api.getWidth(),
45073
+ height: api.getHeight()
45074
+ }
45075
+ );
45076
+ }
45077
+
44096
45078
  var pieLayout = function (seriesType, ecModel, api, payload) {
44097
45079
  ecModel.eachSeriesByType(seriesType, function (seriesModel) {
44098
45080
  var data = seriesModel.getData();
44099
45081
  var valueDim = data.mapDimension('value');
45082
+ var viewRect = getViewRect(seriesModel, api);
44100
45083
 
44101
45084
  var center = seriesModel.get('center');
44102
45085
  var radius = seriesModel.get('radius');
@@ -44108,11 +45091,11 @@ var pieLayout = function (seriesType, ecModel, api, payload) {
44108
45091
  center = [center, center];
44109
45092
  }
44110
45093
 
44111
- var width = api.getWidth();
44112
- var height = api.getHeight();
45094
+ var width = parsePercent$1(viewRect.width, api.getWidth());
45095
+ var height = parsePercent$1(viewRect.height, api.getHeight());
44113
45096
  var size = Math.min(width, height);
44114
- var cx = parsePercent$1(center[0], width);
44115
- var cy = parsePercent$1(center[1], height);
45097
+ var cx = parsePercent$1(center[0], width) + viewRect.x;
45098
+ var cy = parsePercent$1(center[1], height) + viewRect.y;
44116
45099
  var r0 = parsePercent$1(radius[0], size / 2);
44117
45100
  var r = parsePercent$1(radius[1], size / 2);
44118
45101
 
@@ -44158,7 +45141,8 @@ var pieLayout = function (seriesType, ecModel, api, payload) {
44158
45141
  r0: r0,
44159
45142
  r: roseType
44160
45143
  ? NaN
44161
- : r
45144
+ : r,
45145
+ viewRect: viewRect
44162
45146
  });
44163
45147
  return;
44164
45148
  }
@@ -44191,7 +45175,8 @@ var pieLayout = function (seriesType, ecModel, api, payload) {
44191
45175
  r0: r0,
44192
45176
  r: roseType
44193
45177
  ? linearMap(value, extent, [r0, r])
44194
- : r
45178
+ : r,
45179
+ viewRect: viewRect
44195
45180
  });
44196
45181
 
44197
45182
  currentAngle = endAngle;
@@ -44229,7 +45214,7 @@ var pieLayout = function (seriesType, ecModel, api, payload) {
44229
45214
  }
44230
45215
  }
44231
45216
 
44232
- labelLayout(seriesModel, r, width, height);
45217
+ labelLayout(seriesModel, r, viewRect.width, viewRect.height, viewRect.x, viewRect.y);
44233
45218
  });
44234
45219
  };
44235
45220
 
@@ -44340,7 +45325,7 @@ SeriesModel.extend({
44340
45325
  dependencies: ['grid', 'polar', 'geo', 'singleAxis', 'calendar'],
44341
45326
 
44342
45327
  getInitialData: function (option, ecModel) {
44343
- return createListFromArray(this.getSource(), this);
45328
+ return createListFromArray(this.getSource(), this, {useEncodeDefaulter: true});
44344
45329
  },
44345
45330
 
44346
45331
  brushSelector: 'point',
@@ -48760,9 +49745,9 @@ var LegendModel = extendComponentModel({
48760
49745
  availableNames.push(seriesName);
48761
49746
  var isPotential;
48762
49747
 
48763
- if (seriesModel.legendDataProvider) {
48764
- var data = seriesModel.legendDataProvider();
48765
- var names = data.mapArray(data.getName);
49748
+ if (seriesModel.legendVisualProvider) {
49749
+ var provider = seriesModel.legendVisualProvider;
49750
+ var names = provider.getAllNames();
48766
49751
 
48767
49752
  if (!ecModel.isSeriesFiltered(seriesModel)) {
48768
49753
  availableNames = availableNames.concat(names);
@@ -49351,7 +50336,7 @@ var LegendView = extendComponentView({
49351
50336
  return;
49352
50337
  }
49353
50338
 
49354
- // Series legend
50339
+ // Legend to control series.
49355
50340
  if (seriesModel) {
49356
50341
  var data = seriesModel.getData();
49357
50342
  var color = data.getVisual('color');
@@ -49380,29 +50365,31 @@ var LegendView = extendComponentView({
49380
50365
  selectMode
49381
50366
  );
49382
50367
 
49383
- itemGroup.on('click', curry$3(dispatchSelectAction, name, api))
50368
+ itemGroup.on('click', curry$3(dispatchSelectAction, name, null, api, excludeSeriesId))
49384
50369
  .on('mouseover', curry$3(dispatchHighlightAction, seriesModel.name, null, api, excludeSeriesId))
49385
50370
  .on('mouseout', curry$3(dispatchDownplayAction, seriesModel.name, null, api, excludeSeriesId));
49386
50371
 
49387
50372
  legendDrawnMap.set(name, true);
49388
50373
  }
49389
50374
  else {
49390
- // Data legend of pie, funnel
50375
+ // Legend to control data. In pie and funnel.
49391
50376
  ecModel.eachRawSeries(function (seriesModel) {
50377
+
49392
50378
  // In case multiple series has same data name
49393
50379
  if (legendDrawnMap.get(name)) {
49394
50380
  return;
49395
50381
  }
49396
50382
 
49397
- if (seriesModel.legendDataProvider) {
49398
- var data = seriesModel.legendDataProvider();
49399
- var idx = data.indexOfName(name);
49400
- if (idx < 0) {
50383
+ if (seriesModel.legendVisualProvider) {
50384
+ var provider = seriesModel.legendVisualProvider;
50385
+ if (!provider.containName(name)) {
49401
50386
  return;
49402
50387
  }
49403
50388
 
49404
- var color = data.getItemVisual(idx, 'color');
49405
- var borderColor = data.getItemVisual(idx, 'borderColor');
50389
+ var idx = provider.indexOfName(name);
50390
+
50391
+ var color = provider.getItemVisual(idx, 'color');
50392
+ var borderColor = provider.getItemVisual(idx, 'borderColor');
49406
50393
 
49407
50394
  var legendSymbolType = 'roundRect';
49408
50395
 
@@ -49414,7 +50401,7 @@ var LegendView = extendComponentView({
49414
50401
  );
49415
50402
 
49416
50403
  // FIXME: consider different series has items with the same name.
49417
- itemGroup.on('click', curry$3(dispatchSelectAction, name, api))
50404
+ itemGroup.on('click', curry$3(dispatchSelectAction, null, name, api, excludeSeriesId))
49418
50405
  // Should not specify the series name, consider legend controls
49419
50406
  // more than one pie series.
49420
50407
  .on('mouseover', curry$3(dispatchHighlightAction, null, name, api, excludeSeriesId))
@@ -49694,11 +50681,15 @@ function setSymbolStyle(symbol, symbolType, legendModelItemStyle, borderColor, i
49694
50681
  return symbol.setStyle(itemStyle);
49695
50682
  }
49696
50683
 
49697
- function dispatchSelectAction(name, api) {
50684
+ function dispatchSelectAction(seriesName, dataName, api, excludeSeriesId) {
50685
+ // downplay before unselect
50686
+ dispatchDownplayAction(seriesName, dataName, api, excludeSeriesId);
49698
50687
  api.dispatchAction({
49699
50688
  type: 'legendToggleSelect',
49700
- name: name
50689
+ name: seriesName != null ? seriesName : dataName
49701
50690
  });
50691
+ // highlight after select
50692
+ dispatchHighlightAction(seriesName, dataName, api, excludeSeriesId);
49702
50693
  }
49703
50694
 
49704
50695
  function dispatchHighlightAction(seriesName, dataName, api, excludeSeriesId) {
@@ -54941,10 +55932,6 @@ var SliderZoomView = DataZoomView.extend({
54941
55932
  draggable: true,
54942
55933
  cursor: getCursor(this._orient),
54943
55934
  drift: bind$3(this._onDragMove, this, 'all'),
54944
- onmousemove: function (e) {
54945
- // Fot mobile devicem, prevent screen slider on the button.
54946
- stop(e.event);
54947
- },
54948
55935
  ondragstart: bind$3(this._showDataInfo, this, true),
54949
55936
  ondragend: bind$3(this._onDragEnd, this),
54950
55937
  onmouseover: bind$3(this._showDataInfo, this, true),
@@ -54980,10 +55967,6 @@ var SliderZoomView = DataZoomView.extend({
54980
55967
  cursor: getCursor(this._orient),
54981
55968
  draggable: true,
54982
55969
  drift: bind$3(this._onDragMove, this, handleIndex),
54983
- onmousemove: function (e) {
54984
- // Fot mobile devicem, prevent screen slider on the button.
54985
- stop(e.event);
54986
- },
54987
55970
  ondragend: bind$3(this._onDragEnd, this),
54988
55971
  onmouseover: bind$3(this._showDataInfo, this, true),
54989
55972
  onmouseout: bind$3(this._showDataInfo, this, false)
@@ -55205,9 +56188,12 @@ var SliderZoomView = DataZoomView.extend({
55205
56188
  handleLabels[1].attr('invisible', !showOrHide);
55206
56189
  },
55207
56190
 
55208
- _onDragMove: function (handleIndex, dx, dy) {
56191
+ _onDragMove: function (handleIndex, dx, dy, event) {
55209
56192
  this._dragging = true;
55210
56193
 
56194
+ // For mobile device, prevent screen slider on the button.
56195
+ stop(event.event);
56196
+
55211
56197
  // Transform dx, dy to bar coordination.
55212
56198
  var barTransform = this._displayables.barGroup.getLocalTransform();
55213
56199
  var vertex = applyTransform$1([dx, dy], barTransform, true);
@@ -56528,6 +57514,11 @@ extendComponentView({
56528
57514
  var featureModel = new Model(featureOpt, toolboxModel, toolboxModel.ecModel);
56529
57515
  var feature;
56530
57516
 
57517
+ // FIX#11236, merge feature title from MagicType newOption. TODO: consider seriesIndex ?
57518
+ if (payload && payload.newTitle != null) {
57519
+ featureOpt.title = payload.newTitle;
57520
+ }
57521
+
56531
57522
  if (featureName && !oldName) { // Create
56532
57523
  if (isUserFeatureName(featureName)) {
56533
57524
  feature = {
@@ -56867,6 +57858,7 @@ register$2(
56867
57858
  */
56868
57859
 
56869
57860
  var magicTypeLang = lang.toolbox.magicType;
57861
+ var INNER_STACK_KEYWORD = '__ec_magicType_stack__';
56870
57862
 
56871
57863
  function MagicType(model) {
56872
57864
  this.model = model;
@@ -56880,8 +57872,7 @@ MagicType.defaultOption = {
56880
57872
  /* eslint-disable */
56881
57873
  line: 'M4.1,28.9h7.1l9.3-22l7.4,38l9.7-19.7l3,12.8h14.9M4.1,58h51.4',
56882
57874
  bar: 'M6.7,22.9h10V48h-10V22.9zM24.9,13h10v35h-10V13zM43.2,2h10v46h-10V2zM3.1,58h53.7',
56883
- 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
56884
- tiled: 'M2.3,2.2h22.8V25H2.3V2.2z M35,2.2h22.8V25H35V2.2zM2.3,35h22.8v22.8H2.3V35z M35,35h22.8v22.8H35V35z'
57875
+ 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
56885
57876
  /* eslint-enable */
56886
57877
  },
56887
57878
  // `line`, `bar`, `stack`, `tiled`
@@ -56932,26 +57923,20 @@ var seriesOptGenreator = {
56932
57923
  }
56933
57924
  },
56934
57925
  'stack': function (seriesType, seriesId, seriesModel, model) {
57926
+ var isStack = seriesModel.get('stack') === INNER_STACK_KEYWORD;
56935
57927
  if (seriesType === 'line' || seriesType === 'bar') {
57928
+ model.setIconStatus('stack', isStack ? 'normal' : 'emphasis');
56936
57929
  return merge({
56937
57930
  id: seriesId,
56938
- stack: '__ec_magicType_stack__'
57931
+ stack: isStack ? '' : INNER_STACK_KEYWORD
56939
57932
  }, model.get('option.stack') || {}, true);
56940
57933
  }
56941
- },
56942
- 'tiled': function (seriesType, seriesId, seriesModel, model) {
56943
- if (seriesType === 'line' || seriesType === 'bar') {
56944
- return merge({
56945
- id: seriesId,
56946
- stack: ''
56947
- }, model.get('option.tiled') || {}, true);
56948
- }
56949
57934
  }
56950
57935
  };
56951
57936
 
56952
57937
  var radioTypes = [
56953
57938
  ['line', 'bar'],
56954
- ['stack', 'tiled']
57939
+ ['stack']
56955
57940
  ];
56956
57941
 
56957
57942
  proto$3.onclick = function (ecModel, api, type) {
@@ -57016,10 +58001,21 @@ proto$3.onclick = function (ecModel, api, type) {
57016
58001
  }
57017
58002
  }, generateNewSeriesTypes
57018
58003
  );
58004
+
58005
+ var newTitle;
58006
+ // Change title of stack
58007
+ if (type === 'stack') {
58008
+ var isStack = newOption.series && newOption.series[0] && newOption.series[0].stack === INNER_STACK_KEYWORD;
58009
+ newTitle = isStack
58010
+ ? merge({ stack: magicTypeLang.title.tiled }, magicTypeLang.title)
58011
+ : clone(magicTypeLang.title);
58012
+ }
58013
+
57019
58014
  api.dispatchAction({
57020
58015
  type: 'changeMagicType',
57021
58016
  currentType: type,
57022
- newOption: newOption
58017
+ newOption: newOption,
58018
+ newTitle: newTitle
57023
58019
  });
57024
58020
  };
57025
58021
 
@@ -57632,12 +58628,6 @@ function BrushController(zr) {
57632
58628
  */
57633
58629
  this._dragging;
57634
58630
 
57635
- /**
57636
- * @private
57637
- * @type {Object}
57638
- */
57639
- this._lastMouseMovePoint = {};
57640
-
57641
58631
  /**
57642
58632
  * @private
57643
58633
  * @type {Array}
@@ -57682,7 +58672,8 @@ function BrushController(zr) {
57682
58672
  * @type {Object}
57683
58673
  */
57684
58674
  this._handlers = {};
57685
- each$16(mouseHandlers, function (handler, eventName) {
58675
+
58676
+ each$16(pointerHandlers, function (handler, eventName) {
57686
58677
  this._handlers[eventName] = bind(handler, this);
57687
58678
  }, this);
57688
58679
  }
@@ -57878,9 +58869,7 @@ function doEnableBrush(controller, brushOption) {
57878
58869
  take(zr, MUTEX_RESOURCE_KEY, controller._uid);
57879
58870
  }
57880
58871
 
57881
- each$16(controller._handlers, function (handler, eventName) {
57882
- zr.on(eventName, handler);
57883
- });
58872
+ mountHandlers(zr, controller._handlers);
57884
58873
 
57885
58874
  controller._brushType = brushOption.brushType;
57886
58875
  controller._brushOption = merge(clone(DEFAULT_BRUSH_OPT), brushOption, true);
@@ -57891,13 +58880,23 @@ function doDisableBrush(controller) {
57891
58880
 
57892
58881
  release(zr, MUTEX_RESOURCE_KEY, controller._uid);
57893
58882
 
57894
- each$16(controller._handlers, function (handler, eventName) {
57895
- zr.off(eventName, handler);
57896
- });
58883
+ unmountHandlers(zr, controller._handlers);
57897
58884
 
57898
58885
  controller._brushType = controller._brushOption = null;
57899
58886
  }
57900
58887
 
58888
+ function mountHandlers(zr, handlers) {
58889
+ each$16(handlers, function (handler, eventName) {
58890
+ zr.on(eventName, handler);
58891
+ });
58892
+ }
58893
+
58894
+ function unmountHandlers(zr, handlers) {
58895
+ each$16(handlers, function (handler, eventName) {
58896
+ zr.off(eventName, handler);
58897
+ });
58898
+ }
58899
+
57901
58900
  function createCover(controller, brushOption) {
57902
58901
  var cover = coverRenderers[brushOption.brushType].createCover(controller, brushOption);
57903
58902
  cover.__brushOption = brushOption;
@@ -58211,8 +59210,14 @@ function pointsToRect(points) {
58211
59210
  }
58212
59211
 
58213
59212
  function resetCursor(controller, e, localCursorPoint) {
58214
- // Check active
58215
- if (!controller._brushType) {
59213
+ if (
59214
+ // Check active
59215
+ !controller._brushType
59216
+ // resetCursor should be always called when mouse is in zr area,
59217
+ // but not called when mouse is out of zr area to avoid bad influence
59218
+ // if `mousemove`, `mouseup` are triggered from `document` event.
59219
+ || isOutsideZrArea(controller, e)
59220
+ ) {
58216
59221
  return;
58217
59222
  }
58218
59223
 
@@ -58316,7 +59321,7 @@ function determineBrushType(brushType, panel) {
58316
59321
  return brushType;
58317
59322
  }
58318
59323
 
58319
- var mouseHandlers = {
59324
+ var pointerHandlers = {
58320
59325
 
58321
59326
  mousedown: function (e) {
58322
59327
  if (this._dragging) {
@@ -58341,56 +59346,34 @@ var mouseHandlers = {
58341
59346
  },
58342
59347
 
58343
59348
  mousemove: function (e) {
58344
- var lastPoint = this._lastMouseMovePoint;
58345
- lastPoint.x = e.offsetX;
58346
- lastPoint.y = e.offsetY;
59349
+ var x = e.offsetX;
59350
+ var y = e.offsetY;
58347
59351
 
58348
- var localCursorPoint = this.group.transformCoordToLocal(lastPoint.x, lastPoint.y);
59352
+ var localCursorPoint = this.group.transformCoordToLocal(x, y);
58349
59353
 
58350
59354
  resetCursor(this, e, localCursorPoint);
58351
59355
 
58352
59356
  if (this._dragging) {
58353
-
58354
59357
  preventDefault(e);
58355
-
58356
59358
  var eventParams = updateCoverByMouse(this, e, localCursorPoint, false);
58357
-
58358
59359
  eventParams && trigger$1(this, eventParams);
58359
59360
  }
58360
59361
  },
58361
59362
 
58362
59363
  mouseup: function (e) {
58363
59364
  handleDragEnd(this, e);
58364
- },
58365
-
58366
- globalout: function (e) {
58367
- handleDragEnd(this, e, true);
58368
59365
  }
58369
59366
  };
58370
59367
 
58371
- function handleDragEnd(controller, e, isGlobalOut) {
58372
- if (controller._dragging) {
58373
59368
 
58374
- // Just be worried about bring some side effect to the world
58375
- // out of echarts, we do not `preventDefault` for globalout.
58376
- !isGlobalOut && preventDefault(e);
59369
+ function handleDragEnd(controller, e) {
59370
+ if (controller._dragging) {
59371
+ preventDefault(e);
58377
59372
 
58378
- var pointerX = e.offsetX;
58379
- var pointerY = e.offsetY;
58380
- var lastPoint = controller._lastMouseMovePoint;
58381
- if (isGlobalOut) {
58382
- pointerX = lastPoint.x;
58383
- pointerY = lastPoint.y;
58384
- }
59373
+ var x = e.offsetX;
59374
+ var y = e.offsetY;
58385
59375
 
58386
- var localCursorPoint = controller.group.transformCoordToLocal(pointerX, pointerY);
58387
- // FIXME
58388
- // Here `e` is used only in `onIrrelevantElement` finally. And it's OK
58389
- // that pass the `e` of `globalout` to `onIrrelevantElement`. But it is
58390
- // not a good design of these interfaces. However, we do not refactor
58391
- // these code now because the implementation of `onIrrelevantElement`
58392
- // need to be discussed and probably be changed in future, becuase it
58393
- // slows down the performance of zrender in some cases.
59376
+ var localCursorPoint = controller.group.transformCoordToLocal(x, y);
58394
59377
  var eventParams = updateCoverByMouse(controller, e, localCursorPoint, true);
58395
59378
 
58396
59379
  controller._dragging = false;
@@ -58402,6 +59385,12 @@ function handleDragEnd(controller, e, isGlobalOut) {
58402
59385
  }
58403
59386
  }
58404
59387
 
59388
+ function isOutsideZrArea(controller, x, y) {
59389
+ var zr = controller._zr;
59390
+ return x < 0 || x > zr.getWidth() || y < 0 || y > zr.getHeight();
59391
+ }
59392
+
59393
+
58405
59394
  /**
58406
59395
  * key: brushType
58407
59396
  * @type {Object}
@@ -61178,6 +62167,9 @@ svgPath.brush = function (el) {
61178
62167
  if (style.text != null) {
61179
62168
  svgTextDrawRectText(el, el.getBoundingRect());
61180
62169
  }
62170
+ else {
62171
+ removeOldTextNode(el);
62172
+ }
61181
62173
  };
61182
62174
 
61183
62175
  /***************************************************
@@ -61225,6 +62217,9 @@ svgImage.brush = function (el) {
61225
62217
  if (style.text != null) {
61226
62218
  svgTextDrawRectText(el, el.getBoundingRect());
61227
62219
  }
62220
+ else {
62221
+ removeOldTextNode(el);
62222
+ }
61228
62223
  };
61229
62224
 
61230
62225
  /***************************************************
@@ -61425,6 +62420,18 @@ function updateTextLocation(tspan, textAlign, x, y) {
61425
62420
  attr(tspan, 'y', y);
61426
62421
  }
61427
62422
 
62423
+ function removeOldTextNode(el) {
62424
+ if (el && el.__textSvgEl) {
62425
+ // textSvgEl may has no parentNode if el has been removed temporary.
62426
+ if (el.__textSvgEl.parentNode) {
62427
+ el.__textSvgEl.parentNode.removeChild(el.__textSvgEl);
62428
+ }
62429
+ el.__textSvgEl = null;
62430
+ el.__tspanList = [];
62431
+ el.__text = null;
62432
+ }
62433
+ }
62434
+
61428
62435
  svgText.drawRectText = svgTextDrawRectText;
61429
62436
 
61430
62437
  svgText.brush = function (el) {
@@ -61432,6 +62439,9 @@ svgText.brush = function (el) {
61432
62439
  if (style.text != null) {
61433
62440
  svgTextDrawRectText(el, false);
61434
62441
  }
62442
+ else {
62443
+ removeOldTextNode(el);
62444
+ }
61435
62445
  };
61436
62446
 
61437
62447
  // Myers' Diff Algorithm
@@ -62686,8 +63696,8 @@ SVGPainter.prototype = {
62686
63696
  else if (!item.removed) {
62687
63697
  for (var k = 0; k < item.count; k++) {
62688
63698
  var displayable = newVisibleList[item.indices[k]];
62689
- prevSvgElement = getTextSvgElement(displayable)
62690
- || getSvgElement(displayable) || prevSvgElement;
63699
+ var svgElement = getSvgElement(displayable);
63700
+ var textSvgElement = getTextSvgElement(displayable);
62691
63701
 
62692
63702
  var svgElement = getSvgElement(displayable);
62693
63703
  var textSvgElement = getTextSvgElement(displayable);
@@ -62701,6 +63711,12 @@ SVGPainter.prototype = {
62701
63711
  .addWithoutUpdate(svgElement || textSvgElement, displayable);
62702
63712
 
62703
63713
  this.clipPathManager.markUsed(displayable);
63714
+
63715
+ if (textSvgElement) { // Insert text.
63716
+ insertAfter(svgRoot, textSvgElement, svgElement);
63717
+ }
63718
+ prevSvgElement = svgElement
63719
+ || textSvgElement || prevSvgElement;
62704
63720
  }
62705
63721
  }
62706
63722
  }