⭕小小的环形标识,不用Echarts如何实现?

405 阅读3分钟

环形统计图的话,大家第一反应应该是使用Echarts来实现,Echarts配置丰富,示例众多,而且现在也支持按需引入,可以减少打包后的体积。但是如果需求是在卡片或者表格中,作为一个图标形式来展示的话,这种情况下,一个页面中,可能会展示很多个,使用Echarts的话,可能就不是那么好了。

1. SVG

SVG应该是大家很容易想到的实现方式,这是因为我们平常所用的组件库中,有一个组件:环形进度条,看起来很像我们想要的效果,它就是用SVG来实现的。Arco Design中的迷你进度条,就更像了:

image.png
如果项目有使用组件库的话,并且环形标识中只展示2项,只需要把环形进度条的样式稍微改下,就能满足要求;如果超过2项的话,我们就得仿照环形进度条实现一个组件了。

F12看下环形进度条包含哪些元素、哪些属性:

image.png
从图中可以看出,只用到了circle元素。进度条是由一个表示背景的环,加一个表示进度的环,两个都是circle

  • stroke-dasharray: 定义了用于绘制形状轮廓的虚线段和间隙的排列形式,此处是周长:2 * Math.PI * 6(r = 6)
  • stroke-dashoffset: 定义了虚线与路径起点之间的偏移量,此处偏移80%(2*Math.PI*6*0.8),展示的就是20%

基于这种实现,需要展示几项,就用几个circle表示就可以了,只需要计算出每个circlestroke-dashoffset就行了:

<template>
  <svg view-box="0 0 16 16" class="circle-svg">
    <circle
      v-for="(offset, index) in offsetArr"
      :key="index"
      fill="none"
      cx="8"
      cy="8"
      r="6"
      stroke-width="4"
      :stroke="COLORS[index % 4]"
      :stroke-dasharray="length"
      :stroke-dashoffset="offset"
    ></circle>
  </svg>
</template>

<script setup lang="ts">
import { computed, PropType, ref } from 'vue'

const COLORS = ['#165dff', '#ff7d00', '#f53f3f', '#00b42a'].reverse()

defineOptions({ name: 'RingIcon' })
const props = defineProps({
  percents: { type: Array as PropType<number[]>, required: true },
})
const percentArr = ref([0.3, 0.4, 0.2, 0.1])
const length = Math.round(2 * Math.PI * 6 * 10000) / 10000

let sum = 0
const offsetArr = computed(() => {
  return props.percents
    .map(item => {
      sum += item
      return Math.round(length * (1 - sum) * 10000) / 10000
    })
    .reverse()
})
</script>

<style lang="less" scoped>
.circle-svg {
  transform: rotate(-90deg);
  width: 1em;
  height: 1em;
}
</style>

image.png

  • 优点:矢量图形,清晰不失真
  • 缺点:多项的话,看起来就没那么圆了,锯齿看起来也会严重些

2. CSS

线性渐变和径向渐变,大家应该都很熟悉,其实还有一种渐变:锥形渐变 conic-gradient()

CSS 函数 conic-gradient()  创建一个由渐变组成的图像,渐变的颜色围绕一个中心点旋转(而不是从中心辐射)进行过渡。锥形渐变的例子包括饼图和色轮。conic-gradient() 函数的结果是 <gradient> 数据类型的对象,此对象是一种特殊的 <image> 数据类型。

image.png
可以实现饼图,那环形图自然也可以,中间区域加一个遮罩就可以了:

  • 优点:非常简单,几行CSS就能搞定
  • 缺点:锯齿比较严重,尤其环形比较小和某段环形角度比较小时

总结

SVG和CSS都可以实现饼图和环形图,根据需求选择合适的实现方式,你学废了吗?