实现echarts全屏的放大/缩小最优解
需求 :
丝滑实现echarts全屏的放大/缩小
最终效果如下 :
未处理前 :
放大-->缩小后出现echarts样式
旧方案 :
监听全屏变化事件,全局触发 window.resize , 会出现顿挫感
最终方案 :
监听全屏切换事件,并在容器尺寸真正变化后才 resize 图表
步骤一 : 在echarts组件中
每个图表组件暴露 resize() 方法
// 文件位置 @/home/components/pieChart.vue<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue'
import * as echarts from 'echarts'const chartRef = ref<HTMLDivElement | null>(null)
let chartInstance: echarts.ECharts | null = nullconst initChart = () => {...
}const resizeChart = () => {chartInstance?.resize()
}onMounted(initChart)
onBeforeUnmount(() => {chartInstance?.dispose()window.removeEventListener('resize', resizeChart)
})// 为每个组件暴露resize方法
const resize = () => {chartInstance?.resize()
}defineExpose({resize
})
</script>
步骤二 : 在hooks中
使用 ResizeObserver 来感知图表容器尺寸变化 (还可封装为hooks方法)
// 文件位置 @/hooks/useEChartsResizeimport { onMounted, onBeforeUnmount, Ref } from 'vue'export function useChartResize (containerRef: Ref<HTMLElement | null>,chartRefs: Ref[] = []
) {let observer: ResizeObserver | null = nullonMounted(() => {if (containerRef.value) {observer = new ResizeObserver(() => {chartRefs.forEach(chartRef => {chartRef.value?.resize?.()})})observer.observe(containerRef.value)}})onBeforeUnmount(() => {if (observer && containerRef.value) {observer.unobserve(containerRef.value)observer.disconnect()}})
}
步骤三 : 在父组件中
父组件(即index.vue)中引入ResizeObserver方法 , 模板中绑定ref
// 文件位置 @/home/index.vue<template><div class="big-screen" ref="screenRef"><!-- 左侧 --><div class="left"><div class="chart-box"><BarChart ref="barChartRef1" /></div><div class="chart-box"><LineChart ref="lineChartRef1" /></div><div class="chart-box"><PieChart ref="pieChartRef1" /></div></div><!-- 中间 --><div class="center">...</div><!-- 右侧 --><div class="right">...</div><!-- 全屏 --><i:class="['iconfont', isFullscreen ? 'icon-suoxiao' : 'icon-fangda']"class="echarts-icon"@click="toggleFullScreen"></i></div>
</template><script setup lang="ts">import { useChartResize } from '@/hooks/useEChartsResize' // 引入hooksconst screenRef = ref<HTMLElement | null>(null)const barChartRef1 = ref()
const lineChartRef1 = ref()
const pieChartRef1 = ref()
const lineChartRef2 = ref()
const barChartRef3 = ref()
const lineChartRef3 = ref()
const pieChartRef3 = ref()useChartResize(screenRef, [barChartRef1,lineChartRef1,pieChartRef1,lineChartRef2,barChartRef3,lineChartRef3,pieChartRef3
])// 点击全屏切换
const toggleFullScreen = () => {if (screenfull.isEnabled && screenRef.value) {screenfull.toggle(screenRef.value).then(() => {// 等待动画结束,再 resize 所有图表setTimeout(() => {;[barChartRef1,lineChartRef1,pieChartRef1,lineChartRef2,barChartRef3,lineChartRef3,pieChartRef3].forEach(refItem => {refItem.value?.resize?.()})}, 300)})}
}</script>