import { nextTick, onBeforeUnmount, onMounted, watch } from 'vue' import { init } from 'echarts/core' export function useEcharts(chartElement, chartOptions) { let chartInstance = null let resizeObserver = null let renderFrame = 0 let initialFrame = 0 let initialTimer = 0 let initialRendered = false let initialPending = false let latestOption = null const initialAnimationDelay = 180 function renderChart() { if (!chartElement.value) { return } if (!chartInstance) { chartInstance = init(chartElement.value, null, { renderer: 'canvas' }) chartInstance.resize() } if (!initialRendered) { initialRendered = true initialPending = true latestOption = chartOptions.value if (typeof window !== 'undefined') { initialTimer = window.setTimeout(() => { initialTimer = 0 initialFrame = window.requestAnimationFrame(() => { initialFrame = 0 initialPending = false chartInstance?.setOption(latestOption || chartOptions.value, { notMerge: true, lazyUpdate: false }) latestOption = null }) }, initialAnimationDelay) return } } if (initialPending) { latestOption = chartOptions.value return } chartInstance.setOption(chartOptions.value, { notMerge: false, lazyUpdate: false }) } function handleResize() { chartInstance?.resize() } function scheduleRender() { if (typeof window === 'undefined') { renderChart() return } if (renderFrame) { window.cancelAnimationFrame(renderFrame) } renderFrame = window.requestAnimationFrame(() => { renderFrame = 0 renderChart() }) } function bindResize() { if (!chartElement.value) { return } if (typeof ResizeObserver !== 'undefined') { resizeObserver = new ResizeObserver(handleResize) resizeObserver.observe(chartElement.value) } window.addEventListener('resize', handleResize) } function unbindResize() { resizeObserver?.disconnect() resizeObserver = null window.removeEventListener('resize', handleResize) } onMounted(() => { renderChart() bindResize() }) onBeforeUnmount(() => { unbindResize() if (renderFrame && typeof window !== 'undefined') { window.cancelAnimationFrame(renderFrame) renderFrame = 0 } if (initialFrame && typeof window !== 'undefined') { window.cancelAnimationFrame(initialFrame) initialFrame = 0 } if (initialTimer && typeof window !== 'undefined') { window.clearTimeout(initialTimer) initialTimer = 0 } if (chartInstance) { chartInstance.dispose() chartInstance = null } }) watch(chartOptions, () => { nextTick(scheduleRender) }, { deep: true }) return { renderChart } }