javascripttypescriptchartsecharts

How can I use two different data sources for the main chart and dataZoom in Apache ECharts?


I'm working with Apache ECharts and trying to use two different data sources: one for the main chart and another for the dataZoom preview.

Due to the large amount of data, I've reduced the resolution over longer time periods to minimize the data sent to the client. However, I want the main chart to display a much higher resolution when the user zooms in on a smaller time range.

This screenshot shows my issue

Unfortunately, I can't figure out how to use two different data sources for the main chart and the dataZoom overview. Does anyone have any suggestions on how to achieve this?

Basically the dataZoom chart should always show the complete chart, and the main plot should load and display the selected area.

I have created this example in the online editor of ECharts, to demonstrate my issue


Solution

  • The best way I can think of is using a helper xAxis with type: 'category', show: false and your time data (formatted in some way) as data property. Now you only need a dataZoom on this axis and use the dataZoom event to fetch new data.

    Example:

    function generateDateRandomPairs() {
      const dateRandomPairs = [];
    
      const date = new Date();
    
      var j = 1;
      for (let i = 0; i < 10000; i++) {
        const number = j;
        if (i % 10 == 0) {
          j++;
        }
        dateRandomPairs.push([date.toISOString(), number]);
        date.setSeconds(date.getSeconds() + 60);
      }
    
      return dateRandomPairs;
    }
    
    // All data but with lower resolution
    // Should be used in dataZoom
    var allData = generateDateRandomPairs();
    
    // Data with high resolution
    // Would be loaded through Ajax in real world
    var mainPlotData = allData.slice(50, 200);
    
    option = {
      tooltip: {
        trigger: 'axis'
      },
      xAxis: [
        {
          type: 'time',
          name: 'Date'
        },
        {
          type: 'category',
          data: allData.map((point) => point[0]),
          show: false
        }
      ],
      yAxis: [
        {
          gridIndex: 0,
          type: 'value',
          name: 'Value',
        }
      ],
      series: [
        {
          name: 'High-Res Data',
          type: 'line',
          xAxisIndex: 0,
          yAxisIndex: 0,
          data: mainPlotData
        }
      ],
      dataZoom: [
        {
          type: 'slider',
          xAxisIndex: 1,
          endValue: 200,
          realtime: false
        }
      ]
    };
    
    myChart.on('dataZoom', function(params) {
      const startIndex = Math.round((params.start / 100) * allData.length);
      const endIndex = Math.round((params.end / 100) * allData.length);
      let resolution = Math.ceil((endIndex - startIndex) / 200);
      resolution = resolution === 0 ? 1 : resolution;
      const data = allData.slice(startIndex, endIndex).filter((x, i) => i % resolution === 0);
      myChart.setOption({series: [{data: data}]})
    });