3/4环形图实现

  1. 通过循环数据,把每一条数据放入一个环形图内,每一个环形图分为3块空间:

    • 实际数据占据的空间

    这里占据的空间需要转换成3/4比例:value * 0.75

    • 虚拟的3/4环形图剩下的数据

    这里是占据3/4空间内除了实际数据之后剩余空间:(总数据-value) * 0.75

    • 1/4需要做成透明的数据

    始终占据1/4空间:总数 * 0.25,颜色设置为transparent透明色

  2. 利用y轴上显现旁边的注释。注意x轴也必须写!

    xAxis: [{ show: false }],
    yAxis: [
      {
     type: "category",
     inverse: true,
     axisLine: {
       show: false,
     },
     axisTick: {
       show: false,
     },
     axisLabel: {
     },
     data: lineYAxis,
      },
    ],

    效果图

优点:

通过这一系列计算保证了环形图数据量过大时不会溢出

缺点:

  • 环形图数据项不能过多,因为内圈最小就是0%。
  • 在缩放的时候放大基本没问题,缩小的时候会出现数据注释对应不上的问题。
    因为这里是grid定位,y轴label来显示数据,考虑给grid设置一个高度,但是这个高度应该随着环形图的半径来变化,而环形缩放的时候resize方法是按照盒子给定的最小宽或高来设置大小,用来保持为一个圆。所以不知道怎么取这个高度才能为最小...
    希望读者能解决这个问题,并评论补充!

js实现代码:

export default {
  data() {
    return {
      ectOpts: {},
      error: "",
      loading: false,
      latest: true,
      data: [],
    };
  },
  computed: {
    total() {
      let total = this.data.reduce((item1, item2) => {
        return (typeof item1 === "number" ? item1 : item1.num) + item2.num;
      });
      return total;
    },
  },
  created() {
    this.getData();
  },
  mounted() {
    this.initEchart();
  },
  methods: {
    getData() {
      this.data = [
        { name: "钱包支付", num: 13210 },
        { name: "现金支付", num: 42111 },
        { name: "记账支付", num: 81711 },
        { name: "移动支付", num: 121700 },
      ];
      this.data.forEach((item) => {
        item.percent = ((item.num / this.total) * 100).toFixed(1);
      });
    },
    initEchart() {
      let color = [
        "rgba(255, 135, 0, 1)",
        "rgba(255, 195, 0, 1)",
        "rgba(0, 228, 115, 1)",
        "rgba(0, 157, 255, 1)",
      ].reverse();
      let pieSeries = [];
      let lineYAxis = [];
      this.data.forEach((item, index) => {
        let iname = item.name;
        let inum = item.num;
        pieSeries.push({
          name: iname,
          type: "pie",
          radius: [65 - 15 * index + "%", 57 - 15 * index + "%"],
          // 关闭悬停动画
          hoverAnimation: false,
          // 是否顺时针旋转
          clockwise: false,
          center: ["35%", "50%"],
          label: {
            show: false,
          },
          data: [
            {
              // 只设置3/4的值,以用于3/4环形图
              value: inum * 0.75,
              name: iname,
              tooltip: {
                formatter: (item) => {
                  return `<div style="display:flex;font-size:12px;">
                        <div style="color:${item.color};margin-right:10px;">●</div>
                        <div>
                          <div>${item.seriesName}:${item.value} 辆</div>
                          <div>占比:${(item.percent / 0.75).toFixed(1) + "%"}</div>
                        </div>
                      </div>
                      `
                },
              }
            },
            {
              // 这里的值+上面的值为总和,但是只占比75%
              value: (this.total - inum) * 0.75,
              itemStyle: {
                color: "rgba(0, 132, 251, 0.2)",
              },
              tooltip: {
                show: false
              }
            },
            {
              // 弃用25%的环形图不做显示
              value: this.total * 0.25,
              itemStyle: {
                color: "rgba(0,0,0,0)",
              },
              tooltip: {
                show: false
              }
            },
          ],
        });
        lineYAxis.push({
          value: index,
          textStyle: {
            rich: {
              circle: {
                color: color[index],
                padding: [0, 5],
              },
            },
          },
        });
      });
      this.ectOpts = {
        tooltip: {
          trigger: "item",
        },
        color,
        grid: {
          top: "15%",
          bottom: "54%",
          left: "35%",
          containLabel: false,
        },
        // 有yAxis必须有xAxis
        xAxis: [{ show: false }],
        yAxis: [
          {
            type: "category",
            // 反向坐标轴
            inverse: true,
            axisLine: {
              show: false,
            },
            axisTick: {
              show: false,
            },
            axisLabel: {
              formatter: (params) => {
                let item = this.data[params];
                return `{line|----------}{circle|●}{name|${item.name}:}{value|${item.num}辆,}{percent|占${item.percent}%}`;
              },
              interval: 0,
              inside: true,
              rich: {
                line: {
                  // width: 50,
                  // height: 1,
                  color: "rgba(236, 236, 236, 1)",
                  // 当前echart版本不支持borderType用------代替
                  // borderType: "dashed",
                  // borderColor: "#D9DFEB",
                  // borderWidth: 1,
                },
              },
              textStyle: {
                color: "#fff",
                fontSize: 12,
              },
              show: true,
            },
            data: lineYAxis,
          },
        ],
        series: pieSeries,
      };
    },
  },
};
03-06 00:09