需求 :
丝滑实现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 = null
const 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/useEChartsResize
import { onMounted, onBeforeUnmount, Ref } from 'vue'
export function useChartResize (
containerRef: Ref<HTMLElement | null>,
chartRefs: Ref[] = []
) {
let observer: ResizeObserver | null = null
onMounted(() => {
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' // 引入hooks
const 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>