echarts 环形饼状图颜色渐变加自定义Legend效果

echarts饼状图 yekong

数据可视化大屏 项目开发中,要显示各种各种的饼状图效果,今天要实现的是环形饼状图,中间显示数字以及文字描述,并有颜色渐变背景效果。并添加自定义Legend,因为echarts自带的Legend自定义程度不高,所以这里使用html代码来实现。

效果图

echarts 环形饼状图颜色渐变加自定义Legend效果

演示实例

实现代码

<template>
  <div class="echartsBodys">
    <echarts1 title="人员资质" :total="total" :list="list" ref="echarts"></echarts1>
    <div class="list">
      <div class="listItem cur" @click="getChecked(index)" v-for="(item,index) in list" :key="index">
        <div class="listIteml">
          <div class="dot" :class="{disabled:!item.checked}"
               :style="'background: linear-gradient(80deg,'+item.color1+' 0%, '+item.color2+' 100%);'"></div>
          <span :class="{disabled:!item.checked}">{{ item.name }}</span>
        </div>
        <em class="num"
            v-if="item.checked"
            :style="'background: linear-gradient(0deg,'+item.color1+' 0%, '+item.color2+' 100%);-webkit-background-clip: text;-webkit-text-fill-color: transparent;'">{{
            item.value
          }}</em>
        <em class="num"
            v-else>{{
            item.value
          }}</em>
      </div>
    </div>
  </div>
</template>

<script>
import WOW from "wow.js";
import echarts1 from "./components/echarts.vue";

export default {
  name: "title",
  data() {
    return {
      list: [
        {
          name: '工食品签证官',
          value: 80,
          color1: 'rgba(252, 96, 93, 1)',
          color2: 'rgba(253, 173, 68, 1)',
          checked: true
        },
        {
          name: '植物源性食品现场查验资质',
          value: 70,
          color1: 'rgba(253, 168, 62, 1)',
          color2: 'rgba(254, 217, 82, 1)',
          checked: true
        },
        {
          name: '不合格原因3',
          value: 70,
          color1: 'rgba(47, 156, 252, 1)',
          color2: 'rgba(254, 221, 66, 1)',
          checked: true
        }]
    }
  },
  computed: {
    total: function () {
      var total = 0
      this.list.forEach((type) => {
        total += type.value
      });
      return total
    }
  },
  components: {echarts1},
  props: {
    title: {
      type: String,
      default() {
        return '';
      }
    },
    icon: {
      type: String,
      default() {
        return '';
      }
    },
  },
  watch: {},
  mounted() {
    var that = this;
    var wow = new WOW({
      boxClass: "wow", // animated element css class (default is wow)
      animateClass: "animated", // animation css class (default is animated)
      offset: 0, // distance to the element when triggering the animation (default is 0)
      mobile: true, // trigger animations on mobile devices (default is true)
      live: true, // act on asynchronously loaded content (default is true)
      callback: function (box) {
        // the callback is fired every time an animation is started
        // the argument that is passed in is the DOM node being animated
      },
      scrollContainer: null, // optional scroll container selector, otherwise use window,
      resetAnimation: true, // reset animation on end (default is true)
    });
    wow.init();
  },
  methods: {
    getChecked(index) {
      this.list[index].checked = !this.list[index].checked
      this.$refs.echarts.drawEcharts()
    }
  },
}
</script>

<style lang="scss" scoped>
.list {
  margin-left: 0px;
  position: relative;
  width: 50%;
  height: calc(100% - 10px);
  //background: url("./assets/jiaobiaobg.png") no-repeat;
  //background-size: 100% 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: nowrap;
  flex-direction: column;
  align-content: flex-start;

  .listItem {
    font-size: 14px;
    display: flex;
    height: 30%;
    width: calc(100% - 20px);
    margin: 0 auto;
    justify-content: space-between;
    align-items: center;
    flex-wrap: nowrap;
    flex-direction: row;
    align-content: flex-start;

    .listIteml {
      display: flex;
      justify-content: flex-start;
      align-items: center;
      flex-wrap: nowrap;
      flex-direction: row;
      align-content: flex-start;
      font-size: 14px;
      font-family: MicrosoftYaHei;
      font-weight: 400;
      color: #FFFFFF;
    }

    span {
      font-size: 14px;
      font-family: PingFang SC-Regular, PingFang SC;
      font-weight: 400;
      color: #E0F9FF;
      line-height: 20px;
    }

    .dot {
      width: 8px;
      height: 8px;
      margin-right: 10px;
      flex-shrink: 0;
    }

    .dot.disabled {
      background: rgba(#999, 0.8) !important;
    }

    span.disabled {
      color: rgba(#999, 0.8) !important;
    }

    .num {
      font-size: 22px;
      font-family: DIN;
      font-weight: normal;
      color: #FFFFFF;
      line-height: 20px;
      background: linear-gradient(0deg, rgba(#999, 0.8) 0.1220703125%, rgba(#999, 0.8) 100%);
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
    }
  }
}

.echartsBodys {
  width: 100%;
  position: relative;
  height: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: nowrap;
  flex-direction: row;
  align-content: flex-start;
}
</style>

组件代码

<template>
  <div class="echartsBodys">
    <echarts1 title="人员资质" :total="total" :list="list" ref="echarts"></echarts1>
    <div class="list">
      <div class="listItem cur" @click="getChecked(index)" v-for="(item,index) in list" :key="index">
        <div class="listIteml">
          <div class="dot" :class="{disabled:!item.checked}"
               :style="'background: linear-gradient(80deg,'+item.color1+' 0%, '+item.color2+' 100%);'"></div>
          <span :class="{disabled:!item.checked}">{{ item.name }}</span>
        </div>
        <em class="num"
            v-if="item.checked"
            :style="'background: linear-gradient(0deg,'+item.color1+' 0%, '+item.color2+' 100%);-webkit-background-clip: text;-webkit-text-fill-color: transparent;'">{{
            item.value
          }}</em>
        <em class="num"
            v-else>{{
            item.value
          }}</em>
      </div>
    </div>
  </div>
</template>

<script>
import WOW from "wow.js";
import echarts1 from "./components/echarts.vue";

export default {
  name: "title",
  data() {
    return {
      list: [
        {
          name: '工食品签证官',
          value: 80,
          color1: 'rgba(252, 96, 93, 1)',
          color2: 'rgba(253, 173, 68, 1)',
          checked: true
        },
        {
          name: '植物源性食品现场查验资质',
          value: 70,
          color1: 'rgba(253, 168, 62, 1)',
          color2: 'rgba(254, 217, 82, 1)',
          checked: true
        },
        {
          name: '不合格原因3',
          value: 70,
          color1: 'rgba(47, 156, 252, 1)',
          color2: 'rgba(254, 221, 66, 1)',
          checked: true
        }]
    }
  },
  computed: {
    total: function () {
      var total = 0
      this.list.forEach((type) => {
        total += type.value
      });
      return total
    }
  },
  components: {echarts1},
  props: {
    title: {
      type: String,
      default() {
        return '';
      }
    },
    icon: {
      type: String,
      default() {
        return '';
      }
    },
  },
  watch: {},
  mounted() {
    var that = this;
    var wow = new WOW({
      boxClass: "wow", // animated element css class (default is wow)
      animateClass: "animated", // animation css class (default is animated)
      offset: 0, // distance to the element when triggering the animation (default is 0)
      mobile: true, // trigger animations on mobile devices (default is true)
      live: true, // act on asynchronously loaded content (default is true)
      callback: function (box) {
        // the callback is fired every time an animation is started
        // the argument that is passed in is the DOM node being animated
      },
      scrollContainer: null, // optional scroll container selector, otherwise use window,
      resetAnimation: true, // reset animation on end (default is true)
    });
    wow.init();
  },
  methods: {
    getChecked(index) {
      this.list[index].checked = !this.list[index].checked
      this.$refs.echarts.drawEcharts()
    }
  },
}
</script>

<style lang="scss" scoped>
.list {
  margin-left: 0px;
  position: relative;
  width: 50%;
  height: calc(100% - 10px);
  //background: url("./assets/jiaobiaobg.png") no-repeat;
  //background-size: 100% 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: nowrap;
  flex-direction: column;
  align-content: flex-start;

  .listItem {
    font-size: 14px;
    display: flex;
    height: 30%;
    width: calc(100% - 20px);
    margin: 0 auto;
    justify-content: space-between;
    align-items: center;
    flex-wrap: nowrap;
    flex-direction: row;
    align-content: flex-start;

    .listIteml {
      display: flex;
      justify-content: flex-start;
      align-items: center;
      flex-wrap: nowrap;
      flex-direction: row;
      align-content: flex-start;
      font-size: 14px;
      font-family: MicrosoftYaHei;
      font-weight: 400;
      color: #FFFFFF;
    }

    span {
      font-size: 14px;
      font-family: PingFang SC-Regular, PingFang SC;
      font-weight: 400;
      color: #E0F9FF;
      line-height: 20px;
    }

    .dot {
      width: 8px;
      height: 8px;
      margin-right: 10px;
      flex-shrink: 0;
    }

    .dot.disabled {
      background: rgba(#999, 0.8) !important;
    }

    span.disabled {
      color: rgba(#999, 0.8) !important;
    }

    .num {
      font-size: 22px;
      font-family: DIN;
      font-weight: normal;
      color: #FFFFFF;
      line-height: 20px;
      background: linear-gradient(0deg, rgba(#999, 0.8) 0.1220703125%, rgba(#999, 0.8) 100%);
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
    }
  }
}

.echartsBodys {
  width: 100%;
  position: relative;
  height: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: nowrap;
  flex-direction: row;
  align-content: flex-start;
}
</style>

效果在项目中的应用

vue3 可视化数据大屏 - 进口食品安全智慧监管决策大屏

喜欢