Echart饼图实现(圆环图)+状态颜色控制

javascript/jquery

浏览数:692

2020-5-23

最近做项目遇到了圆环图以及对于图例颜色值的处理,这里做一个记录,分享给大家。
UI图长这样:

HTML

<div class="flex-row">
              <div class="contain flex-row" v-loading="taskLoading">
                <resize-chart :chart="taskChart">
                  <div id="taskChart" style="width:7.8rem;height:5rem;" />
                </resize-chart>
              </div>
            </div>

其中,resize-chart是封装的自适应组件

JS

initTaskChart() {
      getTaskStatus({ type: this.taskTimeType }).then(res => {
        console.log('任务状态', res)
        if (res) {
          const color = [
            '#999999',
            '#00cce2',
            '#9962ff',
            '#27dca1',
            '#e9e536',
            '',
            '#1cbe6b',
            '#f8a639',
            '#f868b9',
            '#4a8dfd',
            '#f45151'
          ]
          let taskStateList = JSON.parse(JSON.stringify(res))
          let taskStateData = []
          let taskStatelegendData = []
          let taskTotal = 0
          for (const item of taskStateList) {
            taskTotal += item.count
            taskStateData.push({
              name: this.taskStateArr[item.state],
              value: item.count,
              itemStyle: {
                normal: { color: this.statusColorHandle(item.state, color) }
              }
            })
            taskStatelegendData.push({
              name: this.taskStateArr[item.state],
              value: item.count,
              textStyle: {
                normal: { color: this.statusColorHandle(item.state, color) }
              }
            })
          }
          this.taskChart = echarts.init(document.getElementById('taskChart'))
          this.taskChart.setOption(
            {
              title: {
                text: taskTotal === 0 ? '' : taskTotal,//主要是为了处理没有数据时
                subtext: taskTotal !== 0 ? '任务总量' : '',
                x: 'center',
                y: 'center',
                textAlign: 'center',
                itemGap: 5, //主副标题之间的间距
                top: '38%',
                left: '28%',
                // 标题
                textStyle: {
                  fontFamily: 'PingFangSC-Medium',
                  fontWeight: 'normal',
                  fontSize: 20,
                  color: '#333333'
                },
                // 副标题
                subtextStyle: {
                  fontWeight: 'normal',
                  fontSize: 14,
                  color: '#333333'
                }
              },
              legend: {
                type: 'scroll',
                icon: 'circle',
                orient: 'vertical',
                y: 'center',
                right: '5%',
                itemWidth: 5,
                itemHeight: 5,
                data: taskStatelegendData,
                // 使用回调函数
                formatter: function(name) {
                  let count, percent
                  for (const item of taskStatelegendData) {
                    if (item.name === name) {
                      count = item.value
                      percent = ((item.value / taskTotal) * 100).toFixed(2)
                    }
                  }
                  let arr = [
                    '{a|' + name + '}',
                    '{b|' + count + '}',
                    '{c|' + percent + '}%'
                  ]
                  return arr.join('')
                },
                textStyle: {
                  rich: {
                    a: {
                      fontSize: 12,
                      width: 50,
                      color: 'rgba(51, 51, 51, 0.6)'
                    },
                    b: {
                      fontSize: 12,
                      width: 40,
                      color: '#333'
                    },
                    c: {
                      fontSize: 12,
                      width: 38,
                      color: '#333'
                    }
                  }
                }
              },
              tooltip: {
                trigger: 'item',
                formatter: '{a} <br/>{b} : {c} ({d}%)'
              },
              series: [
                {
                  name: '任务状态',
                  type: 'pie',
                  radius: ['40%', '55%'], // 第一项是内半径,第二项是外半径,内半径为0就是真的饼,不是环形
                  center: ['30%', '50%'], // 位置
                  label: {
                    normal: {
                      show: false, // 是否显示标签[ default: false ]
                      position: 'outside', // 标签的位置。'outside'饼图扇区外侧,通过视觉引导线连到相应的扇区。'inside','inner' 同 'inside',饼图扇区内部。'center'在饼图中心位置。
                      formatter: function(params) {
                        return (
                          '{c|' +
                          params.value +
                          '}  {d|' +
                          params.percent +
                          '%}\n{b|' +
                          params.name +
                          '}'
                        )
                      },
                      fontFamily: 'PingFangSC-Regular',
                      lineHeight: 20,
                      padding: [0, -55],
                      rich: {
                        c: {
                          color: '#333333',
                          fontSize: 14,
                          align: 'left',
                          padding: [0, 0, 0, 10]
                        },
                        d: {
                          color: '#333333',
                          align: 'left',
                          fontSize: 14
                        },
                        b: {
                          color: 'rgba(51, 51, 51, 0.6)',
                          fontSize: 14,
                          align: 'left',
                          padding: [0, 0, 0, 10]
                        }
                      }
                    }
                  },
                  labelLine: {
                    // 标签的视觉引导线样式,在 label 位置 设置为'outside'的时候会显示视觉引导线。
                    normal: {
                      show: false, // 是否显示视觉引导线。
                      length: 20, // 在 label 位置 设置为'outside'的时候会显示视觉引导线。
                      length2: 40, // 视觉引导项第二段的长度。
                      lineStyle: {
                        // 视觉引导线的样式
                        //color: '#000',
                        //width: 1
                      }
                    }
                  },
                  data: taskStateData,
                  itemStyle: {
                    emphasis: {
                      shadowBlur: 10,
                      shadowOffsetX: 0,
                      shadowColor: 'rgba(0, 0, 0, 0.5)'
                    }
                  }
                }
              ]
            },
            true //这个参数有它的作用
          )
        }
        this.taskLoading = false
      })
    }

其中,用到了一个函数statusColorHandle,这个是根据具体的状态分配颜色值的,这里做了封装:

statusColorHandle(state, colorArr) {
  state = ~~state
  return colorArr[state % colorArr.length]
},

这是其中一个,另外一个基本类似,下面是实现的效果图:

代码里添加了很多注释,方便自己查阅,分享给大家,希望大家在用到的时候遇到问题了可以作为参考。

作者:阿星