vue3 封装 echarts

vue3 封装echarts

因为很早前接触echarts 都是在原生js 中使用,所以不太喜欢vue 的一些封装库,因此便于开发,封装一个适合个人的方法组件。

创建模版组件

/Echarts/index.vue

<template>
    <div :id="id" :class="className" :style="{ height, width }"></div>
</template>

<script setup lang="ts">
// 按需导入需要用到的 vue函数 和 echarts
import {
    onMounted,
    onUnmounted,
    onBeforeUnmount,
    defineProps,
    watch,
    ref,
    defineEmits,
    defineExpose,
} from 'vue';
import * as echarts from 'echarts';

// 获取 dom 和 父组件数据 并定义"myChart"用于初始化图表
let myChart: echarts.ECharts;
const props = defineProps({
    id: {
        type: String,
        default: 'chart',
        required: true,
    },
    className: {
        type: String,
        default: '',
    },
    width: {
        type: String,
        default: '100%',
    },
    height: {
        type: String,
        default: '300px',
    },
    loading: {
        type: Boolean,
        default: true,
    },
    fullOptions: {
        type: Object,
        default: () => ({}),
        required: true,
    },
});
// 重绘图表函数
const resizeHandler = () => {
    myChart.resize();
};

// 传出 实例
const chartObj = () => {
    return myChart;
};
// 设置防抖,保证无论拖动窗口大小,只执行一次获取浏览器宽高的方法
const debounce = (fun: { (): void; (): void }, delay: number | undefined) => {
    let timer: number | undefined;
    return function () {
        if (timer) {
            clearTimeout(timer);
        }
        timer = setTimeout(() => {
            fun();
        }, delay);
    };
};
const cancalDebounce = debounce(resizeHandler, 50);
const emit = defineEmits(['legendselectchange']);
// 页面成功渲染,开始绘制图表
onMounted(() => {
    // 配置为 svg 形式,预防页面缩放而出现模糊问题;图表过于复杂时建议使用 Canvas
    myChart = echarts.init(document.getElementById(props.id) as HTMLDivElement, {
        renderer: 'svg',
    });
    // props.loading &&
    //   myChart.showLoading({
    //     text: '',
    //     color: '#409eff',
    //     textColor: '#000',
    //     maskColor: 'rgba(255, 255, 255, .95)',
    //     zlevel: 0,
    //     lineWidth: 2,
    //   });
    // if (!props.loading) {
    // myChart.hideLoading();
    myChart.setOption(props.fullOptions.options, true);
    // }
    // 自适应不同屏幕时改变图表尺寸
    window.addEventListener('resize', cancalDebounce);

    // 监听图例的选中状态切换事件
    myChart.on('legendselectchanged', function (params) {
        console.log('legendselectchanged', params);
        emit('legendselectchange', params);
    });
});
// 页面销毁前,销毁事件和实例
onBeforeUnmount(() => {
    window.removeEventListener('resize', cancalDebounce);
    myChart?.dispose();
});
defineExpose({ resizeHandler, chartObj });

// 监听图表数据时候变化,重新渲染图表
watch(
    () => [props.fullOptions.options, props.loading],
    () => {
        // if (!props.loading) {
        // myChart.hideLoading();
        myChart.setOption(props.fullOptions.options, true);
        // }
    },
    { deep: true }
);
</script>

创建配置文件

/Echarts/options.vue

// 图表默认配置项
const defaultOption = {
    grid: {
        left: '3%',
        right: '2%',
        bottom: '15',
        containLabel: true,
    },
    legend: {
        show: false,
        top: 'bottom',
        textStyle: {
            color: '#999',
        },
    },
    tooltip: {
        trigger: 'axis',
        axisPointer: {
            //坐标轴指示器,坐标轴触发有效,
            type: 'shadow', //默认为line,line直线,cross十字准星,shadow阴影
            crossStyle: {
                color: '#fff',
            },
            label: {
                show: true,
                backgroundColor: '#333',
            },
        },
    },
};

// 所有用到的 echarts option 都在这里进行配置
export const chartOption = {
    // 饼图
    pieOption(data: any, dimensions = ['name', 'value'], isRose = false) {
        const option = {
            ...defaultOption,
            tooltip: {
                trigger: 'item',
                formatter: '{b} : {d}%',
            },
            dataset: {
                dimensions: dimensions,
                source: data ? data : [{ value: 0, name: '-' }],
            },
            series: {
                type: 'pie',
                radius: ['50%', '65%'],
                center: ['50%', '50%'],
                roseType: isRose ? 'area' : '', // 玫瑰图
                itemStyle: {
                    borderRadius: 1,
                    // color: function (params: any) {
                    //   //自定义颜色
                    //   const colorList = ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C'];
                    //   return colorList[params.dataIndex];
                    // }
                },
                encode: {
                    itemName: dimensions[0],
                    value: dimensions[1],
                    tooltip: dimensions[1],
                },
            },
        };
        return option;
    },
    // 柱状图
    barLineOption(xData: any, sData: any, type = 'bar') {
        const option = {
            ...defaultOption,
            xAxis: {
                type: 'category',
                data: xData ? xData : ['-', '-', '-', '-', '-'],
                axisLabel: {
                    interval: 0, // 强制显示所有标签
                    textStyle: {
                        // color: '#fff',
                    },
                },
            },
            yAxis: {
                type: 'value',
                nameTextStyle: {
                    padding: [0, 20, 0, 0],
                },
                min: 0,
                minInterval: 1,
                axisLabel: {
                    interval: 0, // 强制显示所有标签
                    textStyle: {
                        color: '#8FADCC',
                    },
                },
                splitLine: {
                    show: true,
                    lineStyle: {
                        // 分割线的颜色
                        color: 'rgba(1,1,1,0.5)',
                        // 分割线的宽度
                        width: 1,
                        // 分割线的类型
                        type: 'solid',
                    },
                },
            },
            series: {
                type: type,
                itemStyle: {},
                smooth: true,
                data: sData ? sData : [0, 0, 0, 0, 0],
            },
        };
        return option;
    },
    // 柱状图
    barLineOption2(yData: any, sData: any, type = 'bar') {
        const option = {
            ...defaultOption,
            xAxis: {
                type: 'value',
                nameTextStyle: {
                    padding: [0, 20, 0, 0],
                },
                min: 0,
                max: function (value) {
                    return value.max + 20;
                },
            },
            yAxis: {
                type: 'category',
                splitLine: {
                    show: true,
                    lineStyle: {
                        // 分割线的颜色
                        color: '#ddd',
                        // 分割线的类型
                        type: 'dashed',
                    },
                },
                data: yData ? yData : ['-', '-', '-', '-', '-'],
            },
            series: {
                type: type,
                itemStyle: {},
                data: sData ? sData : [0, 0, 0, 0, 0],
            },
        };
        return option;
    },
};

// x轴方向 滚动条
export const dataZoom = [
    {
        type: 'slider',
        width: '80%',
        zoomLock: true, // 是否只平移不缩放
        moveOnMouseMove: true, // 鼠标移动能触发数据窗口平移
        zoomOnMouseWheel: false, // 鼠标移动能触发数据窗口缩放
        // start: 0,
        // end: 60,
        // startValue: 0,
        // endValue: 10,
        maxValueSpan: 9,
        minValueSpan: 9,
        showDataShadow: false,
        fillerColor: '#DADADA',
        borderRadius: '50%',
        moveHandleSize: 0,
        moveHandleStyle: {},
        left: '10%',
        right: '10%',
        bottom: 10,
        height: 10,
        handleSize: '80%', // 滑动条的 左右2个滑动条的大小
        handleIcon: 'path://M512,512m-448,0a448,448,0,1,0,896,0a448,448,0,1,0,-896,0Z',
        handleStyle: {
            borderWidth: 0, // 边框宽度
            color: '#DADADA',
        },
        brushSelect: false,
        textStyle: false,
    },
    {
        type: 'inside',
        zoomOnMouseWheel: false, // 关闭滚轮缩放
        moveOnMouseWheel: true, // 开启滚轮平移
        moveOnMouseMove: true, // 鼠标移动能触发数据窗口平移
        zoomLock: false,
        brushSelect: false,
    },
];

// y轴方向滚动条
export const dataZoomY = [
    {
        type: 'slider',
        zoomLock: true, // 是否只平移不缩放
        moveOnMouseMove: true, // 鼠标移动能触发数据窗口平移
        zoomOnMouseWheel: false, // 鼠标移动能触发数据窗口缩放
        start: 100,
        // end: 10,
        maxValueSpan: 5,
        minValueSpan: 5,
        showDataShadow: false,
        fillerColor: '#DADADA',
        borderRadius: '50%',
        yAxisIndex: 0,
        moveHandleSize: 0,
        moveHandleStyle: {},
        left: '10',
        right: '10',
        bottom: 20,
        top: 18,
        width: 10,
        handleSize: '80%', // 滑动条的 左右2个滑动条的大小
        handleIcon: 'path://M512,512m-448,0a448,448,0,1,0,896,0a448,448,0,1,0,-896,0Z',
        handleStyle: {
            borderWidth: 0, // 边框宽度
            color: '#DADADA',
        },
        brushSelect: false,
        textStyle: false,
    },
    {
        type: 'inside',
        zoomOnMouseWheel: true, // 关闭滚轮缩放
        moveOnMouseWheel: true, // 开启滚轮平移
        moveOnMouseMove: true, // 鼠标移动能触发数据窗口平移
        yAxisIndex: 0,
        zoomLock: false,
        brushSelect: false,
    },
];

使用

<template>
    <v-card class="energy_used" title="Energy Used">
        <ECharts :height="`calc(${props?.height} - 52px)`" :full-options="options" />
    </v-card>
</template>
<script setup lang="ts">
// import VueApexCharts from 'vue3-apexcharts';
import { ref, computed, onMounted, reactive } from 'vue';
import ECharts from '@/components/Echarts/index.vue';
import { chartOption } from '@/components/Echarts/options';

const props = withDefaults(
    defineProps<{
        height?: string | number;
    }>(),
    {
        height: 308,
    }
);

const series = ref([
    {
        name: 'Kwh',
        data: [31, 40, 28, 51, 42, 109, 100],
    },
]);

onMounted(() => {
    initChart();
});

const options = reactive({
    options: {},
});

function initChart() {
    const xData = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
    const sData = [31, 40, 28, 51, 42, 109, 100];
    const option = chartOption.barLineOption(xData, sData);
    option.yAxis['name'] = 'Kwh';
    option.series.type = 'line';
    options.options = option;
}
</script>

这是我自己比较喜欢的一种方式。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vue3中封装ECharts组件的方法如下所示: 1. 首先,在Vue项目中引入ECharts组件,可以使用import语句将ECharts组件导入到你的Vue文件中。例如,你可以使用以下代码引入ECharts组件: ```javascript import Echarts from '@/components/Echarts/Echarts.vue'; ``` 2. 然后,创建一个名为echartsOptions的响应式对象来存储ECharts的配置项。你可以使用reactive函数创建一个响应式对象。例如: ```javascript import { reactive } from 'vue'; const echartsOptions = reactive({ options: {}, init: false }); ``` 3. 在mounted钩子函数中,初始化ECharts的配置项。你可以根据需要从后端获取数据,并将数据传递给ECharts的配置项。例如,你可以使用以下代码初始化配置项: ```javascript import { onMounted } from 'vue'; import chartOption from '@/components/Echarts/options'; onMounted(() => { const testData = [ { value: 26, name: '家用电器' }, { value: 27, name: '户外运动' }, { value: 24, name: '汽车用品' }, { value: 23, name: '手机数码' } ]; const testDimensions = ['name', 'value']; echartsOptions.options = chartOption.testOption(testData, testDimensions); }); ``` 4. 最后,在模板中使用ECharts组件并传递配置项和其他属性。例如: ```html <template> <Echarts id="echarts" height="300px" :full-options="echartsOptions" :loading="loading"></Echarts> </template> ``` 在上述代码中,`full-options`属性将配置项传递给ECharts组件,`loading`属性控制组件的加载状态。 这样,你就可以在Vue3中封装ECharts组件并使用它了。更多关于Vue3和ECharts的具体用法,你可以参考ECharts官方网站和Vue官方文档。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [vue3 封装ECharts组件](https://blog.csdn.net/weixin_42775304/article/details/130390065)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值