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 } ] };