Chart.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. import React from 'react'
  2. import { IChartProps } from './index'
  3. import chartlibs from '../../config/chart'
  4. import echarts from 'echarts/lib/echarts'
  5. import { ECharts } from 'echarts'
  6. import chartOptionGenerator from '../../render/chart'
  7. const styles = require('./Chart.less')
  8. interface IChartStates {
  9. seriesItems: string[]
  10. }
  11. export class Chart extends React.PureComponent<IChartProps, IChartStates> {
  12. private asyncEmitTimer: NodeJS.Timer | null = null
  13. private container: HTMLDivElement = null
  14. private instance: ECharts
  15. constructor(props) {
  16. super(props)
  17. this.state = {
  18. seriesItems: []
  19. }
  20. }
  21. public componentDidMount() {
  22. this.renderChart(this.props)
  23. }
  24. public componentDidUpdate() {
  25. this.renderChart(this.props)
  26. }
  27. private renderChart = (props: IChartProps) => {
  28. const {
  29. selectedChart,
  30. renderType,
  31. getDataDrillDetail,
  32. isDrilling,
  33. onError
  34. } = props
  35. if (renderType === 'loading') {
  36. return
  37. }
  38. if (!this.instance) {
  39. this.instance = echarts.init(this.container, 'default')
  40. } else {
  41. if (renderType === 'rerender') {
  42. this.instance.dispose()
  43. this.instance = echarts.init(this.container, 'default')
  44. }
  45. if (renderType === 'clear') {
  46. this.instance.clear()
  47. }
  48. }
  49. try {
  50. this.instance.off('click')
  51. this.instance.on('click', (params) => {
  52. this.collectSelectedItems(params)
  53. })
  54. this.instance.setOption(
  55. chartOptionGenerator(
  56. chartlibs.find((cl) => cl.id === selectedChart).name,
  57. props,
  58. {
  59. instance: this.instance,
  60. isDrilling,
  61. getDataDrillDetail,
  62. selectedItems: this.props.selectedItems,
  63. callback: (seriesData) => {
  64. this.instance.off('click')
  65. this.instance.on('click', (params) => {
  66. this.collectSelectedItems(params, seriesData)
  67. })
  68. }
  69. }
  70. )
  71. )
  72. this.instance.resize()
  73. } catch (error) {
  74. if (onError) {
  75. onError(error)
  76. }
  77. }
  78. }
  79. public componentWillUnmount() {
  80. if (this.instance) {
  81. this.instance.off('click')
  82. }
  83. if (this.asyncEmitTimer) {
  84. clearTimeout(this.asyncEmitTimer)
  85. }
  86. }
  87. private collectSelectedItems = (params, seriesData?) => {
  88. const {
  89. data,
  90. selectedChart,
  91. onDoInteract,
  92. getDataDrillDetail,
  93. onSelectChartsItems,
  94. onCheckTableInteract
  95. } = this.props
  96. const { seriesItems } = this.state
  97. let selectedItems = []
  98. let series = []
  99. if (this.props.selectedItems && this.props.selectedItems.length) {
  100. selectedItems = [...this.props.selectedItems]
  101. }
  102. let dataIndex = params.dataIndex
  103. if (selectedChart === 4) {
  104. dataIndex = params.seriesIndex
  105. }
  106. if (selectedItems.length === 0) {
  107. selectedItems.push(dataIndex)
  108. } else {
  109. const isb = selectedItems.some((item) => item === dataIndex)
  110. if (isb) {
  111. for (let index = 0, l = selectedItems.length; index < l; index++) {
  112. if (selectedItems[index] === dataIndex) {
  113. selectedItems.splice(index, 1)
  114. break
  115. }
  116. }
  117. } else {
  118. selectedItems.push(dataIndex)
  119. }
  120. }
  121. if (seriesData) {
  122. const { seriesIndex, dataIndex } = params
  123. const char = `${seriesIndex}&${dataIndex}`
  124. if (seriesItems && Array.isArray(seriesItems)) {
  125. series = seriesItems.includes(char)
  126. ? seriesItems.filter((item) => item !== char)
  127. : seriesItems.concat(char)
  128. this.setState({ seriesItems: series })
  129. }
  130. }
  131. const resultData = selectedItems.map((item, index) => {
  132. if (seriesData) {
  133. const seriesIndex = series[index] ? series[index].split('&')[0] : null
  134. return seriesData[seriesIndex] ? seriesData[seriesIndex][item] : []
  135. }
  136. return data[item]
  137. })
  138. const brushed = [{ 0: Object.values(resultData) }]
  139. const sourceData = Object.values(resultData)
  140. const isInteractiveChart = onCheckTableInteract && onCheckTableInteract()
  141. if (isInteractiveChart && onDoInteract) {
  142. const triggerData = sourceData
  143. onDoInteract(triggerData)
  144. }
  145. this.asyncEmitTimer = setTimeout(() => {
  146. if (getDataDrillDetail) {
  147. getDataDrillDetail(JSON.stringify({ range: null, brushed, sourceData }))
  148. }
  149. }, 500)
  150. if (onSelectChartsItems) {
  151. onSelectChartsItems(selectedItems)
  152. }
  153. }
  154. public render() {
  155. return (
  156. <div
  157. className={styles.chartContainer}
  158. ref={(f) => (this.container = f)}
  159. />
  160. )
  161. }
  162. }
  163. export default Chart