vue3.0封装eCharts组件(扇形,柱状图,折线+柱状图)

在这里插入图片描述

扇形图组件

<template>
  <div :id="id" :chartOptions="chartOptions" class="chart"></div>
</template>

<script setup>
import { onMounted, onBeforeUnmount, watch } from "vue";
import * as echarts from "echarts";
const props = defineProps({
  id: {
    type: String,
    default: "chart",
  },
  chartOptions: {
    type: Object,
    default: {},
  },
});

let myChart;
let chartOptions = props.chartOptions;

onMounted(() => {
  setTimeout(() => {
    var id = props.id;
    var chartDom = document.getElementById(id);
    if (myChart) {
      myChart.dispose(); //销毁
    }
    myChart = echarts.init(chartDom);
    getEchartsData();
  }, 500);

  window.addEventListener("resize", () => {
    myChart.resize();
  });
});

const getEchartsData = () => {
  let option = {
    grid: {
      top: "15%",
      left: 0,
      containLabel: true, // 确保标签不被剪裁
      height: "85%", // 高度为容器高度的80%
      width: "100%",
    },
    tooltip: {
      trigger: "item",
    },
    legend: {
      show: true,
    },
    xAxis: {
      data: ["变更改造", "缺陷申报", "其他", "预测性维修", "预防性维修", "点巡检"],
      axisLabel: {
            interval: 0,
            formatter:function(value){  
                var str = ""; 
                var num = 5; //每行显示字数 
                var valLength = value.length; //该项x轴字数  
                var rowNum = Math.ceil(valLength / num); // 行数  
                
                if(rowNum > 1) {
                    for(var i = 0; i < rowNum; i++) {
                        var temp = "";
                        var start = i * num;
                        var end = start + num;
                        
                        temp = value.substring(start, end) + "\n";
                        str += temp; 
                    }
                    return str;
                } else {
                    return value;
                } 
            }
        }
    },
    yAxis: {
      splitLine: {
        show: true,
        lineStyle: {
          type: "dashed", //背景色为虚线
        },
      },
    },
    series: [
      {
        name: "申请数量",
        type: "bar",
        data: chartOptions.data1,
        itemStyle: {
          color: "#3299EC", // 这里设置柱状图的颜色
        },
      },
      {
        name: "审批数量",
        type: "bar",
        data: chartOptions.data2,
        itemStyle: {
          color: "#F1AF1F", // 这里设置柱状图的颜色
        },
      },
    ],
  };
  //{ notMerge: true } 数据更新关键
  if (myChart) {
    myChart.setOption(option, { notMerge: true });
  }
};

watch(
  () => props.chartOptions,
  (val) => {
    if (val) {
      getEchartsData();
    }
  },
  { deep: true }
);

onBeforeUnmount(() => {
  window.removeEventListener("resize", () => {
    myChart.resize();
  });
});
</script>

<style scoped lang="scss">
.chart {
  width: 100%;
  height: 203px;
}
</style>

柱状图组件

<template>
  <div :id="id" :chartOptions="chartOptions" class="chart"></div>
</template>

<script setup>
import { onMounted, onBeforeUnmount, watch } from "vue";
import * as echarts from "echarts";
const props = defineProps({
  id: {
    type: String,
    default: "chart",
  },
  chartOptions: {
    type: Object,
    default: {},
  },
});

let myChart;
let chartOptions = props.chartOptions;

onMounted(() => {
  setTimeout(() => {
    var id = props.id;
    var chartDom = document.getElementById(id);
    if (myChart) {
      myChart.dispose(); //销毁
    }
    myChart = echarts.init(chartDom);
    getEchartsData();
  }, 500);

  window.addEventListener("resize", () => {
    myChart.resize();
  });
});

const getEchartsData = () => {
  let option = {
    title: {
      text: "合计申请工单",
      subtext: chartOptions.seriesData[0] ? chartOptions.seriesData[0].num : 0,
      left: "center",
      top: "42%",
    },
    tooltip: {
      trigger: "item",
    },
    series:{
      name: "访问来源",
      type: "pie",
      radius: ["64%", "79%"],
      labelLine: {
        show:true,
        length: 5, //第一段线长
        length2: 50, //第二段线长
      },
      label: {
        formatter: '{b}:{c}\n'+'{a|{d}%}',
        position:'outer',
        alignTo:'edge',
        padding: [33, -50, 20, -50], 
        distance: 10,
        rich: {
          a: {
            fontSize: 13,
            color: "inherit",
            lineHeight: 32,
          },
        },
      },
      itemStyle: {
        normal: {
          color: function (params) {
            const colorList = ["#3299EC", "#F1AF1F "];
            return colorList[params.dataIndex % colorList.length];
          },
        },
      },
      data: chartOptions.seriesData,
    },
  };
  //{ notMerge: true } 数据更新关键
  if (myChart) {
    myChart.setOption(option, { notMerge: true });
  }
};

watch(
  () => props.chartOptions,
  (val) => {
    if(val){
      getEchartsData();
    }
  },
  { deep: true }
);

onBeforeUnmount(() => {
  window.removeEventListener("resize", () => {
    myChart.resize();
  });
});
</script>

<style scoped lang="scss">
.chart {
  width: 100%;
  height: 203px;
}
</style>

折线+柱状图组件

<template>
  <div :id="id" :chartOptions="chartOptions" class="chart"></div>
</template>

<script setup>
import { onMounted, onBeforeUnmount, watch } from "vue";
import * as echarts from "echarts";
const props = defineProps({
  id: {
    type: String,
    default: "chart",
  },
  chartOptions: {
    type: Object,
    default: {},
  }
});

let myChart;
let chartOptions = props.chartOptions;

onMounted(() => {
  setTimeout(() => {
    var id = props.id;
    var chartDom = document.getElementById(id);
    if (myChart) {
      myChart.dispose(); //销毁
    }
    myChart = echarts.init(chartDom);
    getEchartsData();
  }, 500);

  window.addEventListener("resize", () => {
    myChart.resize();
  });
});

const getEchartsData = () => {
  let option = {
    grid: {
      top: "15%",
      left: 0,
      containLabel: true, // 确保标签不被剪裁
      height: "86%", // 高度为容器高度的80%
      width: "100%",
    },
    tooltip: {
      trigger: "axis",
      axisPointer: {
        type: "cross",
        label: {
          backgroundColor: "#283b56",
        },
      },
    },
    legend: {},
    toolbox: {
      show: true,
    },
    dataZoom: {
      show: false,
      start: 0,
      end: 100,
    },
    xAxis: [
      {
        type: "category",
        axisPointer: {
          type: "shadow",
        },
        data:
          chartOptions.xData.length !== 0
            ? chartOptions.xData
            : [
                "第一周",
                "第二周",
                "第三周",
                "第四周",
                "第五周",
                "第六周",
                "第七周",
                "第八周",
                "第九周",
                "第十周",
                "第十一周",
                "第十二周",
              ],
        axisLabel: {
          interval: 0,
          rotate:45
        },
      },
      // {
      //   type: "category",
      //   boundaryGap: true,
      //   data:[10,10,10],
      //   //data: chartOptions.xData.length!==0?chartOptions.xData:['第一周','第二周','第三周'],
      // },
    ],
    yAxis: [
      {
        type: "value",
        scale: true,
        // name: "数量/个",
        max: Math.max(...chartOptions.y1Data),
        min: 0,
        boundaryGap: [0.2, 0.2],
        splitLine: {
          show: true,
          lineStyle: {
            type: "dashed", //背景色为虚线
          },
        },
      },
      {
        type: "value",
        scale: true,
        // name: "趋势/%",
        axisLabel: {
          show: true,
          interval: "auto", //居中显示
          formatter: (value) => {
            return value + "%";
          },
        },
        max: Math.max(...chartOptions.y2Data),
        min: Math.floor(Math.min(...chartOptions.y2Data))< 0 ?Math.floor(Math.min(...chartOptions.y2Data)-10) : 0,
        boundaryGap: [0.2, 0.2],
        splitLine: {
          show: true,
          lineStyle: {
            type: "dashed", //背景色为虚线
          },
        },
      },
    ],
    series: [
      {
        name: "申请数量",
        type: "bar",
        //xAxisIndex: 1,
        yAxisIndex: 0,
        data: chartOptions.y1Data, // 柱状图数据
        itemStyle: {
          color: "#1CDEA4", // 这里设置柱状图的颜色
        },
      },
      {
        name: "申请数量增长趋势",
        type: "line",
        yAxisIndex: 1,
        data: chartOptions.y2Data, // 折线图数据
        itemStyle: {
          color: "#F1AF1F", // 这里设置柱状图的颜色
        },
      },
    ],
  };
  //{ notMerge: true } 数据更新关键
  if (myChart) {
    myChart.setOption(option, { notMerge: true });
  }
};

watch(
  () => props.chartOptions,
  (val) => {
    if (val) {
      getEchartsData();
    }
  },
  { deep: true }
);

onBeforeUnmount(() => {
  window.removeEventListener("resize", () => {
    myChart.resize();
  });
});
</script>

<style scoped lang="scss">
.chart {
  width: 100%;
  height: 203px;
}
</style>

父组件
注意:一定必须用reactive,否则不会实现父子组件的响应式效果

const pieOptions = reactive({
  seriesData: [],
});
const barLineConfig = reactive({
  xData: [],  // 横坐标
  y1Data: [], // 纵坐标1
  y2Data: [], // 纵坐标2
});
const barsConfig = reactive({
  data1: ["", "", "", "", "", ""],  // 纵坐标1    这块的案例是两个柱状图
  data2: ["", "", "", "", "", ""],  // 纵坐标2
});

在onMounted里面进行初始化数据给pieOptions,barLineConfig,barsConfig进行赋值

onMounted(() => {

});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值