1、echarts.js
将饼图封装成一个组件

<template>
  <!-- 每一个图表都有自己唯一的id,所有需要动态传入。 -->
  <div
    :id="id"
    :style="style"/>
</template>
<script>
import echarts from 'echarts'
// 引入 echarts 主模块。
export * from 'echarts/src/echarts'
// 引入饼图。
import 'echarts/src/chart/pie'
export default {
  props: {
    id: {
      type: String,
      default: ''
    },
    width: {
      type: String,
      default: '100%'
    },
    height: {
      type: String,
      default: ''
    },
    chartData: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {
      MyEcharts: '' // echarts实例
    }
  },
  computed: {
    style() {
      return {
        height: '300px',
        width: '100%'
        //可以使用父组件传递过来的值   height width
        //height:this.height,
        //width:this.width
      }
    },
    optionData() {
      return this.chartData
    }
  },
  mounted() {
    this.InitCharts()
  },
  methods: {
    InitCharts() {
      this.MyEcharts = echarts.init(document.getElementById(this.id))
      this.MyEcharts.clear() // 适用于大数据量的切换时图表绘制错误,先清空在重绘
      console.log(this.optionData, '传入的值item')
      if (this.optionData) {
        var options = {
          name: this.optionData.columnName,//统计表格列的表头名
          data: []
        }
        options.data = this.optionData.countObjects.map(item => {
          return { name: item.name, value: item.count }
        })
        const nameArr = options.data.map(item => {
          return item.name
        })
        const setChart = this.drawChart(options, nameArr)
        console.log(setChart, '图表配置数据')
        this.MyEcharts.setOption(setChart, true) // 设置为true可以是图表切换数据时重新渲染
      }
      //  以下这种方法,当一个页面有多个图表时,会有一个bug那就是只有一个图表会随着窗口大小变化而变化,解决办法。
      // window.onresize = () => {
      //   this.MyEcharts.resize()
      // }
      // 当窗口变化时随浏览器大小而改变
      // 以下为上边的bug的解决方案。以后用这种方案,放弃上一种。
      const _this = this
      window.addEventListener('resize', function() {
        _this.MyEcharts.resize()
      })
    },
    drawChart(options, nameArr) {
      const option = {
        // 图标的标题   
        title: {
          text: this.getName(this.optionData.columnName),//需要过滤显示  不然显示的是表格列的字段名
          subtext: '统计图',
          // x 设置水平安放位置,默认左对齐,可选值:'center' ¦ 'left' ¦ 'right' ¦ {number}(x坐标,单位px)
          x: 'center',
          // y 设置垂直安放位置,默认全图顶端,可选值:'top' ¦ 'bottom' ¦ 'center' ¦ {number}(y坐标,单位px)
          y: 'top',
          // itemGap设置主副标题纵向间隔,单位px,默认为10,
          itemGap: 20,
          // backgroundColor: '#EEE',标题背景颜色
          // 主标题文本样式设置
          textStyle: {
            fontSize: 18,
            fontWeight: 'bolder',
            color: '#49ADF4'
          },
          // 副标题文本样式设置
          subtextStyle: {
            fontSize: 14,
            color: '#8B2323'
          }
        },
        // // 图例   本例中未使用
        // legend: {
        //   // orient 设置布局方式,默认水平布局,可选值:'horizontal'(水平) ¦ 'vertical'(垂直)
        //   orient: 'vertical',
        //   // x 设置水平安放位置,默认全图居中,可选值:'center' ¦ 'left' ¦ 'right' ¦ {number}(x坐标,单位px)
        //   x: 'left',
        //   // y 设置垂直安放位置,默认全图顶端,可选值:'top' ¦ 'bottom' ¦ 'center' ¦ {number}(y坐标,单位px)
        //   y: 'center',
        //   itemWidth: 24, // 设置图例图形的宽
        //   itemHeight: 18, // 设置图例图形的高
        //   textStyle: {
        //     color: '#666' // 图例文字颜色
        //   },
        //   // itemGap设置各个item之间的间隔,单位px,默认为10,横向布局时为水平间隔,纵向布局时为纵向间隔
        //   itemGap: 30,
        //   backgroundColor: '#eee', // 设置整个图例区域背景颜色
        //   data: nameArr
        // },
        // 鼠标悬浮提示框
        tooltip: {
          // trigger 设置触发类型,默认数据触发,可选值:'item' ¦ 'axis'
          trigger: 'item',
          showDelay: 20, // 显示延迟,添加显示延迟可以避免频繁切换,单位ms
          hideDelay: 20, // 隐藏延迟,单位ms
          backgroundColor: 'rgba(255,0,0,0.7)', // 提示框背景颜色
          textStyle: {
            fontSize: '16px',
            color: '#000' // 设置文本颜色 默认#FFF
          },
           position: 'inside', //设置提示框位置位于鼠标所在图形的内部中心位置
          /* 这种方法只在设置  只有在 trigger: 'item' 的时候才有效
            'inside'  鼠标所在图形的内部中心位置
            'top'  鼠标所在图形上侧
            'left'  鼠标所在图形左侧
            'right'  鼠标所在图形右侧
            'bottom'  鼠标所在图形底侧
          */
          // formatter设置提示框显示内容
          // {a}指series.name  {b}指series.data的name
          // {c}指series.data的value  {d}%指这一部分占总数的百分比
          formatter: '{a} <br/>{b} : {c}个 ({d}%)'
        },
        // 设置饼状图每个颜色块的颜色
        // color: ['red', 'orange', 'green', 'blue', 'indigo', 'purple'],
        normal: {
          // 自定义颜色
          color: function(params) {
            var colorList = [
              'red', 'orange', '#49ADF4', '#00FFFF', '#00FF00', '#FFFF00', '#FF8C00', '#FF0000', '#FE8463'
            ]
            return colorList[params.dataIndex]
          }
        },
        series: [
          {
            name: this.getName(options.name),
            type: 'pie',
            redius: '55%',
            data: options.data,
            // itemStyle 设置饼状图扇形区域样式
            itemStyle: {
              normal: {
                label: {
                  show: true,
                  formatter: '{b} : {c} ({d}%)'
                },
                labelLine: { show: true },
                // emphasis:英文意思是 强调;着重;(轮廓、图形等的)鲜明;突出,重读
                // emphasis:设置鼠标放到哪一块扇形上面的时候,扇形样式、阴影
                emphasis: {
                  shadowBlur: 10,
                  shadowOffsetX: 0,
                  shadowColor: 'rgba(30, 144, 255,0.5)'
                }
              }
            },
            // 设置值域的那指向线
            labelLine: {
              normal: {
                show: false // show设置线是否显示,默认为true,可选值:true ¦ false
              }
            },
            // 设置值域的标签
            label: {
              normal: {
                position: 'inner', // 设置标签位置,默认在饼状图外 可选值:'outer' ¦ 'inner(饼状图上)'
                // formatter: '{a} {b} : {c}个 ({d}%)'   设置标签显示内容 ,默认显示{b}
                // {a}指series.name  {b}指series.data的name
                // {c}指series.data的value  {d}%指这一部分占总数的百分比
                formatter: '{c}'
              }
            }
          }
        ]
      }
      return option
    },
    getName() {
      console.log(arguments[0], '传递名字')
      switch (arguments[0]) {
        case 'type':
          return '类型'
        case 'distance':
          return '距离'
        case 'price':
          return '单价'
        case 'charge':
          return '里程费'
        case 'objectType':
          return '对象类型'
        case 'grade':
          return '等级'
        case 'company':
          return '公司'
        case 'status':
          return '状态'
        default :
          return ''
      }
    }
  }

}
</script>
<style lang="scss" scoped>
</style>

2、vue中使用
将上一个页面选择需要统计的表格列数组传递到后台,根据返回的统计数据循环绘制出饼图和表格

<template>
  <div class="form-box" >
    <h3 class="form-title">统计列表</h3>
    <!-- 按钮 -->
    <div class="btn-row">
      <el-button
        size="mini"
        icon="el-icon-back"
        plain
        @click="goBack">返回</el-button>
    </div>
    <!-- 表格 -->
    <el-row :gutter="24">
      <el-col v-for="(item,index) in countData" :xs="24" :sm="12" :lg="6" :key="index" style="margin-top:20px;height:300px">
        <pieChart :id="`chart+${index}`" :style="{width: '100%', height: '380px'}" :chart-data="item"/>
        <el-table
          ref="table"
          :data="item.countObjects"
          height="300"
          resizable
          border
          style="width: 100%">
          <!--数据源-->
          <el-table-column :label="getName(item.columnName)" header-align="center">
            <el-table-column align="center" prop="name" label="名称">
              <template slot-scope="scope">
                <template v-if="item.columnName==='siteStatus'">{{ scope.row.name|filterApprovalStatus }}</template>
                <template v-else>
                  <span>{{ scope.row.name }}</span>
                </template>
              </template>
            </el-table-column>
            <el-table-column align="center" width="100px" prop="count" label="数量"/>
          </el-table-column>
        </el-table>
      </el-col>
    </el-row>
  </div>
</template>

<script>
import { count } from '@/api/public'
import initDict from '@/mixins/initDict'
import statusDict from '@/mixins/statusDict'
import pieChart from '@/views/components/pieChart'
export default {
  components: { pieChart },
  mixins: [initDict, statusDict],
  data() {
    return {
      countData: [],
      name: {}
    }
  },
  beforeRouteEnter(to, from, next) {
    next(vm => {
      vm.name = vm.$route.query.data
      if (vm.name) {
        vm.getData()
      }
    })
  },
  beforeRouteLeave(to, from, next) {
    next()
  },
  created() {
    // 获取数据字典
    this.getDictMap('inside_company,site_status,first_type')
  },
  methods: {
    // 传递需要统计的字段数组 this.name
    getData() {
      count(this.name).then(res => {
        this.countData = res
      })
      this.getDictMap('inside_company,site_status,first_type')
    },
    getName() {
      console.log(arguments[0], '传递名字')
      switch (arguments[0]) {
        case 'type':
          return '类型'
        case 'distance':
          return '距离'
        case 'price':
          return '单价'
        case 'charge':
          return '里程费'
        case 'objectType':
          return '对象类型'
        case 'grade':
          return '等级'
        case 'company':
          return '公司'
        case 'status':
          return '状态'
        default :
          return ''
      }
    },
    goBack() {
      this.$router.go(-1)
    }
  }
}
</script>

<style lang="scss" >
@import "@/styles/form.scss";
</style>

<style scoped>
li{
  margin: 12px 0;
}
</style>

3、效果图如下
在这里插入图片描述

Logo

前往低代码交流专区

更多推荐