Echarts圆环图实现进度条末尾带一个方块的效果


效果这样
直接上代码吧

<template>
  <div ref="chartDom" style="width: 260px; height: 460px; background-color: white"></div>
</template>

<script setup lang="ts">
// import { useI18n } from 'vue-i18n'
// import { useQuasar } from 'quasar'
import * as echarts from 'echarts'
import { computed, nextTick, onMounted, ref, useTemplateRef } from 'vue'

// const { t } = useI18n()
const chartDom = useTemplateRef('chartDom')
let chartInstance: echarts.ECharts | null = null
let data = 0
const domHeight = ref(0)
const domWidth = ref(0)
const blockHeight = ref(4) // 小白块长度
const blockWidth = ref(50) // 小白块宽度 (比下面那个加2就行)
const progressWidth = ref(48)
const name = ref('示例数据')
const radius = computed(
  () => ((domHeight.value > domWidth.value ? domWidth.value : domHeight.value) * 0.75) / 2,
) // 图形的半径
const pi = Math.PI // ≈3.141592653589793

onMounted(async () => {
  await nextTick()
  chartInstance = echarts.init(chartDom.value)
  if (!chartDom.value) {
    console.error('Chart DOM element is not available')
    return
  }
  domHeight.value = chartInstance.getHeight()
  domWidth.value = chartInstance.getWidth()
  const option: echarts.EChartsOption = {
    series: [
      {
        type: 'gauge',
        center: ['50%', '60%'],
        startAngle: 180,
        endAngle: 0,
        min: 0,
        max: 100,
        splitNumber: 1,
        itemStyle: {
          color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
            { offset: 1, color: '#ffffff' }, // 渐变色的开始颜色
            { offset: 0, color: '#f7b733' }, // 渐变色的结束颜色
          ]),
        },
        progress: {
          show: true,
          width: progressWidth.value,
        },
        pointer: {
          show: false,
        },
        axisLine: {
          lineStyle: {
            width: progressWidth.value,
          },
        },
        axisTick: {
          distance: 0,
          splitNumber: 5,
          lineStyle: {
            width: 2,
            color: '#999',
          },
          show: false,
        },
        splitLine: {
          distance: -52,
          show: false,
          length: 14,
          lineStyle: {
            width: 3,
            color: '#999',
          },
        },
        axisLabel: {
          distance: 40,
          padding: [10, -5, 0, 0],
          height: 40,
          width: 20,
          color: '#999',
          fontSize: 12,
          lineHeight: 56,
          rich: {
            a: {
              // 没有设置 `lineHeight`,则 `lineHeight` 为 56
            },
          },
        },
        anchor: {
          show: false,
        },
        title: {
          show: true,
          color: '#999',
          fontSize: 10,
          offsetCenter: [0, 15],
        },
        detail: {
          valueAnimation: true,
          width: '20%',
          lineHeight: 40,
          borderRadius: 8,
          offsetCenter: [0, '-6%'],
          fontSize: 18,
          fontWeight: 'bolder',
          formatter: '{value}%',
          color: 'black',
        }, //百分比那一行的
        data: [
          {
            name: name.value,
            value: data,
          },
        ], //title那里的显示name是在这里,百分比值也是这个value来决定的
      },
    ],
    graphic: [
      {
        id: 'endBlock',
        type: 'rect',

        shape: {
          width: blockWidth.value,
          height: blockHeight.value,
          r: [2, 2, 2, 2],
        }, //长宽
        zlevel: 100,
        style: {
          fill: '#FFFFFF',
          shadowColor: '#999999',
          shadowBlur: 2,
        },
        originX: radius.value + 1,
        originY: 0,
        // position: [19, 95], // 初始占位坐标
        x: (domWidth.value - radius.value * 2) / 2 - (blockWidth.value % 2 != 0 ? 0 : 1),
        y: domHeight.value * 0.6, //因为上面center那里Y轴是在60%,需要自己调整
        transition: ['rotation'],
        rotation: 0,
      },
    ],
  }
  chartInstance.setOption(option)
  chartInstance.setOption({
    series: [
      {
        data: [
          {
            name: name.value,
            value: data,
          },
        ],
      },
    ],
    graphic: [
      {
        id: 'endBlock',
        rotation: 0, // 方向修正
      },
    ],
  })
  setInterval(function () {
    data = +(Math.random() * 60).toFixed(2)
    if (chartInstance) {
      chartInstance.setOption({
        series: [
          {
            data: [
              {
                name: name.value,
                value: data,
              },
            ],
          },
        ],
        graphic: [
          {
            id: 'endBlock',
            rotation: -((data / 100) * pi) - 0.01, // 方向修正
          },
        ],
      })
    }
  }, 2000)
})
</script>

setOptions第二次是因为要处理白块跟进度条初始化时不同步的问题,echarts我不是特别熟,不知道有没有别的办法。只能用笨方法了
翻echarts官方没找到特别相符的,百度也只找到了那种圆球实现,如果有更好的实现也麻烦评论区回复一下,感谢

posted @ 2025-03-10 21:26  Pkernel  阅读(207)  评论(0)    收藏  举报