javascript - 当系列没有相同的时间值时,如何在工具提示中显示所有系列

标签 javascript echarts

我有一个显示多个时间序列的图表。不同的时间序列不会同时采样。有没有办法可以在工具提示中显示所有系列?在示例中,您可以看到所有系列都包含在前 2 个点的工具提示中,因为它们同时被采样。对于其余的点,仅包括 1 个系列。

var myChart = echarts.init(document.getElementById('main'));

var series = [{
    "name": "sensor 1",
    "data": [{
        "value": [
          "2019-02-20T11:47:44.000Z",
          22.2
        ]
      },
      {
        "value": [
          "2019-02-20T12:03:02.000Z",
          22.1
        ]
      },
      {
        "value": [
          "2019-02-20T12:18:19.000Z",
          22.15
        ]
      },
      {
        "value": [
          "2019-02-20T12:33:36.000Z",
          22.2
        ]
      },
      {
        "value": [
          "2019-02-20T12:48:53.000Z",
          22.15
        ]
      }
    ],
    "type": "line"
  },
  {
    "name": "sensor 2",
    "data": [{
        "value": [
          "2019-02-20T11:47:44.000Z",
          23.2
        ]
      },
      {
        "value": [
          "2019-02-20T12:03:02.000Z",
          23.1
        ]
      },
      {
        "value": [
          "2019-02-20T12:22:19.000Z",
          24.15
        ]
      },
      {
        "value": [
          "2019-02-20T12:39:36.000Z",
          21.2
        ]
      },
      {
        "value": [
          "2019-02-20T12:52:53.000Z",
          20.15
        ]
      }
    ],
    "type": "line"
  }
]

var option = {
  legend: {},
  tooltip: {
    trigger: 'axis',
  },
  xAxis: {
    type: 'time'
  },
  yAxis: {
    scale: true
  },
  series: series,
};

myChart.setOption(option);
<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/4.0.4/echarts.min.js"></script>

<div id="main" style="width: 500px;height:400px;"></div>

最佳答案

解决方案说明
如本文所述 feature request在 echarts 的 github 上,他们计划在 future 添加您正在寻找的内容。但目前,它仍然不受支持。
所以我找到了一个解决方法来显示工具提示 全部 系列,即使它们在axisPointer所在的确切x处没有值。为此,我使用了工具提示 formatter 可以定义为每次必须更改工具提示时调用的回调函数(即每次axisPointer在新值上移动时)并且您可以在其中指定自己的工具提示格式。
在这个函数中,您可以访问关于axisPointer 数据的每一条信息(尤其是在我们的例子中它的xAxis 值)。给定axisPointer的xAxis值,我们可以通过series并从该 xAxis 值中找到最接近的值。

formatter : (params) => {
   //The datetime where the axisPointer is
   var xTime = new Date(params[0].axisValue)
      
   //Create our custom tooltip and add to its top the dateTime where the axisPointer is
   let tooltip = `<p>${xTime.toLocaleString()}</p> `;
      
   //Go through each serie
   series.forEach((serie, index) => {
     //Find the closest value
     value = serie.data.reduce((prev, curr) => Math.abs(new Date(curr.value[0]).valueOf() - xTime.valueOf()) < Math.abs(new Date(prev.value[0]).valueOf() - xTime.valueOf()) ? curr : prev).value[1]
        
     /* Add a line in our custom tooltip */
     // Add the colored circle at the begining of the line
     tooltip += `<p><span style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color: ${myChart.getVisual({ seriesIndex: index }, 'color')}"></span>`
     // Add the serie's name and its value
     tooltip += `${serie.name} &emsp;&emsp; <b>${value}</b></p>`;
   });
   return tooltip;
}
完整代码
这是使用您的示例的完整代码:

var myChart = echarts.init(document.getElementById('main'));

var series = [{
    "name": "sensor 1",
    //step: "end",
    "data": [{
        "value": [
          "2019-02-20T11:47:44.000Z",
          22.2
        ]
      },
      {
        "value": [
          "2019-02-20T12:03:02.000Z",
          22.1
        ]
      },
      {
        "value": [
          "2019-02-20T12:18:19.000Z",
          22.15
        ]
      },
      {
        "value": [
          "2019-02-20T12:33:36.000Z",
          22.2
        ]
      },
      {
        "value": [
          "2019-02-20T12:48:53.000Z",
          22.15
        ]
      }
    ],
    "type": "line"
  },
  {
    "name": "sensor 2",
    //step: 'end',
    "data": [{
        "value": [
          "2019-02-20T11:47:44.000Z",
          23.2
        ]
      },
      {
        "value": [
          "2019-02-20T12:03:02.000Z",
          23.1
        ]
      },
      {
        "value": [
          "2019-02-20T12:22:19.000Z",
          24.15
        ]
      },
      {
        "value": [
          "2019-02-20T12:39:36.000Z",
          21.2
        ]
      },
      {
        "value": [
          "2019-02-20T12:52:53.000Z",
          20.15
        ]
      }
    ],
    "type": "line"
  }
]

option = {
  legend: {},
  tooltip: {
    trigger: 'axis',
    formatter : (params) => {
      //The datetime where the axisPointer is
      var xTime = new Date(params[0].axisValue)
      
      //Create our custom tooltip and add to its top the dateTime where the axisPointer is
      let tooltip = `<p>${xTime.toLocaleString()}</p> `;
      
      //Go through each serie
      series.forEach((serie, index) => {
        //Find the closest value
        value = serie.data.reduce((prev, curr) => Math.abs(new Date(curr.value[0]).valueOf() - xTime.valueOf()) < Math.abs(new Date(prev.value[0]).valueOf() - xTime.valueOf()) ? curr : prev).value[1]
        
        /* Add a line in our custom tooltip */
        // Add the colored circle at the begining of the line
        tooltip += `<p><span style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color: ${myChart.getVisual({ seriesIndex: index }, 'color')}"></span>`
        // Add the serie's name and its value
        tooltip += `${serie.name} &emsp;&emsp; <b>${value}</b></p>`;
      });
      return tooltip;
    }
  },
  xAxis: {
    type: 'time'
  },
  yAxis: {
    scale: true
  },
  series: series,
};

myChart .setOption(option)
<html>
  <body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.3.2/echarts.min.js"></script>
    <div id="main" style="width: 600px; height:400px;"></div>
  </body>
</html>

进一步的想法
  • 线性插值

  • 除了显示最接近的实点的值,我们还可以使用简单的线性插值来计算该值。
    Linear interpolation
    这是具有线性插值的格式化函数(不是最先进的,但有效)
    formatter : (params) => {
       var xTime = new Date(params[0].axisValue)
       let tooltip = `<p>${xTime.toLocaleString()}</p> `;
       series.forEach((serie, index) => {
         //Only works if series is chronologically sorted
         prev_point = serie.data.reduce((prev, curr) => new Date(curr.value[0]).valueOf() <= xTime.valueOf() ? curr : prev)
         next_point = serie.data.slice(0).reduce((prev, curr, i, arr) => {
           if(new Date(curr.value[0]).valueOf() >= xTime.valueOf()) {
             arr.splice(1);
           }
           return curr
         })
         var value = 0
         if(next_point.value[1] == prev_point.value[1]){
           value = next_point.value[1]
         }
         else {
           //Linear interpolation
           value = Math.round((prev_point.value[1] + (xTime.valueOf()/1000 - new Date(prev_point.value[0]).valueOf()/1000) * ((next_point.value[1] - prev_point.value[1]) / (new Date(next_point.value[0]).valueOf()/1000 - new Date(prev_point.value[0]).valueOf()/1000)))*10)/10
         }
         tooltip += `<p><span style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color: ${myChart.getVisual({ seriesIndex: index }, 'color')}"></span> ${serie.name} &emsp;&emsp; <b>${value}</b></p>`;
       });
       return tooltip;
    }
    
  • 将系列显示为步骤

  • 为了使其在视觉上更准确,您可以将系列显示为step: 'end'并获得最接近的先前值,而不仅仅是
    最接近的值,使用:
    value = serie.data.reduce((prev, curr) => new Date(curr.value[0]).valueOf() <= xTime.valueOf() ? curr : prev).value[1]
    
    这样做,工具提示中显示的值将与您在图表上看到的完全相同。
  • 业绩
  • reduce()方法在大型数据集上运行缓慢,因为它们遍历整个系列。例如,将其替换为二分搜索(二分搜索)将大大提高性能。
    如果有人有使其性能更高的想法,我会很感兴趣。

    关于javascript - 当系列没有相同的时间值时,如何在工具提示中显示所有系列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55238820/

    相关文章:

    javascript - 如何使用jCarousel放大 slider ?

    javascript - 检测 iframe 外部的点击

    javascript - echarts中如何将数字转换为货币?

    echarts - 如何手动选择调色板的颜色?

    javascript - 选项 :first-child isn't selecting the same in all cases

    javascript - 如何使用 python 从带有 javascript 的网页中获取表格内容?

    javascript - Echarts 和 bootstrap : responsive width

    javascript - 如何在轴线(x 轴)处显示数据(传递给图表的数组)的最后一个值?

    javascript - Canvas 不是由ReactEcharts创建的

    javascript - 获取 li 中每个单词的第一个字母