| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
- import * as echarts from 'echarts';
- import { useResizeObserver } from '@vueuse/core';
- /**
- * ECharts Hook
- * @param containerRef 图表容器 Ref
- * @param options 图表配置 Ref
- * @param theme 主题配置(可选)
- * @param autoResize 是否自动响应容器大小变化(默认 true)
- */
- export function useECharts(
- containerRef,
- options,
- theme = 'macarons',
- autoResize = true
- ) {
- const chartInstance = ref(null);
- const resizeObserver = ref(null);
- let eventQueue = []
- // 初始化图表
- const init = () => {
- if (!containerRef.value) return;
- dispose();
- chartInstance.value = markRaw(echarts.init(containerRef.value, theme))
-
- chartInstance.value.setOption(options.value);
- eventQueue = eventQueue.filter((handler) => {
- handler()
- return false
- })
- // 初始化 resize 监听
- if (autoResize) {
- setupResizeObserver();
- }
- };
- // 设置 resize 监听
- const setupResizeObserver = () => {
- if (!containerRef.value) return;
-
- resizeObserver.value = useResizeObserver(containerRef.value, () => {
- resize();
- });
- };
- // 销毁图表
- const dispose = () => {
- // 移除 resize 监听
- if (resizeObserver.value) {
- resizeObserver.value.stop();
- resizeObserver.value = null;
- }
-
- // 销毁图表实例
- if (chartInstance.value && !chartInstance.value.isDisposed()) {
- chartInstance.value.dispose();
- chartInstance.value = null;
- }
- };
- // 重置图表
- const reset = () => {
- dispose();
- init();
- };
- // 手动触发 resize
- const resize = () => {
- if (chartInstance.value) {
- try {
- chartInstance.value.resize();
- } catch (error) {
- console.error('ECharts resize 失败:', error);
- }
- }
- };
- const bindEvent = (eventName, callback) => {
- eventQueue.push(() => chartInstance.value.getZr().on(eventName, callback))
- return result
- }
- // 监听 options 变化
- watch(options, (newOptions) => {
- if (chartInstance.value) {
- chartInstance.value.setOption(newOptions);
- }
- }, { deep: true, immediate: true });
- // 组件生命周期
- onMounted(() => {
- init()
- });
- onBeforeUnmount(() => dispose());
- const result = {
- instance: chartInstance,
- init,
- dispose,
- reset,
- resize,
- bindEvent
- };
- return result
- }
|