我正在尝试跨多个图表同步共享工具提示,每个图表都有多个系列。
问题出在下面的示例中,工具提示始终显示 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);
}
});
这是我的解决方案。它对我来说非常有效。我根据多图表同步
进行了调整以下代码显示/隐藏工具提示并确保它们在
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;
};
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
}
这些方法(全部源于同步图表的 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);
},
}
}
}
}
});