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 function renderChart() { if (!chartElement.value) { return } if (!chartInstance) { chartInstance = init(chartElement.value, null, { renderer: 'canvas' }) chartInstance.resize() } chartInstance.setOption(chartOptions.value, true) } 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 (chartInstance) { chartInstance.dispose() chartInstance = null } }) watch(chartOptions, () => { nextTick(scheduleRender) }, { deep: true }) return { renderChart } }