echarts各类图表-饼图(一)

1,423 阅读2分钟

饼图(一)

前言

版本用的是5,跟4配置有差别

一、饼图

  1. 有间隔的环形图1,如图所示

image.png image.png

有几个点要注意(从内到外,为环形1-3):

  • 实现逻辑,由三个环形图实现
  • 间隔实现,由于环形1和环形2是贴合的,所以没办法用设置border模拟间隔。这里采用添加数据,设置颜色transparent模拟间隔 缺点:
  • 隐藏图例至保留一个时,会留有一个间隔,如上图
  • 且占比需要手动计算,所以隐藏图例时不会重新生成占比,需要手动监听图例事件去重新计算占比。 主要代码:
const legendArr = [  { name: '图例1' },  { name: '图例2' },  { name: '图例3' }]
// 数据格式
const list = [  {"number":60,"areaName":"图例1"},  {"number":90,"areaName":"图例2"},  {"number":150,"areaName":"图例3"}]
// 转换后的数据
const data = []
if (list.length === 0) {
// 无数据
legendArr.forEach((item, i) => {
  data.push({
    name: item.name,
    value: 0,
    isRealData: true, // 标识,与装饰圆环做区分
    isRealIndex: i
  })
})
}
const total = list.reduce((a, b) => a + b.number, 0)
list.forEach((item, i) => {
data.push({
  name: item.areaName,
  value: item.number,
  isRealData: true, // 标识,与装饰圆环做区分
  isRealIndex: i
})
data.push({
  // 透明扇形作分割
  name: item.areaName,
  value: total / 50,
  labelLine: {
    show: false,
    lineStyle: {
      color: 'transparent'
    }
  },
  itemStyle: {
    color: 'transparent'
  }
})
})
const series = [{  // 外层装饰  type: 'pie',  emphasis: {    scale: false  },  center: ['50%', '40%'],
  radius: ['55%', '65%'],
  label: {
    show: false
  },
  itemStyle: {
    color: new this.$echarts.graphic.RadialGradient(0.5, 0.5, 1, [
      {
        offset: 0,
        color: 'rgba(17, 24, 43, 0)'
      },
      {
        offset: 0.5,
        color: 'rgba(0, 187, 255, 0.3)'
      },
      {
        offset: 1,
        color: 'rgba(17, 24, 43, 0)'
      }
    ], false)
  },
  data: [1]
},
{
  // 实际展示数据
  type: 'pie',
  emphasis: {
    scale: false
  },
  center: ['50%', '40%'],
  radius: ['40%', '48%'],
  label: {
    show: true,
    fontSize: 20,
    padding: [0, 40, 0, 0],
    formatter: params => {
      // 自定义的字段isRealData
      if (params.data?.isRealData) {
        return `
          {color${params.data.isRealIndex}|${this.getPercent(params.data.value, total)}}
          ${params.value}次 ${params.name}
        `
      }
      return ''
    },
    rich: {
      color0: {
        color: echartColors[0][0],
        fontSize: 20,
        lineHeight: 36
      },
      color1: {
        color: echartColors[1][0],
        fontSize: 20,
        lineHeight: 36
      },
      color2: {
        color: echartColors[1][0],
        fontSize: 20,
        lineHeight: 36
      }
    }
  },
  labelLine: {
    show: false,
    length: 0
  },
  data
},
{
  // 内层半透明
  type: 'pie',
  emphasis: {
    scale: false
  },
  center: ['50%', '40%'],
  radius: ['28%', '40%'],
  itemStyle: {
    color: (params) => {
      return params.dataIndex % 2 === 0 ? echartColors[params.dataIndex / 2][1] : 'transparent'
    }
  },
  label: {
    show: false
  },
  data
}
]
const options = {
color: echartColors.map(item => item[0]),
tooltip: {
  trigger: 'item',
  padding: 0,
  borderColor: 'transparent',
  formatter: params => {
    if (params.data?.isRealData) {
      return `
        <div style="
          margin: 0;
          padding: 5px;
          font-size: 20px;
        ">
          <div style="margin: 5px 0;">${params.name}</div>
          <div style="margin: 5px 0;">
            次数:
            <span style="color: ${echartColors[params.data.isRealIndex][0]};">${params.value}</span>
          </div>
          <div style="margin: 5px 0;">占比:${this.getPercent(params.value, total)}</div>
        </div>
      `
    }
    return ``
  },
  borderColor: 'rgba(255, 255, 255, 0.30196078431372547)',
  borderWidth: 2,
  backgroundColor: 'rgba(60, 61, 86, 1)',
  textStyle: {
    color: '#fff'
  }
},
legend: {
  bottom: '10%',
  icon: 'rect',
  itemGap: 40,
  textStyle: {
    color: '#fff',
    fontSize: 20
  }
},
grid: {
  left: 0,
  top: 60,
  right: 50,
  bottom: 45,
      containLabel: true                   
},
xAxis: [
  {
    show: false
  }
],
series
}
  1. 有间隔的环形图2,如图所示 image.png image.png

注意:

  • 两个环形间隔由border实现,只有背景色固定且不渐变不透明才能用这种方式,如果不是则用环形图1的形式实现
  • 这里占比之类就不用向环形图1那样手动计算并监听图例事件
/**
* 数据格式
* { 单位名称:次数 }
*/
const dataObj = {companyone: 60, companytwo: 15, companyfour: 10, companythree: 50}
const data = []
Object.keys(dataObj).forEach((name, i) => {
    data.push({
      name,
      value: dataObj[name],
      isRealData: true, // 标识,与装饰圆环做区分
      isRealIndex: i
    })
})
const series = [{  name: '入廊单位统计',  type: 'pie',  center: ['40%', '50%'],
  radius: ['60%', '68%'],
  label: {
    position: 'center',
    fontSize: 20,
    formatter: params => {
      // 自定义的字段isRealData
      if (params.data?.isRealData) {
        // return `{d|${getPercent(params.value, total)}}\n{c|${params.value}次}\n{b|${params.name}}`
        return `{d|${params.percent}%}\n{c|${params.value}次}\n{b|${params.name}}`
      }
      return ``
    },
    rich: {
      b: {
        fontSize: 18
      },
      c: {
        fontSize: 18,
        lineHeight: 28
      },
      d: {
        fontSize: 18,
        fontWeight: 'bold'
      }
    }
  },
  data: data.map((item, i) => {
    return {
      ...item,
      itemStyle: {
        color: item.isRealData ? new this.$echarts.graphic.LinearGradient(0, 0, 1, 0, [
          {
            offset: 0,
            color: echartColors[item.isRealIndex][0]
          },
          {
            offset: 1,
            color: echartColors[item.isRealIndex][1]
          }
        ]) : 'transparent',
        borderColor: 'rgba(20, 22, 44, 1)',
        borderWidth: 4
      }
    }
  })
},
{
  // 内层半透明
  type: 'pie',
  emphasis: {
    scale: false
  },
  center: ['40%', '50%'],
  radius: ['45%', '55%'],
  itemStyle: {
    color: 'rgba(54, 60, 69, 1)',
    borderColor: 'rgba(20, 22, 44, 1)',
    borderWidth: 4
  },
  label: {
    show: false
  },
  data: data
}
]
const options = {
color: echartColors.map(item => item[0]),
tooltip: {
  trigger: 'item',
  formatter: params => {
    if (params.data?.isRealData) {
      // ${getPercent(params.value, total)
      return `
        <div style="
          margin: 0;
          padding: 5px;
          font-size: 20px;
        ">
          <div style="margin: 5px 0;">${params.name}</div>
          <div style="margin: 5px 0;">
            次数:
            <span style="color: ${echartColors[params.data.isRealIndex][0]};">${params.value}</span>
          </div>
          <div style="margin: 5px 0;">占比:${params.percent}%</div>
        </div>
      `
    }
    return ``
  },
  // '{a} <br/>{b}: {c}次 ({d}%)',
  ...this.$utils.defaultTooltipParams
},
legend: {
  right: '0',
  top: 'middle',
  icon: 'rect',
  orient: 'vertical',
  itemGap: 40,
  textStyle: {
    color: '#fff'
  },
  formatter: name => {
    const obj = data.find(item => item.name === name)
    return `${name}  ${obj?.value || 0}次`
  }
},
series
}