Apache ECharts 如何在带有触发轴的工具提示中包含悬停系列?

问题描述 投票:0回答:1

我正在绘制一个在 x 时间轴上具有多个布尔自定义系列的数字线系列。布尔自定义系列的渲染方式为每个布尔系列创建水平泳道,并且泳道的不透明度由值决定。因为工具提示触发器是轴,所以我只能看到数据点存在时的布尔值(自定义系列渲染项目的开始)。无论我将鼠标悬停在图表上的哪个位置,如何在工具提示中包含所有布尔系列的布尔值,以便我可以看到线条系列的数值以及与悬停位置相交的所有布尔系列值给定时间点?

Apache ECharts 自定义示例:链接

在上面链接的 Apache Echarts 自定义示例中悬停特定时间点的图像

期望:当我将鼠标悬停在特定时间点上时,我期望看到线系列中的数值以及与给定时间点的悬停位置相交的自定义系列中的布尔值。在我提供的图像中,我希望在工具提示中看到这些值:84.5、false、false。

我尝试过的:

  • 添加带有触发器“item”的工具提示规则自定义系列。这不起作用,因为数值不再包含在工具提示中。我相信会发生这种情况,因为一旦自定义布尔系列悬停,它就会优先于其他工具提示规则,并仅显示悬停系列的值。

我考虑过的:

  • 对布尔数据使用堆叠区域阶梯线系列,其中 false 等于 0,true 等于 1。我相信这可能会导致一些问题。首先,我想将这些系列用于其他类型的数据,这些数据将具有比布尔值更多的状态。例如:真、假、空。在这种情况下,我将需要这种状态的多种不同的视觉表示。我相信堆叠区域阶梯线系列只能实现 2 种状态。有阴影和没有阴影。其次,当数据为假(等于 0)时,我无法控制该区域的着色方式。
javascript echarts
1个回答
0
投票

我想到的最简单的解决方案是将所有线点添加到布尔数据数组中。由于这给出了多个布尔值的间隔相等,因此我稍微更改了渲染函数,仅从布尔值发生变化的点进行渲染。

示例

const NUMBER_DATA = [
  [new Date('2024-06-13T00:00:12.000Z'), 78.1],
  [new Date('2024-06-13T00:04:45.000Z'), 76.3],
  [new Date('2024-06-13T00:07:24.000Z'), 72.4],
  [new Date('2024-06-13T00:12:13.000Z'), 73.3],
  [new Date('2024-06-13T00:17:43.000Z'), 84.5],
  [new Date('2024-06-13T00:21:56.000Z'), 81.0],
  [new Date('2024-06-13T00:26:35.000Z'), 77.9],
  [new Date('2024-06-13T00:29:32.000Z'), 65.4],
  [new Date('2024-06-13T00:32:04.000Z'), 51.3],
  [new Date('2024-06-13T00:35:27.000Z'), 44.2],
  [new Date('2024-06-13T00:39:51.000Z'), 39.8]
];
const BOOLEAN_DATA1 = [
  [new Date('2024-06-13T00:00:12.000Z'), true],
  [new Date('2024-06-13T00:11:13.000Z'), false],
  [new Date('2024-06-13T00:24:37.000Z'), true],
  [new Date('2024-06-13T00:30:11.000Z'), false],
  [new Date('2024-06-13T00:32:50.000Z'), true],
  [new Date('2024-06-13T00:39:51.000Z'), false]
];
const BOOLEAN_DATA2 = [
  [new Date('2024-06-13T00:00:12.000Z'), false],
  [new Date('2024-06-13T00:07:52.000Z'), true],
  [new Date('2024-06-13T00:13:48.000Z'), false],
  [new Date('2024-06-13T00:20:11.000Z'), true],
  [new Date('2024-06-13T00:33:23.000Z'), false],
  [new Date('2024-06-13T00:39:51.000Z'), true]
];

function addPointsToBoolData(booldata) {
  let index = 0;
  for (let datapoint of NUMBER_DATA) {
    if (booldata[index] === undefined) {
      booldata.push([datapoint[0], booldata[-1][1]]);
      continue;
    }
    
    while (booldata[index][0] < datapoint[0]) {
      index++;
    }
    
    if (datapoint[0].getTime() === booldata[index][0].getTime()) {
      index++;
      continue;
    }
    
    if (index === 0) {
      booldata.splice(index, 0, [datapoint[0], booldata[index][1]]);
    } else {
      booldata.splice(index, 0, [datapoint[0], booldata[index-1][1]]);
    }
  }
}
addPointsToBoolData(BOOLEAN_DATA1)
addPointsToBoolData(BOOLEAN_DATA2)

function getRenderItem(categoryIndex, data) {
  return function renderItem(params, api) {
    const date = api.value(0);
    const val = api.value(1);

    if (params.dataIndex === data.length - 1) {
      return null;
    }

    if (data[params.dataIndex - 1] && data[params.dataIndex - 1][1] === val) {
      return null;
    }
    
    let index = 0;
    let nextVal = val;
    while (data[params.dataIndex + index + 1] && val === nextVal) {
      index++;
      nextVal = data[params.dataIndex + index][1];
    }
    
    const nextDate = data[params.dataIndex + index][0];

    const start = api.coord([date, categoryIndex]);
    const end = api.coord([nextDate, categoryIndex]);
    const height = api.size([0, 1])[1];

    const opacity = val ? 1 : 0.75;

    var rectShape = echarts.graphic.clipRectByRect(
      {
        x: start[0],
        y: start[1] - height / 2,
        width: end[0] - start[0],
        height: height
      },
      {
        x: params.coordSys.x,
        y: params.coordSys.y,
        width: params.coordSys.width,
        height: params.coordSys.height
      }
    );
    return (
      rectShape && {
        type: 'rect',
        transition: ['shape'],
        shape: rectShape,
        style: {
          fill: api.visual('color'),
          opacity
        }
      }
    );
  };
}
option = {
  tooltip: {
    trigger: 'axis',
    valueFormatter: (value) => (typeof value === 'number' ? value : value[1]),
    axisPointer: {
      axis: 'x'
    }
  },
  xAxis: {
    type: 'time'
  },
  yAxis: [
    {
      type: 'value'
    },
    {
      type: 'category',
      show: false,
      data: ['Boolean Data 1', 'Boolean Data 2']
    }
  ],
  series: [
    {
      type: 'line',
      yAxisIndex: 0,
      data: NUMBER_DATA
    },
    {
      type: 'custom',
      yAxisIndex: 1,
      renderItem: getRenderItem(0, BOOLEAN_DATA1),
      data: BOOLEAN_DATA1
    },
    {
      type: 'custom',
      yAxisIndex: 1,
      renderItem: getRenderItem(1, BOOLEAN_DATA2),
      data: BOOLEAN_DATA2
    }
  ]
};
© www.soinside.com 2019 - 2024. All rights reserved.