echarts监控容器ResizeObserver
背景
我们在使用echarts
绘图的时候往往需要我们监控浏览器或者图表容器的宽高来实现echarts
图表的resize()
功能。这里总结了几种方法来实现
实现方案
window的resize
最常见的就是监控浏览器窗口的大小
window.addEventListener('resize', this.chartResize)
其中
this.echartsObj = this.$echarts.init(document.getElementById('testId'))
...
chartResize () {
this.echartsObj && this.echartsObj.resize()
},
这种方法自然是有用的,但是有些场景不适用。
如果我们有个可以收缩的侧边栏,当我们收缩侧边栏的时候其实浏览器窗口大小是没有变化的,但由于我们的页面是响应式的,所以内容区域容器大小是变化的,所以这个时候我们要监控的就是容器大小来实现echarts
图表的resize()
ResizeObserver
Web API提供了一个方法ResizeObserver
来实现
const resizeObserver = new ResizeObserver(() => this.chartResize())
resizeObserver.observe(document.getElementById('testId')
element-resize-detector
npm提供了一个库element-resize-detector
,同样可以帮助我们实现这个功能
import elementResizeDetector from 'element-resize-detector'
...
let erd = elementResizeDetector()
erd.listenTo(document.getElementById('testId'), this.chartResize)
当resize遇到节流
我们在使用以上功能时,可能会结合节流,比如我们的侧边栏的收缩使用了CSS3
的transition
过渡效果的时候,这时候可能展开一次,会执行多个this.chartResize()
,这就需要我们使用节流来提供性能。
安装:
npm i lodash
element-resize-detector
中使用节流很简单:
import elementResizeDetector from 'element-resize-detector'
...
let erd = elementResizeDetector()
erd.listenTo(document.getElementById('testId'), _.throttle(this.chartResize), 300)
但是,如果我们在ResizeObserver
中这样使用就不起效果:
const resizeObserver = new ResizeObserver(() => {
_.throttle(this.chartResize(), 300) // chartResize()不走
_.throttle(this.chartResize(), 300)() // chartResize()可以执行了,但是throttle节流不起作用
})
resizeObserver.observe(document.getElementById('testId')
那么要如何实现节流呢?自己写一个节流总可以吧(参考之前的文章如何理解js中的函数节流和防抖):
canResize: true
...
const resizeObserver = new ResizeObserver(() => {
if (!this.canResize) {
return
}
this.canResize = false
setTimeout(() => {
this.chartResize() // 注意这里需要在这里执行,因为如果你有transition的话需要在transition之后再执行
this.canResize = true
}, 300)
})
resizeObserver.observe(document.getElementById('testId')
记得销毁
销毁可以选择在beforeDestroy
生命钩子中进行,通常很容易忘记,所以可以选择在监听的地方随手销毁:
...
resizeObserver.observe(document.getElementById('testId')
this.$once('hook:beforeDestroy', () => {
resizeObserver.disconnect()
})