const dataList = [ { name: '网络设备', value: 50 }, { name: '非网管设备', value: 50 }, { name: '终端设备', value: 50 }, { name: '监控设备', value: 50 }, { name: '其他设备', value: 50 } ] let angle = 0 const colors = [ { darkColor: '#eebd4c59', lightColor: '#eebd4c' }, { darkColor: '#5d8ffc59', lightColor: '#5d8ffc' }, { darkColor: '#5fbfc559', lightColor: '#5fbfc5' }, { darkColor: '#ee554c59', lightColor: '#ee554c' }, { darkColor: '#ee4cc259', lightColor: '#ee4cc2' }, { darkColor: '#5cee4c59', lightColor: '#5cee4c' } ] const getCirclePoint = function(x0, y0, r, angle) { const x1 = x0 + r * Math.cos((angle * Math.PI) / 180) const y1 = y0 + r * Math.sin((angle * Math.PI) / 180) return { x: x1, y: y1 } } const data1 = dataList.map((v, i) => { return { ...v, itemStyle: { color: colors[i].lightColor } } }) const data2 = dataList.map((v, i) => { return { ...v, itemStyle: { color: colors[i].darkColor } } }) let sum = 0 dataList.forEach(v => { sum += v.value }) option = { backgroundColor: '#000', tooltip: { show: false, trigger: 'item' }, legend: { orient: 'vertical', top: 'center', left: '75%', itemWidth: 10, itemHeight: 10, itemGap: 20, formatter: function(name) { const res = dataList.filter(n => { return n.name === name }) if (!res.length) return return `${name} ${res[0].value} ${res[0].value ? ((res[0].value / sum) * 100).toFixed(0) : 0}%` }, textStyle: { fontSize: 12, color: '#c8dbfd', fontWeight: 100 }, selectedMode: false }, series: [ { name: '总报警', type: 'pie', center: ['40%', '50%'], radius: ['25%', '48%'], avoidLabelOverlap: false, hoverAnimation: false, label: { show: false, formatter: '({d}%)' }, emphasis: { label: { show: false, fontSize: 12, fontWeight: 'bold' } }, labelLine: { length: 4, length2: 4 }, data: data1 }, { name: '总报警', type: 'pie', center: ['40%', '50%'], radius: ['19%', '25%'], avoidLabelOverlap: false, hoverAnimation: false, silent: true, label: { show: false, formatter: '({d}%)' }, emphasis: { label: { show: false, fontSize: 13, fontWeight: 'bold' } }, data: data2 }, { type: 'custom', coordinateSystem: 'none', silent: true, data: [0], renderItem(params, api) { // 环形图半径 const r = Math.min(api.getWidth(), api.getHeight()) / 2 // 圆心 const center = { x: api.getWidth() * 0.4, y: api.getHeight() / 2 } // 大圆半径 const rBig = r * 0.75 // 小圆半径 const rSmall = r * 0.63 // 大圆上的扇形 const bigSector = [] const smallSector = [] const circleOnCircle = [] // 小圆上携带的小圆圈 const sectorSize = 60 // 扇形长度(弧度) const sectorInterval = 30 // 扇形与扇形之间的间隔 const BigStartAngle = 310 // 大扇形起始角度 for (let i = 0; i < 4; i++) { const startAngle = ((i * (sectorInterval + sectorSize) + BigStartAngle) * Math.PI) / 180 const endAngle = startAngle + (sectorSize * Math.PI) / 180 const smallStartAngle = (Math.PI / 180) * (280 + angle + i * (sectorSize + sectorInterval)) const smallEndAngle = smallStartAngle + (sectorSize * Math.PI) / 180 bigSector.push({ type: 'sector', shape: { cx: center.x, cy: center.y, r: rBig, r0: rBig * 0.93, startAngle, endAngle }, style: { fill: '#234d94', lineWidth: 1 } }) smallSector.push({ type: 'sector', shape: { cx: center.x, cy: center.y, r: rSmall * 0.93, r0: rSmall * 0.87, startAngle: smallStartAngle, endAngle: smallEndAngle }, style: { fill: '#403727', lineWidth: 2 } }) circleOnCircle.push({ type: 'circle', shape: { cx: getCirclePoint(center.x, center.y, rSmall, 270 + i * 90 - angle).x, cy: getCirclePoint(center.x, center.y, rSmall, 270 + i * 90 - angle).y, r: 3 }, style: { fill: '#1e417f', stroke: '#1e417f', lineWidth: 1 } }) } return { type: 'group', children: [ { type: 'group', children: [ ...bigSector, { // 外圆环 type: 'arc', shape: { cx: center.x, cy: center.y, r: rBig }, style: { fill: 'transparent', stroke: '#5d8ffc', lineWidth: 2 } } ] }, { // 内圆环 type: 'group', children: [ ...smallSector, ...circleOnCircle, { // 内圆 type: 'arc', shape: { cx: center.x, cy: center.y, r: rSmall }, style: { fill: 'transparent', stroke: '#1e417f', lineWidth: 2 } } ] } ] } } } ] } function play() { angle += 3 myChart.setOption(option, true) } setTimeout(() => { setInterval(() => { // play() requestAnimationFrame(play) }, 50) }, 1000)