用vue3封装自用的echarts组件

封装的组件


BaseChart.vue

<script setup>
  import {
    ref,
    onMounted,
    onBeforeUnmount,
    watch,
    markRaw
  } from 'vue';
  import {
    debounce
  } from "@/utils"; //节流函数 
  import * as echarts from "echarts";

  const emit = defineEmits(['chartClick', 'chartMouseover', 'chartMouseout'])
  const props = defineProps({
    option: {
      type: Object,
      defined: () => {}
    },
    width: {
      type: String,
      defined: '100%'
    }, // 必须指定容器的宽高,否则无法显示。(容器内图表会自动获取父元素宽高)
    height: {
      type: String,
      defined: '100%'
    },
    theme: {
      type: [Object, String],
      defined: ''
    },
    loading: {
      type: Boolean,
      defined: false
    }, // 受控
    onMouseover: {
      type: Function,
      defined: () => {}
    },
    onMouseout: {
      type: Function,
      defined: () => {}
    },
    onClick: {
      type: Function,
      defined: () => {}
    }
  })

  const chartRef = ref(null);
  const chartInstance = ref();

  const draw = () => {
    if (chartInstance.value) {
      // console.log('修改了', props.option);
      chartInstance.value.setOption(props.option, {
        notMerge: true
      });
    }
  };

  const init = () => {
    if (!chartRef.value) return;

    // 校验 Dom 节点上是否已经挂载了 ECharts 实例,只有未挂载时才初始化
    chartInstance.value = echarts.getInstanceByDom(chartRef.value);
    if (!chartInstance.value) {
      chartInstance.value = markRaw(
        echarts.init(chartRef.value, props.theme, {
          renderer: 'canvas',
        })
      );

      // 绑定鼠标事件:
      if (props.onMouseover) {
        chartInstance.value.on('mouseover', (event) => {
          props.onMouseover(event, chartInstance.value, props.option);

        });
      }
      if (props.onMouseout) {
        chartInstance.value.on('mouseout', (event) => {
          props.onMouseout(event, chartInstance.value, props.option);
        });
      }
      if (props.onClick) {
        chartInstance.value.on('click', (event) => {

          props.onClick(event, chartInstance.value, props.option);
        });
      }

      chartInstance.value.on('mouseover', (event) => {
        emit('chartMouseover', event, chartInstance.value, props.option)
      })
      chartInstance.value.on('mouseout', (event) => {
        emit('chartMouseout', event, chartInstance.value, props.option)
      })
      chartInstance.value.on('click', (event) => {
        emit('chartClick', event, chartInstance.value, props.option)
      })

      draw();
    }
  };

  // 窗口自适应并开启过渡动画
  const resize = () => {
    if (chartInstance.value) {
      chartInstance.value.resize({
        animation: {
          duration: 300
        }
      });
    }
  };

  // 自适应防抖优化
  const debouncedResize = debounce(resize, 500, {
    maxWait: 800
  });

  // 对父组件暴露获取 ECharts 实例的方法,可直接通过实例调用原生函数
  defineExpose({
    getInstance: () => chartInstance.value,
    resize,
    draw,
  });

  watch(props, () => {
    draw();
  });

  // 展示 loading 动画
  watch(
    () => props.loading,
    loading => {
      loading
        ?
        chartInstance.value.showLoading() :
        chartInstance.value.hideLoading();
    }
  );

  onMounted(() => {
    init();
    window.addEventListener('resize', debouncedResize);
  });

  onBeforeUnmount(() => {
    // 容器被销毁之后,销毁实例,避免内存泄漏
    chartInstance.value?.dispose();
    window.removeEventListener('resize', debouncedResize);
  });
</script>

<template>
  <div id="echart" ref="chartRef" :style="{ width: props.width, height: props.height }" />
</template>

在项目中使用

注意:如果你要使用渐变颜色还得自己引入echarts

<template>
  <div class="main-box" style="width: 100%;height: 100%;">
    <!-- :onClick="clickChart"  :onMouseout="onMouseout" :onMouseover="onMouseover"-->
    <!-- @chartClick="clickChart" @chartMouseover="chartMouseover" @chartMouseout="chartMouseout" -->
    <!-- 上面有两种点击事件和鼠标事件 都能使用 -->
    <BaseChart @chartClick="clickChart" width="100%" height="100%" :option="chartOptions">
    </BaseChart>
  </div>
</template>

<script setup>
  import BaseChart from '@/components/BaseChart/index.vue'
  import {
    requestGet
  } from '@/api/index.js'
  import {
    onMounted,
    ref
  } from 'vue'
  import * as echarts from "echarts";
  onMounted(() => {
    initChart();
  })

  const chartOptions = ref({})

  const clickChart = (e, chart, option) => {
    console.log('图标数据', e);
    console.log('图标dom', chart);
    console.log('图标option', option);
  }

  const initChart = async () => {
    chartOptions.value = {
      grid: {
        top: '15%',
        left: '1%',
        right: '7%',
        bottom: '0%',
        containLabel: true,
      },
      legend: {
        top: '0%',
        right: '10%',
        itemGap: 50,
        data: ['产量', '产值'],
        textStyle: {
          color: '#f9f9f9',
          borderColor: '#fff'
        },
      },
      xAxis: [{
        name: '年',
        nameGap: 5,
        type: 'category',
        axisLine: { //坐标轴轴线相关设置。数学上的x轴
          show: true,
          lineStyle: {
            color: '#999'
          },
        },
        axisLabel: { //坐标轴刻度标签的相关设置
          color: '#999',
        },
        axisTick: {
          show: false,
        },
        data: ['2017', '2018', '2019', '2020', '2021', '2022', '2023', ],
      }],
      yAxis: [{
        type: 'value',
        min: 0,
        // max: 140,
        splitNumber: 7,
        splitLine: {
          show: true,
          lineStyle: {
            color: '#0a3256'
          }
        },
        axisLine: {
          show: false,
        },
        axisLabel: {
          // margin: 20,
          color: '#999',
        },
        axisTick: {
          show: false,
        },
      }],
      tooltip: {
        trigger: 'axis',
      },
      series: [{
        name: '产量',
        type: 'line',
        // smooth: true, //是否平滑曲线显示
        // 			symbol:'circle',  // 默认是空心圆(中间是白色的),改成实心圆
        showAllSymbol: true,
        symbol: 'emptyCircle',
        // symbolSize: 6,
        lineStyle: {

          color: "#28ffb3", // 线条颜色
          borderColor: '#f0f'
        },
        label: {
          show: false,
          position: 'top',
          color: '#fff',
        },
        itemStyle: {
          color: "#28ffb3",
          lineStyle: {
            width: 1,
            type: 'solid' //'dotted'虚线 'solid'实线
          }
        },
        areaStyle: { //区域填充样式
          //线性渐变,前4个参数分别是x0,y0,x2,y2(范围0~1);相当于图形包围盒中的百分比。如果最后一个参数是‘true’,则该四个值是绝对像素位置。
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
              offset: 0,
              color: 'rgba(0,154,120,1)'
            },
            {
              offset: 1,
              color: 'rgba(0,0,0, 0)'
            }
          ], false),
          shadowColor: 'rgba(53,142,215, 0.9)', //阴影颜色
          shadowBlur: 20 //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。
        },
        data: [393, 438, 485, 631, 689, 824, 987]
      }, {

        name: '产值',
        type: 'bar',
        barWidth: 15,
        // tooltip: {
        //   show: false
        // },
        label: {
          show: false,
          position: 'top',
          color: '#fff',
        },
        itemStyle: {
          color: "#1cfffb",
          lineStyle: {
            width: 1,
            type: 'solid' //'dotted'虚线 'solid'实线
          },
          //  barBorderRadius: [30, 30, 0, 0],
        },
      }]
    };

  }

</script>

<style scoped lang="scss">
  .main-box {
    width: 100%;
    height: 100%;
  }

  .main-content {

    width: 100%;
    height: 100%;
  }
</style>```

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值