ContinuousView.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. var zrUtil = require("zrender/lib/core/util");
  2. var LinearGradient = require("zrender/lib/graphic/LinearGradient");
  3. var eventTool = require("zrender/lib/core/event");
  4. var VisualMapView = require("./VisualMapView");
  5. var graphic = require("../../util/graphic");
  6. var numberUtil = require("../../util/number");
  7. var sliderMove = require("../helper/sliderMove");
  8. var helper = require("./helper");
  9. var modelUtil = require("../../util/model");
  10. var linearMap = numberUtil.linearMap;
  11. var each = zrUtil.each;
  12. var mathMin = Math.min;
  13. var mathMax = Math.max; // Arbitrary value
  14. var HOVER_LINK_SIZE = 12;
  15. var HOVER_LINK_OUT = 6; // Notice:
  16. // Any "interval" should be by the order of [low, high].
  17. // "handle0" (handleIndex === 0) maps to
  18. // low data value: this._dataInterval[0] and has low coord.
  19. // "handle1" (handleIndex === 1) maps to
  20. // high data value: this._dataInterval[1] and has high coord.
  21. // The logic of transform is implemented in this._createBarGroup.
  22. var ContinuousView = VisualMapView.extend({
  23. type: 'visualMap.continuous',
  24. /**
  25. * @override
  26. */
  27. init: function () {
  28. ContinuousView.superApply(this, 'init', arguments);
  29. /**
  30. * @private
  31. */
  32. this._shapes = {};
  33. /**
  34. * @private
  35. */
  36. this._dataInterval = [];
  37. /**
  38. * @private
  39. */
  40. this._handleEnds = [];
  41. /**
  42. * @private
  43. */
  44. this._orient;
  45. /**
  46. * @private
  47. */
  48. this._useHandle;
  49. /**
  50. * @private
  51. */
  52. this._hoverLinkDataIndices = [];
  53. /**
  54. * @private
  55. */
  56. this._dragging;
  57. /**
  58. * @private
  59. */
  60. this._hovering;
  61. },
  62. /**
  63. * @protected
  64. * @override
  65. */
  66. doRender: function (visualMapModel, ecModel, api, payload) {
  67. if (!payload || payload.type !== 'selectDataRange' || payload.from !== this.uid) {
  68. this._buildView();
  69. }
  70. },
  71. /**
  72. * @private
  73. */
  74. _buildView: function () {
  75. this.group.removeAll();
  76. var visualMapModel = this.visualMapModel;
  77. var thisGroup = this.group;
  78. this._orient = visualMapModel.get('orient');
  79. this._useHandle = visualMapModel.get('calculable');
  80. this._resetInterval();
  81. this._renderBar(thisGroup);
  82. var dataRangeText = visualMapModel.get('text');
  83. this._renderEndsText(thisGroup, dataRangeText, 0);
  84. this._renderEndsText(thisGroup, dataRangeText, 1); // Do this for background size calculation.
  85. this._updateView(true); // After updating view, inner shapes is built completely,
  86. // and then background can be rendered.
  87. this.renderBackground(thisGroup); // Real update view
  88. this._updateView();
  89. this._enableHoverLinkToSeries();
  90. this._enableHoverLinkFromSeries();
  91. this.positionGroup(thisGroup);
  92. },
  93. /**
  94. * @private
  95. */
  96. _renderEndsText: function (group, dataRangeText, endsIndex) {
  97. if (!dataRangeText) {
  98. return;
  99. } // Compatible with ec2, text[0] map to high value, text[1] map low value.
  100. var text = dataRangeText[1 - endsIndex];
  101. text = text != null ? text + '' : '';
  102. var visualMapModel = this.visualMapModel;
  103. var textGap = visualMapModel.get('textGap');
  104. var itemSize = visualMapModel.itemSize;
  105. var barGroup = this._shapes.barGroup;
  106. var position = this._applyTransform([itemSize[0] / 2, endsIndex === 0 ? -textGap : itemSize[1] + textGap], barGroup);
  107. var align = this._applyTransform(endsIndex === 0 ? 'bottom' : 'top', barGroup);
  108. var orient = this._orient;
  109. var textStyleModel = this.visualMapModel.textStyleModel;
  110. this.group.add(new graphic.Text({
  111. style: {
  112. x: position[0],
  113. y: position[1],
  114. textVerticalAlign: orient === 'horizontal' ? 'middle' : align,
  115. textAlign: orient === 'horizontal' ? align : 'center',
  116. text: text,
  117. textFont: textStyleModel.getFont(),
  118. textFill: textStyleModel.getTextColor()
  119. }
  120. }));
  121. },
  122. /**
  123. * @private
  124. */
  125. _renderBar: function (targetGroup) {
  126. var visualMapModel = this.visualMapModel;
  127. var shapes = this._shapes;
  128. var itemSize = visualMapModel.itemSize;
  129. var orient = this._orient;
  130. var useHandle = this._useHandle;
  131. var itemAlign = helper.getItemAlign(visualMapModel, this.api, itemSize);
  132. var barGroup = shapes.barGroup = this._createBarGroup(itemAlign); // Bar
  133. barGroup.add(shapes.outOfRange = createPolygon());
  134. barGroup.add(shapes.inRange = createPolygon(null, useHandle ? getCursor(this._orient) : null, zrUtil.bind(this._dragHandle, this, 'all', false), zrUtil.bind(this._dragHandle, this, 'all', true)));
  135. var textRect = visualMapModel.textStyleModel.getTextRect('国');
  136. var textSize = mathMax(textRect.width, textRect.height); // Handle
  137. if (useHandle) {
  138. shapes.handleThumbs = [];
  139. shapes.handleLabels = [];
  140. shapes.handleLabelPoints = [];
  141. this._createHandle(barGroup, 0, itemSize, textSize, orient, itemAlign);
  142. this._createHandle(barGroup, 1, itemSize, textSize, orient, itemAlign);
  143. }
  144. this._createIndicator(barGroup, itemSize, textSize, orient);
  145. targetGroup.add(barGroup);
  146. },
  147. /**
  148. * @private
  149. */
  150. _createHandle: function (barGroup, handleIndex, itemSize, textSize, orient) {
  151. var onDrift = zrUtil.bind(this._dragHandle, this, handleIndex, false);
  152. var onDragEnd = zrUtil.bind(this._dragHandle, this, handleIndex, true);
  153. var handleThumb = createPolygon(createHandlePoints(handleIndex, textSize), getCursor(this._orient), onDrift, onDragEnd);
  154. handleThumb.position[0] = itemSize[0];
  155. barGroup.add(handleThumb); // Text is always horizontal layout but should not be effected by
  156. // transform (orient/inverse). So label is built separately but not
  157. // use zrender/graphic/helper/RectText, and is located based on view
  158. // group (according to handleLabelPoint) but not barGroup.
  159. var textStyleModel = this.visualMapModel.textStyleModel;
  160. var handleLabel = new graphic.Text({
  161. draggable: true,
  162. drift: onDrift,
  163. onmousemove: function (e) {
  164. // Fot mobile devicem, prevent screen slider on the button.
  165. eventTool.stop(e.event);
  166. },
  167. ondragend: onDragEnd,
  168. style: {
  169. x: 0,
  170. y: 0,
  171. text: '',
  172. textFont: textStyleModel.getFont(),
  173. textFill: textStyleModel.getTextColor()
  174. }
  175. });
  176. this.group.add(handleLabel);
  177. var handleLabelPoint = [orient === 'horizontal' ? textSize / 2 : textSize * 1.5, orient === 'horizontal' ? handleIndex === 0 ? -(textSize * 1.5) : textSize * 1.5 : handleIndex === 0 ? -textSize / 2 : textSize / 2];
  178. var shapes = this._shapes;
  179. shapes.handleThumbs[handleIndex] = handleThumb;
  180. shapes.handleLabelPoints[handleIndex] = handleLabelPoint;
  181. shapes.handleLabels[handleIndex] = handleLabel;
  182. },
  183. /**
  184. * @private
  185. */
  186. _createIndicator: function (barGroup, itemSize, textSize, orient) {
  187. var indicator = createPolygon([[0, 0]], 'move');
  188. indicator.position[0] = itemSize[0];
  189. indicator.attr({
  190. invisible: true,
  191. silent: true
  192. });
  193. barGroup.add(indicator);
  194. var textStyleModel = this.visualMapModel.textStyleModel;
  195. var indicatorLabel = new graphic.Text({
  196. silent: true,
  197. invisible: true,
  198. style: {
  199. x: 0,
  200. y: 0,
  201. text: '',
  202. textFont: textStyleModel.getFont(),
  203. textFill: textStyleModel.getTextColor()
  204. }
  205. });
  206. this.group.add(indicatorLabel);
  207. var indicatorLabelPoint = [orient === 'horizontal' ? textSize / 2 : HOVER_LINK_OUT + 3, 0];
  208. var shapes = this._shapes;
  209. shapes.indicator = indicator;
  210. shapes.indicatorLabel = indicatorLabel;
  211. shapes.indicatorLabelPoint = indicatorLabelPoint;
  212. },
  213. /**
  214. * @private
  215. */
  216. _dragHandle: function (handleIndex, isEnd, dx, dy) {
  217. if (!this._useHandle) {
  218. return;
  219. }
  220. this._dragging = !isEnd;
  221. if (!isEnd) {
  222. // Transform dx, dy to bar coordination.
  223. var vertex = this._applyTransform([dx, dy], this._shapes.barGroup, true);
  224. this._updateInterval(handleIndex, vertex[1]); // Considering realtime, update view should be executed
  225. // before dispatch action.
  226. this._updateView();
  227. } // dragEnd do not dispatch action when realtime.
  228. if (isEnd === !this.visualMapModel.get('realtime')) {
  229. // jshint ignore:line
  230. this.api.dispatchAction({
  231. type: 'selectDataRange',
  232. from: this.uid,
  233. visualMapId: this.visualMapModel.id,
  234. selected: this._dataInterval.slice()
  235. });
  236. }
  237. if (isEnd) {
  238. !this._hovering && this._clearHoverLinkToSeries();
  239. } else if (useHoverLinkOnHandle(this.visualMapModel)) {
  240. this._doHoverLinkToSeries(this._handleEnds[handleIndex], false);
  241. }
  242. },
  243. /**
  244. * @private
  245. */
  246. _resetInterval: function () {
  247. var visualMapModel = this.visualMapModel;
  248. var dataInterval = this._dataInterval = visualMapModel.getSelected();
  249. var dataExtent = visualMapModel.getExtent();
  250. var sizeExtent = [0, visualMapModel.itemSize[1]];
  251. this._handleEnds = [linearMap(dataInterval[0], dataExtent, sizeExtent, true), linearMap(dataInterval[1], dataExtent, sizeExtent, true)];
  252. },
  253. /**
  254. * @private
  255. * @param {(number|string)} handleIndex 0 or 1 or 'all'
  256. * @param {number} dx
  257. * @param {number} dy
  258. */
  259. _updateInterval: function (handleIndex, delta) {
  260. delta = delta || 0;
  261. var visualMapModel = this.visualMapModel;
  262. var handleEnds = this._handleEnds;
  263. var sizeExtent = [0, visualMapModel.itemSize[1]];
  264. sliderMove(delta, handleEnds, sizeExtent, handleIndex, // cross is forbiden
  265. 0);
  266. var dataExtent = visualMapModel.getExtent(); // Update data interval.
  267. this._dataInterval = [linearMap(handleEnds[0], sizeExtent, dataExtent, true), linearMap(handleEnds[1], sizeExtent, dataExtent, true)];
  268. },
  269. /**
  270. * @private
  271. */
  272. _updateView: function (forSketch) {
  273. var visualMapModel = this.visualMapModel;
  274. var dataExtent = visualMapModel.getExtent();
  275. var shapes = this._shapes;
  276. var outOfRangeHandleEnds = [0, visualMapModel.itemSize[1]];
  277. var inRangeHandleEnds = forSketch ? outOfRangeHandleEnds : this._handleEnds;
  278. var visualInRange = this._createBarVisual(this._dataInterval, dataExtent, inRangeHandleEnds, 'inRange');
  279. var visualOutOfRange = this._createBarVisual(dataExtent, dataExtent, outOfRangeHandleEnds, 'outOfRange');
  280. shapes.inRange.setStyle({
  281. fill: visualInRange.barColor,
  282. opacity: visualInRange.opacity
  283. }).setShape('points', visualInRange.barPoints);
  284. shapes.outOfRange.setStyle({
  285. fill: visualOutOfRange.barColor,
  286. opacity: visualOutOfRange.opacity
  287. }).setShape('points', visualOutOfRange.barPoints);
  288. this._updateHandle(inRangeHandleEnds, visualInRange);
  289. },
  290. /**
  291. * @private
  292. */
  293. _createBarVisual: function (dataInterval, dataExtent, handleEnds, forceState) {
  294. var opts = {
  295. forceState: forceState,
  296. convertOpacityToAlpha: true
  297. };
  298. var colorStops = this._makeColorGradient(dataInterval, opts);
  299. var symbolSizes = [this.getControllerVisual(dataInterval[0], 'symbolSize', opts), this.getControllerVisual(dataInterval[1], 'symbolSize', opts)];
  300. var barPoints = this._createBarPoints(handleEnds, symbolSizes);
  301. return {
  302. barColor: new LinearGradient(0, 0, 0, 1, colorStops),
  303. barPoints: barPoints,
  304. handlesColor: [colorStops[0].color, colorStops[colorStops.length - 1].color]
  305. };
  306. },
  307. /**
  308. * @private
  309. */
  310. _makeColorGradient: function (dataInterval, opts) {
  311. // Considering colorHue, which is not linear, so we have to sample
  312. // to calculate gradient color stops, but not only caculate head
  313. // and tail.
  314. var sampleNumber = 100; // Arbitrary value.
  315. var colorStops = [];
  316. var step = (dataInterval[1] - dataInterval[0]) / sampleNumber;
  317. colorStops.push({
  318. color: this.getControllerVisual(dataInterval[0], 'color', opts),
  319. offset: 0
  320. });
  321. for (var i = 1; i < sampleNumber; i++) {
  322. var currValue = dataInterval[0] + step * i;
  323. if (currValue > dataInterval[1]) {
  324. break;
  325. }
  326. colorStops.push({
  327. color: this.getControllerVisual(currValue, 'color', opts),
  328. offset: i / sampleNumber
  329. });
  330. }
  331. colorStops.push({
  332. color: this.getControllerVisual(dataInterval[1], 'color', opts),
  333. offset: 1
  334. });
  335. return colorStops;
  336. },
  337. /**
  338. * @private
  339. */
  340. _createBarPoints: function (handleEnds, symbolSizes) {
  341. var itemSize = this.visualMapModel.itemSize;
  342. return [[itemSize[0] - symbolSizes[0], handleEnds[0]], [itemSize[0], handleEnds[0]], [itemSize[0], handleEnds[1]], [itemSize[0] - symbolSizes[1], handleEnds[1]]];
  343. },
  344. /**
  345. * @private
  346. */
  347. _createBarGroup: function (itemAlign) {
  348. var orient = this._orient;
  349. var inverse = this.visualMapModel.get('inverse');
  350. return new graphic.Group(orient === 'horizontal' && !inverse ? {
  351. scale: itemAlign === 'bottom' ? [1, 1] : [-1, 1],
  352. rotation: Math.PI / 2
  353. } : orient === 'horizontal' && inverse ? {
  354. scale: itemAlign === 'bottom' ? [-1, 1] : [1, 1],
  355. rotation: -Math.PI / 2
  356. } : orient === 'vertical' && !inverse ? {
  357. scale: itemAlign === 'left' ? [1, -1] : [-1, -1]
  358. } : {
  359. scale: itemAlign === 'left' ? [1, 1] : [-1, 1]
  360. });
  361. },
  362. /**
  363. * @private
  364. */
  365. _updateHandle: function (handleEnds, visualInRange) {
  366. if (!this._useHandle) {
  367. return;
  368. }
  369. var shapes = this._shapes;
  370. var visualMapModel = this.visualMapModel;
  371. var handleThumbs = shapes.handleThumbs;
  372. var handleLabels = shapes.handleLabels;
  373. each([0, 1], function (handleIndex) {
  374. var handleThumb = handleThumbs[handleIndex];
  375. handleThumb.setStyle('fill', visualInRange.handlesColor[handleIndex]);
  376. handleThumb.position[1] = handleEnds[handleIndex]; // Update handle label position.
  377. var textPoint = graphic.applyTransform(shapes.handleLabelPoints[handleIndex], graphic.getTransform(handleThumb, this.group));
  378. handleLabels[handleIndex].setStyle({
  379. x: textPoint[0],
  380. y: textPoint[1],
  381. text: visualMapModel.formatValueText(this._dataInterval[handleIndex]),
  382. textVerticalAlign: 'middle',
  383. textAlign: this._applyTransform(this._orient === 'horizontal' ? handleIndex === 0 ? 'bottom' : 'top' : 'left', shapes.barGroup)
  384. });
  385. }, this);
  386. },
  387. /**
  388. * @private
  389. * @param {number} cursorValue
  390. * @param {number} textValue
  391. * @param {string} [rangeSymbol]
  392. * @param {number} [halfHoverLinkSize]
  393. */
  394. _showIndicator: function (cursorValue, textValue, rangeSymbol, halfHoverLinkSize) {
  395. var visualMapModel = this.visualMapModel;
  396. var dataExtent = visualMapModel.getExtent();
  397. var itemSize = visualMapModel.itemSize;
  398. var sizeExtent = [0, itemSize[1]];
  399. var pos = linearMap(cursorValue, dataExtent, sizeExtent, true);
  400. var shapes = this._shapes;
  401. var indicator = shapes.indicator;
  402. if (!indicator) {
  403. return;
  404. }
  405. indicator.position[1] = pos;
  406. indicator.attr('invisible', false);
  407. indicator.setShape('points', createIndicatorPoints(!!rangeSymbol, halfHoverLinkSize, pos, itemSize[1]));
  408. var opts = {
  409. convertOpacityToAlpha: true
  410. };
  411. var color = this.getControllerVisual(cursorValue, 'color', opts);
  412. indicator.setStyle('fill', color); // Update handle label position.
  413. var textPoint = graphic.applyTransform(shapes.indicatorLabelPoint, graphic.getTransform(indicator, this.group));
  414. var indicatorLabel = shapes.indicatorLabel;
  415. indicatorLabel.attr('invisible', false);
  416. var align = this._applyTransform('left', shapes.barGroup);
  417. var orient = this._orient;
  418. indicatorLabel.setStyle({
  419. text: (rangeSymbol ? rangeSymbol : '') + visualMapModel.formatValueText(textValue),
  420. textVerticalAlign: orient === 'horizontal' ? align : 'middle',
  421. textAlign: orient === 'horizontal' ? 'center' : align,
  422. x: textPoint[0],
  423. y: textPoint[1]
  424. });
  425. },
  426. /**
  427. * @private
  428. */
  429. _enableHoverLinkToSeries: function () {
  430. var self = this;
  431. this._shapes.barGroup.on('mousemove', function (e) {
  432. self._hovering = true;
  433. if (!self._dragging) {
  434. var itemSize = self.visualMapModel.itemSize;
  435. var pos = self._applyTransform([e.offsetX, e.offsetY], self._shapes.barGroup, true, true); // For hover link show when hover handle, which might be
  436. // below or upper than sizeExtent.
  437. pos[1] = mathMin(mathMax(0, pos[1]), itemSize[1]);
  438. self._doHoverLinkToSeries(pos[1], 0 <= pos[0] && pos[0] <= itemSize[0]);
  439. }
  440. }).on('mouseout', function () {
  441. // When mouse is out of handle, hoverLink still need
  442. // to be displayed when realtime is set as false.
  443. self._hovering = false;
  444. !self._dragging && self._clearHoverLinkToSeries();
  445. });
  446. },
  447. /**
  448. * @private
  449. */
  450. _enableHoverLinkFromSeries: function () {
  451. var zr = this.api.getZr();
  452. if (this.visualMapModel.option.hoverLink) {
  453. zr.on('mouseover', this._hoverLinkFromSeriesMouseOver, this);
  454. zr.on('mouseout', this._hideIndicator, this);
  455. } else {
  456. this._clearHoverLinkFromSeries();
  457. }
  458. },
  459. /**
  460. * @private
  461. */
  462. _doHoverLinkToSeries: function (cursorPos, hoverOnBar) {
  463. var visualMapModel = this.visualMapModel;
  464. var itemSize = visualMapModel.itemSize;
  465. if (!visualMapModel.option.hoverLink) {
  466. return;
  467. }
  468. var sizeExtent = [0, itemSize[1]];
  469. var dataExtent = visualMapModel.getExtent(); // For hover link show when hover handle, which might be below or upper than sizeExtent.
  470. cursorPos = mathMin(mathMax(sizeExtent[0], cursorPos), sizeExtent[1]);
  471. var halfHoverLinkSize = getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent);
  472. var hoverRange = [cursorPos - halfHoverLinkSize, cursorPos + halfHoverLinkSize];
  473. var cursorValue = linearMap(cursorPos, sizeExtent, dataExtent, true);
  474. var valueRange = [linearMap(hoverRange[0], sizeExtent, dataExtent, true), linearMap(hoverRange[1], sizeExtent, dataExtent, true)]; // Consider data range is out of visualMap range, see test/visualMap-continuous.html,
  475. // where china and india has very large population.
  476. hoverRange[0] < sizeExtent[0] && (valueRange[0] = -Infinity);
  477. hoverRange[1] > sizeExtent[1] && (valueRange[1] = Infinity); // Do not show indicator when mouse is over handle,
  478. // otherwise labels overlap, especially when dragging.
  479. if (hoverOnBar) {
  480. if (valueRange[0] === -Infinity) {
  481. this._showIndicator(cursorValue, valueRange[1], '< ', halfHoverLinkSize);
  482. } else if (valueRange[1] === Infinity) {
  483. this._showIndicator(cursorValue, valueRange[0], '> ', halfHoverLinkSize);
  484. } else {
  485. this._showIndicator(cursorValue, cursorValue, '≈ ', halfHoverLinkSize);
  486. }
  487. } // When realtime is set as false, handles, which are in barGroup,
  488. // also trigger hoverLink, which help user to realize where they
  489. // focus on when dragging. (see test/heatmap-large.html)
  490. // When realtime is set as true, highlight will not show when hover
  491. // handle, because the label on handle, which displays a exact value
  492. // but not range, might mislead users.
  493. var oldBatch = this._hoverLinkDataIndices;
  494. var newBatch = [];
  495. if (hoverOnBar || useHoverLinkOnHandle(visualMapModel)) {
  496. newBatch = this._hoverLinkDataIndices = visualMapModel.findTargetDataIndices(valueRange);
  497. }
  498. var resultBatches = modelUtil.compressBatches(oldBatch, newBatch);
  499. this._dispatchHighDown('downplay', helper.convertDataIndex(resultBatches[0]));
  500. this._dispatchHighDown('highlight', helper.convertDataIndex(resultBatches[1]));
  501. },
  502. /**
  503. * @private
  504. */
  505. _hoverLinkFromSeriesMouseOver: function (e) {
  506. var el = e.target;
  507. var visualMapModel = this.visualMapModel;
  508. if (!el || el.dataIndex == null) {
  509. return;
  510. }
  511. var dataModel = this.ecModel.getSeriesByIndex(el.seriesIndex);
  512. if (!visualMapModel.isTargetSeries(dataModel)) {
  513. return;
  514. }
  515. var data = dataModel.getData(el.dataType);
  516. var dim = data.getDimension(visualMapModel.getDataDimension(data));
  517. var value = data.get(dim, el.dataIndex, true);
  518. if (!isNaN(value)) {
  519. this._showIndicator(value, value);
  520. }
  521. },
  522. /**
  523. * @private
  524. */
  525. _hideIndicator: function () {
  526. var shapes = this._shapes;
  527. shapes.indicator && shapes.indicator.attr('invisible', true);
  528. shapes.indicatorLabel && shapes.indicatorLabel.attr('invisible', true);
  529. },
  530. /**
  531. * @private
  532. */
  533. _clearHoverLinkToSeries: function () {
  534. this._hideIndicator();
  535. var indices = this._hoverLinkDataIndices;
  536. this._dispatchHighDown('downplay', helper.convertDataIndex(indices));
  537. indices.length = 0;
  538. },
  539. /**
  540. * @private
  541. */
  542. _clearHoverLinkFromSeries: function () {
  543. this._hideIndicator();
  544. var zr = this.api.getZr();
  545. zr.off('mouseover', this._hoverLinkFromSeriesMouseOver);
  546. zr.off('mouseout', this._hideIndicator);
  547. },
  548. /**
  549. * @private
  550. */
  551. _applyTransform: function (vertex, element, inverse, global) {
  552. var transform = graphic.getTransform(element, global ? null : this.group);
  553. return graphic[zrUtil.isArray(vertex) ? 'applyTransform' : 'transformDirection'](vertex, transform, inverse);
  554. },
  555. /**
  556. * @private
  557. */
  558. _dispatchHighDown: function (type, batch) {
  559. batch && batch.length && this.api.dispatchAction({
  560. type: type,
  561. batch: batch
  562. });
  563. },
  564. /**
  565. * @override
  566. */
  567. dispose: function () {
  568. this._clearHoverLinkFromSeries();
  569. this._clearHoverLinkToSeries();
  570. },
  571. /**
  572. * @override
  573. */
  574. remove: function () {
  575. this._clearHoverLinkFromSeries();
  576. this._clearHoverLinkToSeries();
  577. }
  578. });
  579. function createPolygon(points, cursor, onDrift, onDragEnd) {
  580. return new graphic.Polygon({
  581. shape: {
  582. points: points
  583. },
  584. draggable: !!onDrift,
  585. cursor: cursor,
  586. drift: onDrift,
  587. onmousemove: function (e) {
  588. // Fot mobile devicem, prevent screen slider on the button.
  589. eventTool.stop(e.event);
  590. },
  591. ondragend: onDragEnd
  592. });
  593. }
  594. function createHandlePoints(handleIndex, textSize) {
  595. return handleIndex === 0 ? [[0, 0], [textSize, 0], [textSize, -textSize]] : [[0, 0], [textSize, 0], [textSize, textSize]];
  596. }
  597. function createIndicatorPoints(isRange, halfHoverLinkSize, pos, extentMax) {
  598. return isRange ? [// indicate range
  599. [0, -mathMin(halfHoverLinkSize, mathMax(pos, 0))], [HOVER_LINK_OUT, 0], [0, mathMin(halfHoverLinkSize, mathMax(extentMax - pos, 0))]] : [// indicate single value
  600. [0, 0], [5, -5], [5, 5]];
  601. }
  602. function getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent) {
  603. var halfHoverLinkSize = HOVER_LINK_SIZE / 2;
  604. var hoverLinkDataSize = visualMapModel.get('hoverLinkDataSize');
  605. if (hoverLinkDataSize) {
  606. halfHoverLinkSize = linearMap(hoverLinkDataSize, dataExtent, sizeExtent, true) / 2;
  607. }
  608. return halfHoverLinkSize;
  609. }
  610. function useHoverLinkOnHandle(visualMapModel) {
  611. var hoverLinkOnHandle = visualMapModel.get('hoverLinkOnHandle');
  612. return !!(hoverLinkOnHandle == null ? visualMapModel.get('realtime') : hoverLinkOnHandle);
  613. }
  614. function getCursor(orient) {
  615. return orient === 'vertical' ? 'ns-resize' : 'ew-resize';
  616. }
  617. var _default = ContinuousView;
  618. module.exports = _default;