ECharts multiple data views for adaptive size solution

Project scenario:

When making data views, we often encounter multiple data views. It is more troublesome to do self-adaptation in the case of multiple data views. Here is a detailed analysis of how to make them, and share my solutions and train of thought.


Define DOM container

Here we need to pay attention to one point. When defining a high-width DOM container, the width cannot be set to a fixed size, or the parent cannot be a fixed size. If it is a fixed width, even if it is redrawn, the width is the same, so it is impossible To achieve adaptive, in general, the height is fixed, and then the width is adaptive .

example:

<div ref="linechart" style="width:100%;height:400px;"></div>

If you want to realize the self-adaptation of the data view, you must first ensure that its DOM container is self-adaptive.

A single view of data for adaptive

There are more and simpler solutions for a single data view, so I won’t explain too much

1. Use window.onresize

let myChart = echarts.init(document.getElementById(dom))
window.onresize = function () {
    
    
    myChat.resize()
}

This is through the method myChart that comes with ECharts.
You initialize an echarts yourself. There is a method resize in myChart. Calling this method can realize redrawing and self-adaptation

To expand here, myChat.resize() can customize the size:

myChart.resize({
    
    
  width: 800,
  height: 400
});

The specific usage depends on the needs.

There is one more thing to pay attention to here, that is, this method can also realize the self-adaptation of multiple data views, but it is a bit stupid

let myChart1 = echarts.init(document.getElementById(dom1))
let myChart2 = echarts.init(document.getElementById(dom2))
window.onresize = function () {
    
    
 	myChat1.resize()
 	myChat2.resize()
}

2. Use window.addEventListener to add resize method

let myChart = echarts.init(document.getElementById(dom))
let sizeFun = function () {
    
    
 	myChat.resize()
}
window.addEventListener('resize', sizeFun )

I have also used this method. The biggest problem is that this function will still be executed when leaving this page. When the DOM does not exist in other pages, an error will be reported, and it is triggered very frequently. It is necessary to write an anti-shake throttle. Therefore, it is not recommended to use it, so I won’t explain too much here.

Multiple data views for adaptive

Here to share my thoughts:

1. Pass value through parent and child

I use a parent component first, and then divide these views into subcomponents one by one, listen to browser events in the parent component, and pass a defined value (I use resize: true here) when the window size changes For subcomponents, subcomponents perform redrawing when receiving.
The specific code will not be shown, because the problem of passing values ​​from parent to child is relatively simple, mainly to share the solution

2. Through encapsulation

This is the method I am currently using, but this method has certain limitations. It is to determine the requirements first and ensure that the data views used are similar. For example, line charts and histograms are used. This similar data view is here
insert image description here
. All of them use the line area chart, and when you click on an endpoint, you will switch to display the details of the field.

insert image description here

It is also possible to switch the histogram

insert image description here
data view

insert image description here
Here's why:

  1. Anyone who has used ECache knows that the code volume of this component is relatively large, especially in the case of multiple data views, the code redundancy is very large.
  2. Because I have packaged it well, I only need to modify the packaged components when I need to modify it, reducing maintenance costs
  3. Subsequent calls can be made directly when production is required

I will post how to encapsulate it in a later release
. Through encapsulation, we can solve this self-adaptive problem very simply.

      option = option1;
      option && myChart.setOption(option);
      //根据窗口的大小变动图表 --- 重点
      let listener = function(){
    
    
        myChart.resize()
      }
      EleResize.on(chartDom,listener)

EleResize

This JS is an adaptive JS for an ECharts chart I found online

// ECharts图表自适应JS
var EleResize = {
    
    
  _handleResize: function (e) {
    
    
    var ele = e.target || e.srcElement
    var trigger = ele.__resizeTrigger__
    if (trigger) {
    
    
      var handlers = trigger.__z_resizeListeners
      if (handlers) {
    
    
        var size = handlers.length
        for (var i = 0; i < size; i++) {
    
    
          var h = handlers[i]
          var handler = h.handler
          var context = h.context
          handler.apply(context, [e])
        }
      }
    }
  },
  _removeHandler: function (ele, handler, context) {
    
    
    var handlers = ele.__z_resizeListeners
    if (handlers) {
    
    
      var size = handlers.length
      for (var i = 0; i < size; i++) {
    
    
        var h = handlers[i]
        if (h.handler === handler && h.context === context) {
    
    
          handlers.splice(i, 1)
          return
        }
      }
    }
  },
  _createResizeTrigger: function (ele) {
    
    
    var obj = document.createElement('object')
    obj.setAttribute('style',
    'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden;opacity: 0; pointer-events: none; z-index: -1;')
    obj.onload = EleResize._handleObjectLoad
    obj.type = 'text/html'
    ele.appendChild(obj)
    obj.data = 'about:blank'
    return obj
  },
  _handleObjectLoad: function () {
    
    
    this.contentDocument.defaultView.__resizeTrigger__ = this.__resizeElement__
    this.contentDocument.defaultView.addEventListener('resize', EleResize._handleResize)
  }
}
if (document.attachEvent) {
    
     // ie9-10
  EleResize.on = function (ele, handler, context) {
    
    
    var handlers = ele.__z_resizeListeners
    if (!handlers) {
    
    
      handlers = []
      ele.__z_resizeListeners = handlers
      ele.__resizeTrigger__ = ele
      ele.attachEvent('onresize', EleResize._handleResize)
    }
    handlers.push({
    
    
      handler: handler,
      context: context
    })
  }
  EleResize.off = function (ele, handler, context) {
    
    
    var handlers = ele.__z_resizeListeners
    if (handlers) {
    
    
      EleResize._removeHandler(ele, handler, context)
      if (handlers.length === 0) {
    
    
        ele.detachEvent('onresize', EleResize._handleResize)
        delete ele.__z_resizeListeners
      }
    }
  }
} else {
    
    
  EleResize.on = function (ele, handler, context) {
    
    
  var handlers = ele.__z_resizeListeners
  if (!handlers) {
    
    
    handlers = []
    ele.__z_resizeListeners = handlers
    if (getComputedStyle(ele, null).position === 'static') {
    
    
      ele.style.position = 'relative'
    }
    var obj = EleResize._createResizeTrigger(ele)
    ele.__resizeTrigger__ = obj
    obj.__resizeElement__ = ele
  }
  handlers.push({
    
    
    handler: handler,
    context: context
    })
  }
  EleResize.off = function (ele, handler, context) {
    
    
    var handlers = ele.__z_resizeListeners
    if (handlers) {
    
    
      EleResize._removeHandler(ele, handler, context)
      if (handlers.length === 0) {
    
    
        var trigger = ele.__resizeTrigger__
        if (trigger) {
    
    
          trigger.contentDocument.defaultView.removeEventListener('resize', EleResize._handleResize)
          ele.removeChild(trigger)
          delete ele.__resizeTrigger__
        }
        delete ele.__z_resizeListeners
      }
    }
  }
}
export {
    
    EleResize} 

Import this JS into the page and use it directly.

Guess you like

Origin blog.csdn.net/weixin_44748171/article/details/128912400