动态圆环

描述:当前是关于Echarts图表中的 饼图 示例。
 
            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)