barChartZoom.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. import * as React from 'react';
  2. import {browserHistory} from 'react-router';
  3. import {EChartOption} from 'echarts/lib/echarts';
  4. import {Location} from 'history';
  5. import DataZoomInside from 'app/components/charts/components/dataZoomInside';
  6. import ToolBox from 'app/components/charts/components/toolBox';
  7. import {EChartChartReadyHandler, EChartDataZoomHandler} from 'app/types/echarts';
  8. import {callIfFunction} from 'app/utils/callIfFunction';
  9. export type RenderProps = {
  10. dataZoom: EChartOption['dataZoom'];
  11. toolBox: EChartOption['toolbox'];
  12. onChartReady: EChartChartReadyHandler;
  13. onDataZoom: EChartDataZoomHandler;
  14. };
  15. export type BarChartBucket = {
  16. start: number;
  17. end: number;
  18. };
  19. type Props = {
  20. location: Location;
  21. /**
  22. * This is the query parameter the start of the zoom will be propagated to.
  23. */
  24. paramStart: string;
  25. /**
  26. * This is the query parameter the end of the zoom will be propagated to.
  27. */
  28. paramEnd: string;
  29. /**
  30. * This is the minimum width of the zoom. If the targeted zoom area is
  31. * smaller than is specified by this parameter, the zoom will be cancelled
  32. * and the `onDataZoomCancelled` callback will be called.
  33. */
  34. minZoomWidth?: number;
  35. /**
  36. * This is the list of bucket start and end ranges. This is used by the
  37. * component to determine the start and end of the zoom.
  38. */
  39. buckets: BarChartBucket[];
  40. /**
  41. * If you need the dataZoom control to control more than one chart.
  42. * you can provide a list of the axis indexes.
  43. */
  44. xAxisIndex: number[];
  45. /**
  46. * The children function that will receive the render props and return
  47. * a rendered chart.
  48. */
  49. children: (props: RenderProps) => React.ReactNode;
  50. /**
  51. *
  52. */
  53. onHistoryPush?: (start: number, end: number) => void;
  54. /**
  55. * This callback is called when the zoom action was cancelled. It can happen
  56. * when `minZoomWidth` is specified and the user tries to zoom on an area
  57. * smaller than that.
  58. */
  59. onDataZoomCancelled?: () => void;
  60. onChartReady?: EChartChartReadyHandler;
  61. onDataZoom?: EChartDataZoomHandler;
  62. };
  63. class BarChartZoom extends React.Component<Props> {
  64. /**
  65. * Enable zoom immediately instead of having to toggle to zoom
  66. */
  67. handleChartReady = chart => {
  68. chart.dispatchAction({
  69. type: 'takeGlobalCursor',
  70. key: 'dataZoomSelect',
  71. dataZoomSelectActive: true,
  72. });
  73. callIfFunction(this.props.onChartReady, chart);
  74. };
  75. handleDataZoom = (evt, chart) => {
  76. const model = chart.getModel();
  77. const {xAxis} = model.option;
  78. const axis = xAxis[0];
  79. // Both of these values should not be null, but we include it just in case.
  80. // These values are null when the user uses the toolbox included in ECharts
  81. // to navigate back through zoom history, but we hide it below.
  82. if (axis.rangeStart !== null && axis.rangeEnd !== null) {
  83. const {buckets, location, paramStart, paramEnd, minZoomWidth, onHistoryPush} =
  84. this.props;
  85. const {start} = buckets[axis.rangeStart];
  86. const {end} = buckets[axis.rangeEnd];
  87. if (minZoomWidth === undefined || end - start > minZoomWidth) {
  88. const target = {
  89. pathname: location.pathname,
  90. query: {
  91. ...location.query,
  92. [paramStart]: start,
  93. [paramEnd]: end,
  94. },
  95. };
  96. if (onHistoryPush) {
  97. onHistoryPush(start, end);
  98. } else {
  99. browserHistory.push(target);
  100. }
  101. } else {
  102. // Dispatch the restore action here to stop ECharts from zooming
  103. chart.dispatchAction({type: 'restore'});
  104. callIfFunction(this.props.onDataZoomCancelled);
  105. }
  106. } else {
  107. // Dispatch the restore action here to stop ECharts from zooming
  108. chart.dispatchAction({type: 'restore'});
  109. callIfFunction(this.props.onDataZoomCancelled);
  110. }
  111. callIfFunction(this.props.onDataZoom, evt, chart);
  112. };
  113. render() {
  114. const {children, xAxisIndex} = this.props;
  115. const renderProps = {
  116. onChartReady: this.handleChartReady,
  117. dataZoom: DataZoomInside({xAxisIndex}),
  118. // We must include data zoom in the toolbox for the zoom to work,
  119. // but we do not want to show the toolbox components.
  120. toolBox: ToolBox(
  121. {},
  122. {
  123. dataZoom: {
  124. title: {
  125. zoom: '',
  126. back: '',
  127. },
  128. iconStyle: {
  129. borderWidth: 0,
  130. color: 'transparent',
  131. opacity: 0,
  132. },
  133. },
  134. }
  135. ),
  136. onDataZoom: this.handleDataZoom,
  137. };
  138. return children(renderProps);
  139. }
  140. }
  141. export default BarChartZoom;