利用echarts实现四分之三环形弧(弄懂了这个原理,半圆弧形或其他弧形也就很容易实现了)

424 阅读1分钟

1.场景:UI设计给了四分之三环形弧百分比标注

之前开发用的是都是echarts完成的环形弧,接到需求后看了echarts文档也没找到相关的属性配置,后来查了很多资料,找到了解决方法。

截图2022839132.png

2.实现方式

处理传给echart的数据

将数据处理成三部分

1.隐藏的部分占25%,将其设置为透明色,就是那个没显示的部分。

2.将完成的数据乘以75%(就是蓝色的环形部分)。

3.灰色的部分用100减去前面两部分。

const dealOption = val => {
      let rate = (val.rate * 0.75).toFixed(2);
      return [
        {
          value: rate,
          originRate: val.rate,
          name: "",
          itemStyle: {
            color: {
              type: "linear",
              x: 0,
              y: 0,
              x2: 1,
              y2: 1,
              colorStops: [
                {
                  offset: 0,
                  color: "#90C9FF" // 0% 处的颜色
                },
                {
                  offset: 1,
                  color: "#549BFF" // 100% 处的颜色
                }
              ],
              globalCoord: true // 缺省为 false
            }
          }
        },
        {
          value: 75 - rate,
          name: "",
          itemStyle: {
            color: "#EAEFF5"
          }
        },
        {
          value: 25,
          name: "",
          itemStyle: {
            color: "transparent"
          }
        }
      ];
    };
    

echart组件代码

<template>
  <div class="percentPieChart">
    <div class="charCradContainer">
      <div class="cont" ref="contRef">
        <div class="empty" v-if="!option.length">
          <span>暂无数据</span>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import * as echarts from "echarts";
import { defineComponent, toRefs, reactive, watch } from "@vue/composition-api";
export default defineComponent({
  name: "percentPieChart",
  props: {
    title: {
      type: String,
      default: ""
    },
    option: {
      default: () => [],
      type: Array
    },
    count: {
      type: String,
      default: ""
    },
    info: {
      type: String,
      default: ""
    }
  },
  setup(props, { refs, root }) {
    const state = reactive({
      myChart: null
    });
    const innerOption = () => {
      if (props.option.length && !state.myChart) {
        // 基于准备好的dom,初始化echarts实例
        state.myChart = echarts.init(refs.contRef);
        const option = {
          title: {
            text: `{a|${props.option[0].originRate}}{b|%}\n{c|评审通过率}`,
            x: "center",
            y: "center",
            subtext: "",
            textStyle: {
              color: "#1496FF",
              rich: {
                a: {
                  fontSize: 27,
                  fontWeight: 700
                },
                b: {
                  fontSize: 16,
                  fontWeight: 700
                },
                c: {
                  fontSize: 12,
                  fontWeight: 500,
                  marginTop: 4
                }
              }
            }
          },
          itemStyle: {
            borderRadius: 15
          },
          series: [
            {
              name: props.title,
              type: "pie",
              radius: ["88%", "100%"],
              center: ["50%", "50%"],
              startAngle: 225,
              avoidLabelOverlap: false,
              labelLine: {
                normal: {
                  show: false
                }
              },
              data: props.option
            }
          ]
        };
        // 使用刚指定的配置项和数据显示图表。
        state.myChart.setOption(option);
      } else if (state.myChart) {
        state.myChart.setOption({
          title: {
            text: `${props.option[0].value / 0.75}%`
          },
          series: [
            {
              // 根据名字对应到相应的系列
              name: props.title,
              data: props.option
            }
          ]
        });
      }
    };
    watch(
      () => props.option,
      () => {
        if (props.option.length) {
          root.$nextTick(() => {
            innerOption();
          });
        }
      },
      {
        immediate: true,
        deep: true
      }
    );

    return {
      ...toRefs(state),
      innerOption
    };
  }
});
</script>
<style lang="less" scoped>
@w: 7.5vw;
.percentPieChart {
  width: (230 / @w);
  height: (230 / @w);
  background: #f6f8fc;
  margin: auto;
  .undergraduateCharCardTitle {
    padding-left: 0.4667rem;
    font-size: 0.4267rem;
    color: #32220e;
    font-weight: 600;
    line-height: 1.0667rem;
    border-bottom: 1px solid #e5e5e5;
    position: relative;
    .iconR {
      top: 0;
      bottom: 0;
      right: 0;
      position: absolute;
      width: 40px;
    }
    .iconR::before {
      content: "";
      position: absolute;
      background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAZBAMAAADztQLBAAAAGFBMVEUAAADAwMDAwMDCwsLb29vCwsK/v7/AwMBEhVBFAAAACHRSTlMA/YRTB084jrNSCvUAAAApSURBVAjXY2BhgIBABQidKAShmQWhAoZUECgUgfGh8uRzE4VQ3AtzPwCJ4gZ269ouTwAAAABJRU5ErkJggg==");
      background-size: cover;
      background-repeat: no-repeat;
      background-position: center;
      width: 0.2133rem;
      height: 0.3467rem;
      right: 0.2667rem;
      top: 0;
      bottom: 0;
      margin: auto;
    }
  }
  .charCradContainer {
    position: relative;
    width: 100%;
    height: 100%;
    .cont {
      width: 100%;
      height: 100%;
    }
    .contEmpty {
      height: 0;
    }
  }
  .empty {
    background: #fff;
    margin: auto;
    padding-top: 20px;
    padding-bottom: 20px;
    width: 100%;
    font-size: 14px;
    color: #929194;
    text-align: center;
    span {
      line-height: 30/75rem;
    }
    img {
      display: block;
      margin: 0 auto;
      width: 24%;
      height: 24%;
    }
  }
}
</style>