Files
frontend/packages/effects/plugins/src/echarts/use-echarts.ts

137 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { EChartsOption } from 'echarts';
import type { Ref } from 'vue';
import type { Nullable } from '@vben/types';
import type EchartsUI from './echarts-ui.vue';
import { computed, nextTick, watch } from 'vue';
import { usePreferences } from '@vben/preferences';
import {
tryOnUnmounted,
useDebounceFn,
useResizeObserver,
useTimeoutFn,
useWindowSize,
} from '@vueuse/core';
import echarts from './echarts';
// TODO @xingyu有 500kbchina.json 会影响打包么?
import chinaMap from './map/china.json';
type EchartsUIType = typeof EchartsUI | undefined;
type EchartsThemeType = 'dark' | 'light' | null;
function useEcharts(chartRef: Ref<EchartsUIType>) {
let chartInstance: echarts.ECharts | null = null;
let cacheOptions: EChartsOption = {};
const { isDark } = usePreferences();
const { height, width } = useWindowSize();
const resizeHandler: () => void = useDebounceFn(resize, 200);
echarts.registerMap('china', {
geoJSON: chinaMap as any,
specialAreas: {
china: {
left: 500,
top: 500,
width: 1000,
height: 1000,
},
},
});
const getOptions = computed((): EChartsOption => {
if (!isDark.value) {
return {};
}
return {
backgroundColor: 'transparent',
};
});
const initCharts = (t?: EchartsThemeType) => {
const el = chartRef?.value?.$el;
if (!el) {
return;
}
chartInstance = echarts.init(el, t || isDark.value ? 'dark' : null);
return chartInstance;
};
const renderEcharts = (
options: EChartsOption,
clear = true,
): Promise<Nullable<echarts.ECharts>> => {
cacheOptions = options;
const currentOptions = {
...options,
...getOptions.value,
};
return new Promise((resolve) => {
if (chartRef.value?.offsetHeight === 0) {
useTimeoutFn(async () => {
resolve(await renderEcharts(currentOptions));
}, 30);
return;
}
nextTick(() => {
useTimeoutFn(() => {
if (!chartInstance) {
const instance = initCharts();
if (!instance) return;
}
clear && chartInstance?.clear();
chartInstance?.setOption(currentOptions);
resolve(chartInstance);
}, 30);
});
});
};
function resize() {
chartInstance?.resize({
animation: {
duration: 300,
easing: 'quadraticIn',
},
});
}
watch([width, height], () => {
resizeHandler?.();
});
useResizeObserver(chartRef as never, resizeHandler);
watch(isDark, () => {
if (chartInstance) {
chartInstance.dispose();
initCharts();
renderEcharts(cacheOptions);
resize();
}
});
tryOnUnmounted(() => {
// 销毁实例,释放资源
chartInstance?.dispose();
});
return {
renderEcharts,
resize,
getChartInstance: () => chartInstance,
};
}
export { useEcharts };
export type { EchartsUIType };