Uso de ECharts y errores comunes en React + Antd

Recientemente, comencé a usar ECharts para crear gráficos en el proyecto. Todavía encontré muchas trampas al usar EChart en React + Antd. Espero que registrar la solución pueda ayudar a todos. Debido al primer uso, hay mucho espacio para la optimización del código. Espero que todos puedan ayudarme. Gracias ~

efecto final

1. Realice la vinculación de dos datos de gráficos circulares haciendo clic en el punto del gráfico de líneas.
2. Resuelva el problema de que los datos del gráfico circular ECharts son 0 o el gráfico circular desaparece cuando está vacío

Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí

Cómo usar ECharts en React

1. Agrega div en render

<div id='echartLine' style={
    
    {
    
     width: '100%', height: 300, margin: '24px 0' }} />
<div id='pieTotal' style={
    
    {
    
     width: '100%', height: 300, margin: '24px 0' }} />
<div id='pieReject' style={
    
    {
    
     width: '100%', height: 300, margin: '24px 0' }} />

2. Inicie el gráfico ECharts

	// 饼图初始option
	const initPieOption = {
    
    
	  // tooltip: {
    
    
	  //   show: false,
	  // },
	  dataset: {
    
    
	    dimensions: ['desc', 'type', 'value'],
	    source: [{
    
     desc: '', type: '', value: 1 }], // 当无数据时,给饼图个初始数据
	  },
	  grid: {
    
    
	    left: '3%',
	    right: '3%',
	    bottom: '0%',
	    containLabel: true,
	  },
	  series: [
	    {
    
     type: 'pie',
	      radius: ['75%', '45%'],
	      stillShowZeroSum: false,
	      itemStyle: {
    
    
	        color: '#e7e7e7',
	      },
	      label: {
    
    
	        normal: {
    
    
	          show: true,
	          position: 'center',
	          formatter: function () {
    
    
	            var result = ''
	            result = '暂无数据'
	
	            return result
	          },
	          textStyle: {
    
    
	            fontSize: 16,
	            color: '#e2e2e2',
	          },
	        },
	      },
	    },
	  ],
	}
  // 初始化图表
  initChart = () => {
    
    
    // const { trendList } = this.state

    // 折线图
    var lineChart = echarts.init(document.getElementById('echartLine'))
    // 建议将ECharts图表实例进行储存,而不是每次数据变化都进行实例初始化
    this.setState({
    
     lineChart })
    lineChart.setOption({
    
    
      title: {
    
    
        text: '趋势',
      },
      tooltip: {
    
    
        trigger: 'axis',
        axisPointer: {
    
    
          type: 'cross',
        },
      },
      legend: {
    
    
        formatter: function (name) {
    
    
          switch (name) {
    
    
            case 'total':
              return '总量 ' + name
            case 'passCount':
              return '通过量 ' + name
            case 'rejectCount':
              return '拒绝量 ' + name
          }
        },
      },
      dataset: {
    
    
        // 这里指定了维度名的顺序,从而可以利用默认的维度到坐标轴的映射。
        // 如果不指定 dimensions,也可以通过指定 series.encode 完成映射,参见后文。
        dimensions: ['date', 'total', 'passCount', 'rejectCount'],
        source: [],
      },
      xAxis: {
    
     type: 'category' },
      yAxis: {
    
    
        type: 'value',
      },
      grid: {
    
    
        left: '3%',
        right: '6%',
        bottom: '0%',
        containLabel: true,
      },
      series: [
        {
    
     type: 'line' },
        {
    
     type: 'line' },
        {
    
     type: 'line' },
      ],
    })
    // 饼图总量
    var pieChartTotal = echarts.init(document.getElementById('pieTotal'))
    this.setState({
    
     pieChartTotal })

    // 饼图拒绝量
    var pieChartReject = echarts.init(document.getElementById('pieReject'))
    this.setState({
    
     pieChartReject })

	// 使图表自适应div大小,防止图表溢出
    window.addEventListener('resize', function () {
    
    
      lineChart.resize()
      pieChartTotal.resize()
      pieChartReject.resize()
    })
  }

3. Vuelva a renderizar el gráfico cuando cambien los datos.

 // 获取趋势图
  fetchBaseTrend = async () => {
    
    
    const res = await api.getBaseTrend()
    this.setState({
    
    
      trendList: res,
    }, () => {
    
    
      // 获取到数据后再去调用渲染图表函数
      this.generateChart()
    })
  }
  generateChart = () => {
    
    
    const {
    
     trendList, lineChart, pieChartTotal, pieChartReject } = this.state

    lineChart.setOption({
    
    
      dataset: {
    
    
        // 这里指定了维度名的顺序,从而可以利用默认的维度到坐标轴的映射。
        // 如果不指定 dimensions,也可以通过指定 series.encode 完成映射,参见后文。
        dimensions: ['date', 'total', 'passCount', 'rejectCount'],
        source: trendList,
      },
    })
	// 由于我对饼图无数据做了处理,所以每次setOption之前都要先执行clear(),防止之前setOption内的灰色背景属性仍生效
    pieChartTotal.clear()
    pieChartReject.clear()

	// 默认用数据加载第一条渲染饼图,可能存在无数据情况,因此需要判断
    pieChartTotal.setOption(trendList[0] && !!trendList[0].totalRatio.length ? this.PieOption('total') : initPieOption)
    pieChartReject.setOption(trendList[0] && !!trendList[0].rejectRatio.length ? this.PieOption('reject') : initPieOption)
 }

4. Cómo hacer clic en el gráfico de líneas para representar el gráfico circular

Hay mucho espacio para la optimización de esta parte del código, pero lo he cambiado durante mucho tiempo y no he encontrado una mejor manera. Espero que todos puedan ayudarme con comentarios. Gracias ~

  generateChart = () => {
    
    
  
    lineChart.on('click', function (event) {
    
    
      pieChartTotal.clear()

      pieChartTotal.setOption(event.data && !!event.data.totalRatio.length ? {
    
    
        dataset: {
    
    
          // 这里指定了维度名的顺序,从而可以利用默认的维度到坐标轴的映射。
          // 如果不指定 dimensions,也可以通过指定 series.encode 完成映射,参见后文。
          dimensions: ['desc', 'type', 'value'],
          source: event.data && event.data.totalRatio,
        },
        legend: {
    
    
          orient: 'vertical',
          left: 70,
        },
        tooltip: {
    
    
          trigger: 'item',
          formatter: function (params) {
    
    
            var result = ''
            result = params.name + ' : ' + params.data.value + ' ( ' + params.percent + '% )'

            return result
          },
        },
        series: [
          {
    
     type: 'pie',
            radius: ['75%', '50%'],
            label: {
    
    
              normal: {
    
    
                show: true,
                position: 'center',
                color: '#4c4a4a',
                formatter: function (data) {
    
    
                  var result = ''
                  result = event.name + '\n' + '总量' + ' ' + event.data.total

                  return result
                },
                textStyle: {
    
    
                  fontSize: 16,
                  color: '#00c0ef',
                },
              },
            },
          },
        ],
      } : initPieOption)
      pieChartReject.clear()
      pieChartReject.setOption(event.data.rejectRatio && !!event.data.rejectRatio.length ? {
    
    
        dataset: {
    
    
          // 这里指定了维度名的顺序,从而可以利用默认的维度到坐标轴的映射。
          // 如果不指定 dimensions,也可以通过指定 series.encode 完成映射,参见后文。
          dimensions: ['desc', 'type', 'value'],
          source: event.data && event.data.rejectRatio,
        },
        legend: {
    
    
          orient: 'vertical',
          right: 70,
        },
        series: [
          {
    
     type: 'pie',
            radius: ['75%', '45%'],
            label: {
    
    
              normal: {
    
    
                show: true,
                position: 'center',
                color: '#4c4a4a',
                formatter: function (data) {
    
    
                  var result = ''
                  result = event.name + '\n' + '拒绝量' + ' ' + event.data.rejectCount

                  return result
                },
                textStyle: {
    
    
                  fontSize: 16,
                  color: '#00c0ef',
                },
              },
            },
          },
        ],
      } : initPieOption)
    })
  }

4. Estructura de datos TrendList

[{
    
    
	"date": "2020-03-23",
	"total": 52,
	"passCount": 51,
	"rejectCount": 1,
	"totalRatio": [{
    
    
		"type": "text",
		"desc": "文本",
		"value": 27
	}, {
    
    
		"type": "picture",
		"desc": "图片",
		"value": 25
	}],
	"rejectRatio": [{
    
    
		"type": "picture",
		"desc": "图片",
		"value": 1
	}]
}, {
    
    
	"date": "2020-03-24",
	"total": 25,
	"passCount": 18,
	"rejectCount": 7,
	"totalRatio": [{
    
    
		"type": "picture",
		"desc": "图片",
		"value": 15
	}, {
    
    
		"type": "text",
		"desc": "文本",
		"value": 10
	}],
	"rejectRatio": [{
    
    
		"type": "picture",
		"desc": "图片",
		"value": 7
	}]
}]

Preguntas frecuentes sobre ECharts

Problema: Error: El componente series.pie no existe. Cárguelo primero.
Razón: No se introdujo ningún componente circular.
Solución:

import 'echarts/lib/chart/pie'

Problema: ECharts3 elimina noDataLoadingOption. Cuando no hay datos, no muestra datos en el contenedor. Después de cambiar, no se puede mostrar el gráfico.
Solución:

  1. Determinar si los datos tienen un valor y procesarlos si no hay ningún valor
  2. Borrar la opción de la instancia en setOption
  3. Extraiga la instancia de ECharts, no la cree siempre
  4. El código específico se puede ver en el bloque de código anterior, si no está seguro, puede preguntarme en privado
	// 默认用数据加载第一条渲染饼图,可能存在无数据情况,因此需要判断
    pieChartTotal.setOption(trendList[0] && !!trendList[0].totalRatio.length ? this.PieOption('total') : initPieOption)

Problema: contenido del formato del formateador de etiquetas, es necesario ajustar.
Razón: la etiqueta se basa en un lienzo, no es compatible con html, solo admite el ajuste \ nSolve
:

formatter: function (data) {
    
    
	var result = ''
	result = event.name + '\n' + '总量' + ' ' + event.data.total

	return result
},

Problema: el gráfico desborda el div y no se puede resolver de forma adaptativa
:

   window.addEventListener('resize', function () {
    
    
      lineChart.resize()
    })

Problema: el evento de clic está vinculado varias veces, lo que hace que la devolución de llamada se active varias veces
.

  myChart.off('click')// 防止累计触发
  myChart.on('click', function (event) {
    
    
     const url = reportTypesMap[item.key]['url']

     if (!url) return false
     const href = window.location.href.split('#')[0]
     window.open(`${
      
      href}#${
      
      url}?time=${
      
      event.name}`)
   })

Supongo que te gusta

Origin blog.csdn.net/zn740395858/article/details/105181685
Recomendado
Clasificación