124 lines
2.9 KiB
JavaScript
124 lines
2.9 KiB
JavaScript
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
|
|
}
|
|
}
|