双层饼图外层透明

描述:当前是关于Echarts图表中的 饼图 示例。
 
            const sourceData = [
   {
      name: '省部级',
      value: 380,
      color: "#00ff75"
   },
   {
      name: '校级',
      value: 800,
      color: "#0783ff"
   },
   {
      name: '市厅级',
      value: 200,
      color: "#ffc100"
   },
];
const total = sourceData.reduce((num, item) => {
   num += item.value
   return num
}, 0);
// 内环间隔距离
const inSplitWidth = 3;
// 为了实现内环间隔距离,需要额外插入的数值。200 只是个系数,值越大,单位间隔的距离越小。
const inSplitValue = Math.floor(total / (100 / inSplitWidth));
// 外环间隔比内环间隔大的值
const itemSplitWidth = 2;
// 外环间隔距离
const outSplitWidth = inSplitWidth + itemSplitWidth;
// 为了实现外环间隔距离,需要额外插入的数值。
const outSplitValue = Math.floor(total / (150 / outSplitWidth));
// 内环数据的总数
const valueTotal = total + inSplitValue * sourceData.length;
function getTextAngle(currentAngle, angle) {
   currentAngle = currentAngle + angle
   if (currentAngle <= 90) {
      return -currentAngle;
   } else if (currentAngle <= 180 && currentAngle > 90) {
      return 180 - currentAngle;
   } else if (currentAngle < 270 && currentAngle > 180) {
      return 180 - currentAngle;
   } else if (currentAngle < 360 && currentAngle >= 270) {
      return 360 - currentAngle;
   }
};
// 内环数据。在原数据的后面添加间隔数据(间隔块设置颜色透明)
const valueData = sourceData.reduce((arr, item) => {
   const currentTotal = arr.reduce((total, item) => {
      total += item.value
      return total
   }, 0)
   const currentAngle = 360 * (currentTotal / valueTotal)
   const angle = 360 * (item.value / valueTotal) / 2
   arr.push({
      name: item.name,
      value: item.value,
      itemStyle: {
         color: item.color
      },
      label: {
         lineHeight: 80,
         rotate: getTextAngle(currentAngle, angle)
      }
   }, {
      name: '',
      value: inSplitValue,
      itemStyle: {
         color: 'transparent',
         opacity: 0
      },
      label: {
         show: false
      },
      labelLine: {
         show: false
      }
   })
   return arr
}, []);
// 原数据需要减去的值(外环每块的数据都要比原数据少一点才能达到外环嵌在内环的效果)
const itemReduced = outSplitValue - inSplitValue
// 外环数据
const outValueData = sourceData.reduce((arr, item, index) => {
   arr.push(
      {
         name: item.name,
         value: item.value - itemReduced,
         itemStyle: {
            color: item.color
         },
         label: { color: item.color }
      },
      {
         name: '',
         value: outSplitValue,
         itemStyle: {
            color: 'transparent',
            opacity: 0
         },
         label: {
            show: false
         },
         labelLine: {
            show: false
         }
      })
   return arr
}, []);
option = {
   backgroundColor: '#031d33',
   tooltip: {
      show: true
   },
   series: [
      {
         type: 'pie',
         label: {
            show: false,
         },
         labelLine: {
            show: false,
         },
         radius: ['35%', '45%'],
         data: valueData,
      },
      {
         type: 'pie',
         startAngle: -360 * (itemReduced / 2 / valueTotal) + 90,
         radius: ['35%', '65%'],
         itemStyle: {
            opacity: 0.3,
         },
         label: {
            show: true,
            formatter(params) {
               return `{percent|${params.value}}\n{name|${params.name}}`
            },
            rich: {
               name: {
                  color: "#ccc",
                  fontSize: 20,
                  padding: [0, 0],
                  align: "center"
               },
               percent: {
                  align: "center",
                  fontSize: 26,
                  padding: [0, 0]
               },
            },
            color: "#FFF",
            opacity: 1,
         },
         labelLine: {
            show: true,
            length: 40, // 第一根标识线的长度
            length2: 50, // 拐弯后标识线的长度
            lineStyle: {
               width: 1,
            }
            // lineStyle: {
            //   color: "red", // 标识线颜色
            //   width: 2, // 标识线宽度
            // }
         },
         data: outValueData
      }
   ]
};