Symbol.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. var zrUtil = require("zrender/lib/core/util");
  2. var _symbol = require("../../util/symbol");
  3. var createSymbol = _symbol.createSymbol;
  4. var graphic = require("../../util/graphic");
  5. var _number = require("../../util/number");
  6. var parsePercent = _number.parsePercent;
  7. var _labelHelper = require("./labelHelper");
  8. var findLabelValueDim = _labelHelper.findLabelValueDim;
  9. /**
  10. * @module echarts/chart/helper/Symbol
  11. */
  12. function getSymbolSize(data, idx) {
  13. var symbolSize = data.getItemVisual(idx, 'symbolSize');
  14. return symbolSize instanceof Array ? symbolSize.slice() : [+symbolSize, +symbolSize];
  15. }
  16. function getScale(symbolSize) {
  17. return [symbolSize[0] / 2, symbolSize[1] / 2];
  18. }
  19. /**
  20. * @constructor
  21. * @alias {module:echarts/chart/helper/Symbol}
  22. * @param {module:echarts/data/List} data
  23. * @param {number} idx
  24. * @extends {module:zrender/graphic/Group}
  25. */
  26. function SymbolClz(data, idx, seriesScope) {
  27. graphic.Group.call(this);
  28. this.updateData(data, idx, seriesScope);
  29. }
  30. var symbolProto = SymbolClz.prototype;
  31. function driftSymbol(dx, dy) {
  32. this.parent.drift(dx, dy);
  33. }
  34. symbolProto._createSymbol = function (symbolType, data, idx, symbolSize) {
  35. // Remove paths created before
  36. this.removeAll();
  37. var color = data.getItemVisual(idx, 'color'); // var symbolPath = createSymbol(
  38. // symbolType, -0.5, -0.5, 1, 1, color
  39. // );
  40. // If width/height are set too small (e.g., set to 1) on ios10
  41. // and macOS Sierra, a circle stroke become a rect, no matter what
  42. // the scale is set. So we set width/height as 2. See #4150.
  43. var symbolPath = createSymbol(symbolType, -1, -1, 2, 2, color);
  44. symbolPath.attr({
  45. z2: 100,
  46. culling: true,
  47. scale: getScale(symbolSize)
  48. }); // Rewrite drift method
  49. symbolPath.drift = driftSymbol;
  50. this._symbolType = symbolType;
  51. this.add(symbolPath);
  52. };
  53. /**
  54. * Stop animation
  55. * @param {boolean} toLastFrame
  56. */
  57. symbolProto.stopSymbolAnimation = function (toLastFrame) {
  58. this.childAt(0).stopAnimation(toLastFrame);
  59. };
  60. /**
  61. * FIXME:
  62. * Caution: This method breaks the encapsulation of this module,
  63. * but it indeed brings convenience. So do not use the method
  64. * unless you detailedly know all the implements of `Symbol`,
  65. * especially animation.
  66. *
  67. * Get symbol path element.
  68. */
  69. symbolProto.getSymbolPath = function () {
  70. return this.childAt(0);
  71. };
  72. /**
  73. * Get scale(aka, current symbol size).
  74. * Including the change caused by animation
  75. */
  76. symbolProto.getScale = function () {
  77. return this.childAt(0).scale;
  78. };
  79. /**
  80. * Highlight symbol
  81. */
  82. symbolProto.highlight = function () {
  83. this.childAt(0).trigger('emphasis');
  84. };
  85. /**
  86. * Downplay symbol
  87. */
  88. symbolProto.downplay = function () {
  89. this.childAt(0).trigger('normal');
  90. };
  91. /**
  92. * @param {number} zlevel
  93. * @param {number} z
  94. */
  95. symbolProto.setZ = function (zlevel, z) {
  96. var symbolPath = this.childAt(0);
  97. symbolPath.zlevel = zlevel;
  98. symbolPath.z = z;
  99. };
  100. symbolProto.setDraggable = function (draggable) {
  101. var symbolPath = this.childAt(0);
  102. symbolPath.draggable = draggable;
  103. symbolPath.cursor = draggable ? 'move' : 'pointer';
  104. };
  105. /**
  106. * Update symbol properties
  107. * @param {module:echarts/data/List} data
  108. * @param {number} idx
  109. * @param {Object} [seriesScope]
  110. * @param {Object} [seriesScope.itemStyle]
  111. * @param {Object} [seriesScope.hoverItemStyle]
  112. * @param {Object} [seriesScope.symbolRotate]
  113. * @param {Object} [seriesScope.symbolOffset]
  114. * @param {module:echarts/model/Model} [seriesScope.labelModel]
  115. * @param {module:echarts/model/Model} [seriesScope.hoverLabelModel]
  116. * @param {boolean} [seriesScope.hoverAnimation]
  117. * @param {Object} [seriesScope.cursorStyle]
  118. * @param {module:echarts/model/Model} [seriesScope.itemModel]
  119. * @param {string} [seriesScope.symbolInnerColor]
  120. * @param {Object} [seriesScope.fadeIn=false]
  121. */
  122. symbolProto.updateData = function (data, idx, seriesScope) {
  123. this.silent = false;
  124. var symbolType = data.getItemVisual(idx, 'symbol') || 'circle';
  125. var seriesModel = data.hostModel;
  126. var symbolSize = getSymbolSize(data, idx);
  127. var isInit = symbolType !== this._symbolType;
  128. if (isInit) {
  129. this._createSymbol(symbolType, data, idx, symbolSize);
  130. } else {
  131. var symbolPath = this.childAt(0);
  132. symbolPath.silent = false;
  133. graphic.updateProps(symbolPath, {
  134. scale: getScale(symbolSize)
  135. }, seriesModel, idx);
  136. }
  137. this._updateCommon(data, idx, symbolSize, seriesScope);
  138. if (isInit) {
  139. var symbolPath = this.childAt(0);
  140. var fadeIn = seriesScope && seriesScope.fadeIn;
  141. var target = {
  142. scale: symbolPath.scale.slice()
  143. };
  144. fadeIn && (target.style = {
  145. opacity: symbolPath.style.opacity
  146. });
  147. symbolPath.scale = [0, 0];
  148. fadeIn && (symbolPath.style.opacity = 0);
  149. graphic.initProps(symbolPath, target, seriesModel, idx);
  150. }
  151. this._seriesModel = seriesModel;
  152. }; // Update common properties
  153. var normalStyleAccessPath = ['itemStyle', 'normal'];
  154. var emphasisStyleAccessPath = ['itemStyle', 'emphasis'];
  155. var normalLabelAccessPath = ['label', 'normal'];
  156. var emphasisLabelAccessPath = ['label', 'emphasis'];
  157. /**
  158. * @param {module:echarts/data/List} data
  159. * @param {number} idx
  160. * @param {Array.<number>} symbolSize
  161. * @param {Object} [seriesScope]
  162. */
  163. symbolProto._updateCommon = function (data, idx, symbolSize, seriesScope) {
  164. var symbolPath = this.childAt(0);
  165. var seriesModel = data.hostModel;
  166. var color = data.getItemVisual(idx, 'color'); // Reset style
  167. if (symbolPath.type !== 'image') {
  168. symbolPath.useStyle({
  169. strokeNoScale: true
  170. });
  171. }
  172. var itemStyle = seriesScope && seriesScope.itemStyle;
  173. var hoverItemStyle = seriesScope && seriesScope.hoverItemStyle;
  174. var symbolRotate = seriesScope && seriesScope.symbolRotate;
  175. var symbolOffset = seriesScope && seriesScope.symbolOffset;
  176. var labelModel = seriesScope && seriesScope.labelModel;
  177. var hoverLabelModel = seriesScope && seriesScope.hoverLabelModel;
  178. var hoverAnimation = seriesScope && seriesScope.hoverAnimation;
  179. var cursorStyle = seriesScope && seriesScope.cursorStyle;
  180. if (!seriesScope || data.hasItemOption) {
  181. var itemModel = seriesScope && seriesScope.itemModel ? seriesScope.itemModel : data.getItemModel(idx); // Color must be excluded.
  182. // Because symbol provide setColor individually to set fill and stroke
  183. itemStyle = itemModel.getModel(normalStyleAccessPath).getItemStyle(['color']);
  184. hoverItemStyle = itemModel.getModel(emphasisStyleAccessPath).getItemStyle();
  185. symbolRotate = itemModel.getShallow('symbolRotate');
  186. symbolOffset = itemModel.getShallow('symbolOffset');
  187. labelModel = itemModel.getModel(normalLabelAccessPath);
  188. hoverLabelModel = itemModel.getModel(emphasisLabelAccessPath);
  189. hoverAnimation = itemModel.getShallow('hoverAnimation');
  190. cursorStyle = itemModel.getShallow('cursor');
  191. } else {
  192. hoverItemStyle = zrUtil.extend({}, hoverItemStyle);
  193. }
  194. var elStyle = symbolPath.style;
  195. symbolPath.attr('rotation', (symbolRotate || 0) * Math.PI / 180 || 0);
  196. if (symbolOffset) {
  197. symbolPath.attr('position', [parsePercent(symbolOffset[0], symbolSize[0]), parsePercent(symbolOffset[1], symbolSize[1])]);
  198. }
  199. cursorStyle && symbolPath.attr('cursor', cursorStyle); // PENDING setColor before setStyle!!!
  200. symbolPath.setColor(color, seriesScope && seriesScope.symbolInnerColor);
  201. symbolPath.setStyle(itemStyle);
  202. var opacity = data.getItemVisual(idx, 'opacity');
  203. if (opacity != null) {
  204. elStyle.opacity = opacity;
  205. }
  206. var useNameLabel = seriesScope && seriesScope.useNameLabel;
  207. var valueDim = !useNameLabel && findLabelValueDim(data);
  208. if (useNameLabel || valueDim != null) {
  209. graphic.setLabelStyle(elStyle, hoverItemStyle, labelModel, hoverLabelModel, {
  210. labelFetcher: seriesModel,
  211. labelDataIndex: idx,
  212. defaultText: useNameLabel ? data.getName(idx) : data.get(valueDim, idx),
  213. isRectText: true,
  214. autoColor: color
  215. });
  216. }
  217. symbolPath.off('mouseover').off('mouseout').off('emphasis').off('normal');
  218. symbolPath.hoverStyle = hoverItemStyle; // FIXME
  219. // Do not use symbol.trigger('emphasis'), but use symbol.highlight() instead.
  220. graphic.setHoverStyle(symbolPath);
  221. var scale = getScale(symbolSize);
  222. if (hoverAnimation && seriesModel.isAnimationEnabled()) {
  223. var onEmphasis = function () {
  224. var ratio = scale[1] / scale[0];
  225. this.animateTo({
  226. scale: [Math.max(scale[0] * 1.1, scale[0] + 3), Math.max(scale[1] * 1.1, scale[1] + 3 * ratio)]
  227. }, 400, 'elasticOut');
  228. };
  229. var onNormal = function () {
  230. this.animateTo({
  231. scale: scale
  232. }, 400, 'elasticOut');
  233. };
  234. symbolPath.on('mouseover', onEmphasis).on('mouseout', onNormal).on('emphasis', onEmphasis).on('normal', onNormal);
  235. }
  236. };
  237. /**
  238. * @param {Function} cb
  239. * @param {Object} [opt]
  240. * @param {Object} [opt.keepLabel=true]
  241. */
  242. symbolProto.fadeOut = function (cb, opt) {
  243. var symbolPath = this.childAt(0); // Avoid mistaken hover when fading out
  244. this.silent = symbolPath.silent = true; // Not show text when animating
  245. !(opt && opt.keepLabel) && (symbolPath.style.text = null);
  246. graphic.updateProps(symbolPath, {
  247. style: {
  248. opacity: 0
  249. },
  250. scale: [0, 0]
  251. }, this._seriesModel, this.dataIndex, cb);
  252. };
  253. zrUtil.inherits(SymbolClz, graphic.Group);
  254. var _default = SymbolClz;
  255. module.exports = _default;