echarts使用resize重新绘制图表时遇到的问题
需求: 外部输入一个echart数组,根据恒定的数组长度动态决定是否有滚动条存在,如果数组长超过恒定值则赋予滚动条,否则平滑展示
PS: 上级不许使用echart提供的滚动条,只好使用echart容器的父容器来实现
滚动原理
当子容器宽度大于父容器宽度且父容器设置了x或y轴overflow:auto时,会出现滚动条
前期准备
由于后端只给了一条数据,无法满足多种可能,因而自己写了一个循环多个的函数
/**
* @description: 拷贝数组项,适用于后台仅返回一条数据而我们需要多条数据
* @param {*} arr 初始数组项,
* @param {*} num 循环数,默认10
* @return {*} newArr
*/
export const repeatArrayItem = (arr,num = 10) => {
let newArr = []
for (let index = 0; index < num; index++) {
newArr.push(arr[0])
}
return newArr
}
外部使用:
const a = repeatArrayItem(res.item)
setTopData(a) //其中topData即为传入数组
准备工作完毕,接下来要写echart组件内部逻辑
需求实现
已知数组长度不确定,因而要动态设置父子容器样式(父容器ovwerlowX、子容器width)
jsx部分:
<div style={{ overflowX }}>
<div ref={divRef} style={{
height: "440px",
width
}} >
</div>
</div>
// receiveEchartResource 为接收到的echart list
// 默认滚动
const [overflowX, setOverflowX] = useState('auto')
const [width, setWidth] = useState('140%')
const isScroll = receiveEchartResource.length >= 18 //恒定值,作为是否滚动的依据
// 监听receiveEchartResource,变化则立即触发
useEffect(()=>{
setOverflowX( isScroll ? 'auto' : `hidden` )
setWidth( isScroll ? '140%' : '100%' )
},[receiveEchartResource])
本以为这样写就可以了,但是还不行,会有一个致命bug:外部父组件需要动态设置长度,假设恒定值为18,长度第一次大于小于18都可以展示,但是第二次如果是反状态则页面则不会渲染成功,或者挤到一起,或者展示不全且无滚动条,
起初以为是我的动态设置的样式有问题,直到看到window.resize函数里有echart.resize方法,突然想到应该是resize方法,然后尝试调用了一下,但是发现还是不行,后来感觉思路是对的,setState是异步,所以可能是resize方法提前于设置样式前就执行了,
所以就有了下面一步:
解决方案
原因:外部的动态传入list虽然生效,但是echart并没有办法改变自身容器,所以需要在监听到receiveEchartResource变化时重新resize一下
// 监听receiveEchartResource,变化则立即触发
let timer
useEffect(()=>{
setOverflowX( isScroll ? 'auto' : `hidden` )
setWidth( isScroll ? '140%' : '100%' )
// 判断外部传入数组是否有值,如果有则执行延时器
if (receiveEchartResource.length > 0) {
timer = setTimeout(() => {
myChart?.resize()
}, 100);
}
return (() => timer && clearTimeout(timer))
},[receiveEchartResource])
原本没准备写判断传入数组,直接写定时器,但是码友说不判断就直接写入,会出现bug: 当网络延迟至大于500ms时,会出现无法渲染情况,所以就加了一层判断,并在销毁时清除timer。
ok,描述完毕,以上。
浙公网安备 33010602011771号