130 lines
3.2 KiB
TypeScript
130 lines
3.2 KiB
TypeScript
import type { EChartsOption } from 'echarts'
|
|
import type { Ref } from 'vue'
|
|
import { useTimeoutFn } from '@/hooks/core/useTimeout'
|
|
import { tryOnUnmounted } from '@vueuse/core'
|
|
import { unref, nextTick, watch, computed, ref } from 'vue'
|
|
import { useDebounceFn } from '@vueuse/core'
|
|
import { useEventListener } from '@/hooks/event/useEventListener'
|
|
import { useBreakpoint } from '@/hooks/event/useBreakpoint'
|
|
import echarts from '@/utils/lib/echarts'
|
|
import { useRootSetting } from '@/hooks/setting/useRootSetting'
|
|
import { useMenuSetting } from '@/hooks/setting/useMenuSetting'
|
|
|
|
export function useECharts(elRef: Ref<HTMLDivElement>, theme: 'light' | 'dark' | 'default' = 'default') {
|
|
const { getDarkMode: getSysDarkMode } = useRootSetting()
|
|
const { getCollapsed } = useMenuSetting()
|
|
|
|
const getDarkMode = computed(() => {
|
|
return theme === 'default' ? getSysDarkMode.value : theme
|
|
})
|
|
let chartInstance: echarts.ECharts | null = null
|
|
let resizeFn: Fn = resize
|
|
const cacheOptions = ref({}) as Ref<EChartsOption>
|
|
let removeResizeFn: Fn = () => {}
|
|
|
|
resizeFn = useDebounceFn(resize, 200)
|
|
|
|
const getOptions = computed(() => {
|
|
if (getDarkMode.value !== 'dark') {
|
|
return cacheOptions.value as EChartsOption
|
|
}
|
|
return {
|
|
backgroundColor: 'transparent',
|
|
...cacheOptions.value
|
|
} as EChartsOption
|
|
})
|
|
|
|
function initCharts(t = theme) {
|
|
const el = unref(elRef)
|
|
if (!el || !unref(el)) {
|
|
return
|
|
}
|
|
|
|
chartInstance = echarts.init(el, t)
|
|
const { removeEvent } = useEventListener({
|
|
el: window,
|
|
name: 'resize',
|
|
listener: resizeFn
|
|
})
|
|
removeResizeFn = removeEvent
|
|
const { widthRef, screenEnum } = useBreakpoint()
|
|
if (unref(widthRef) <= screenEnum.MD || el.offsetHeight === 0) {
|
|
useTimeoutFn(() => {
|
|
resizeFn()
|
|
}, 30)
|
|
}
|
|
}
|
|
|
|
function setOptions(options: EChartsOption, clear = true) {
|
|
cacheOptions.value = options
|
|
return new Promise((resolve) => {
|
|
if (unref(elRef)?.offsetHeight === 0) {
|
|
useTimeoutFn(() => {
|
|
setOptions(unref(getOptions))
|
|
resolve(null)
|
|
}, 30)
|
|
}
|
|
nextTick(() => {
|
|
useTimeoutFn(() => {
|
|
if (!chartInstance) {
|
|
initCharts(getDarkMode.value as 'default')
|
|
|
|
if (!chartInstance) return
|
|
}
|
|
clear && chartInstance?.clear()
|
|
|
|
chartInstance?.setOption(unref(getOptions))
|
|
resolve(null)
|
|
}, 30)
|
|
})
|
|
})
|
|
}
|
|
|
|
function resize() {
|
|
chartInstance?.resize({
|
|
animation: {
|
|
duration: 300,
|
|
easing: 'quadraticIn'
|
|
}
|
|
})
|
|
}
|
|
|
|
watch(
|
|
() => getDarkMode.value,
|
|
(theme) => {
|
|
if (chartInstance) {
|
|
chartInstance.dispose()
|
|
initCharts(theme as 'default')
|
|
setOptions(cacheOptions.value)
|
|
}
|
|
}
|
|
)
|
|
|
|
watch(getCollapsed, (_) => {
|
|
useTimeoutFn(() => {
|
|
resizeFn()
|
|
}, 300)
|
|
})
|
|
|
|
tryOnUnmounted(() => {
|
|
if (!chartInstance) return
|
|
removeResizeFn()
|
|
chartInstance.dispose()
|
|
chartInstance = null
|
|
})
|
|
|
|
function getInstance(): echarts.ECharts | null {
|
|
if (!chartInstance) {
|
|
initCharts(getDarkMode.value as 'default')
|
|
}
|
|
return chartInstance
|
|
}
|
|
|
|
return {
|
|
setOptions,
|
|
resize,
|
|
echarts,
|
|
getInstance
|
|
}
|
|
}
|