Highcharts 同步多个系列的多个图表上的工具提示

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

我正在尝试跨多个图表同步共享工具提示,每个图表都有多个系列。

问题出在下面的示例中,工具提示始终显示 3 系列,即使在该特定点仅存在两个系列。

1) 如何确保系列仅在实际存在时才显示在工具提示中?

2) 当我们移出图表时,如何确保工具提示关闭?

JSFiddle:https://jsfiddle.net/qoL7fx27/1/

小提琴同步代码:

$('#container').bind('mousemove touchmove touchstart', function (e) {
    var chart,
        point,
        i,
        event;

    for (i = 0; i < Highcharts.charts.length; i = i + 1) {
        chart = Highcharts.charts[i];
        var points = [];
        // Find coordinates within the chart
        event = chart.pointer.normalize(e.originalEvent);
        // Get the hovered point
        for(var j=0; j<chart.series.length; j++) {
           point = chart.series[j].searchPoint(event, true);
           points.push(point);  
        }

        chart.tooltip.refresh(points);

    }
});
javascript highcharts
3个回答
6
投票

这是我的解决方案。它对我来说非常有效。我根据多图表同步

进行了调整

演示在这里

effect

以下代码显示/隐藏工具提示并确保它们在

mousemove
mouseleave
上对齐。

请注意,我发现我只需要找到搜索到的第一个点并用它来显示/隐藏工具提示。这是因为我所有的时间序列都具有相同的 x 值。

$("#container").bind("mousemove mouseleave", function(e) {
  for (let i = 0; i < Highcharts.charts.length; ++i) {
    let hart = Highcharts.charts[i];
    let event = chart.pointer.normalize(e.originalEvent); // Find coordinates within the chart
    let point;
    for (let j = 0; j < chart.series.length && !point; ++j) {
      point = chart.series[j].searchPoint(event, true);
    }
    if (!point) return;

    if (e.type === "mousemove") {
       point.onMouseOver();
      chart.xAxis[0].drawCrosshair(event, point); // Show the crosshair
    } else {
      point.onMouseOut();
      chart.tooltip.hide(point);
      chart.xAxis[0].hideCrosshair();
    }

  }
});

继续重置

reset
功能,以禁止 HighCharts 重置点——我们接管控制权。

Highcharts.Pointer.prototype.reset = function() {
  return undefined;
};

4
投票

1) 如何确保系列仅在实际存在时才显示在工具提示中?

不良行为是由

searchPoint
函数引起的 - 即使 x 位置与其他点不匹配,它也会返回最近的点。因此,如果该系列只有一个点,那么总会找到它。

解决方案:

手动选择要在

tooltip.formatter
中显示的点:

        formatter: function() {
          var outputString = '';

          this.points.forEach(function(point) {
            if (point.x === this.x) {
              outputString += "<span style='color:" + point.color + "'>\u25CF</span> " + point.series.name + ": <b>" + point.y + "</b><br/>";
            }
          }, this);
          return outputString;
        }

API 参考: https://api.highcharts.com/highcharts/tooltip.formatter


2) 当我们移出图表时,如何确保工具提示关闭?

通过删除这些行来恢复默认的

Highcharts.Pointer.prototype.reset
功能:

Highcharts.Pointer.prototype.reset = function() {
  return undefined;
};


这两个问题的演示:https://jsfiddle.net/BlackLabel/2mxxrk5n/


更新:

我发布了第二个问题的错误答案。此代码隐藏工具提示:

$('#container').bind('mouseout', function(e) {
  Highcharts.charts.forEach(function(chart) {
    chart.tooltip.hide();
    // undo point highlight
    chart.series.forEach(function(series) {
        series.points.forEach((point) => point.setState(''));
    });
  });
});

您能告诉我如何突出显示每个图表中的相应点吗?截至目前,工具提示显示正确,但三个图表中的点未突出显示

本段亮点:

points.forEach(function(point_) {
  if (point_) {
    point_.highlight(e);
  }
}, this);

为了实现所需的行为,您必须提供用于过滤应突出显示的点的逻辑。这是一个针对这种特殊情况进行调整的非常简化的示例:

// provide a logic for filtering points
if(points[0] && points[1].x > 0) {
    points.pop(); // remove the unwanted point
}

0
投票

这些方法(全部源于同步图表的 Highcharts 演示)对我不起作用,原因很简单,我的图表采用 2x2 网格布局,显然因为这些方法依赖于鼠标事件和特定坐标,所以同步不会当图表并排(如我的情况)而不是全部在一个垂直对齐的列中时,它不起作用。

我采用了一种更简单的方法,使用内置点事件,并假设图表的 x 轴值全部相同(并且大概应该给定您想要同步它们的值),那么此方法将仅使用悬停-超过点的 x 值,使具有相同 x 值的其他点(在所有图表和系列中)也出现悬停。

这是所需的所有代码(不需要其他覆盖/自定义):

function syncActivePoints(hovPt) {
  for (let i = 0; i < Highcharts.charts.length; ++i) {
    let chart = Highcharts.charts[i];
    let point;
    for (let j = 0; j < chart.series.length; ++j) {
      point = chart.series[j].points[hovPt.x]
      if (!point) return;
      point.setState('hover');
      chart.tooltip.refresh(chart.series[j].data[hovPt.x]);
      chart.xAxis[0].drawCrosshair(null, point);
    }
  }
}

function clearActivePoints(outPt) {

  for (let i = 0; i < Highcharts.charts.length; ++i) {
    let chart = Highcharts.charts[i];
    chart.xAxis[0].hideCrosshair();
    chart.tooltip.hide();

    let point;
    for (let j = 0; j < chart.series.length; ++j) {
      point = chart.series[j].points[outPt.x]
      if (!point) return;
      point.setState();
    }
  }
}

   // this will attach those functions globally (i.e. to all charts)
   // otherwise, you can just add the events to each specfic chart config that you want the syncing behavior to apply to
Highcharts.setOptions({
  plotOptions: {
     series: {
        point: {
            events: {
                mouseOver: function () {
                  syncActivePoints(this);
                },
                mouseOut: function () {
                  clearActivePoints(this);
                },
              }
            }
          }
        }
});
© www.soinside.com 2019 - 2024. All rights reserved.