Пользовательские метки могут быть сделаны с использованием Highcharts.SVGRenderer
. Однако при перерисовке диаграммы требуется дополнительная логика, поскольку метки меняют свои позиции, а более сложная группировка данных приближается к другим значениям при изменении экстремумов.
Мне удалось это сделать, вы можете придерживаться этого подхода:
- в
point.events.click
обратном вызове найти позицию x из целого
группа точек. Вы можете найти его в массиве chart.series.xData
.
Обратите внимание, что chart.series.processedXData
имеет значения, которые в данный момент отображаются на диаграмме - сгруппированы по dataGrouping.
- рендеринг plotLine в позиции x
- используйте
chart.renderer.text
, чтобы добавить метку для каждой серии. Спасти
ссылка на созданный ярлык.
- в обратном вызове
chart.events.render
уничтожает существующие элементы SVG
для каждой метки и перерисовать его с новой позицией и новым значением, когда dataGrouping изменит его.
Код:
добавление меток при нажатии точки:
point: {
events: {
click(event) {
var chart = this.series.chart,
seriesLen = chart.series.length,
x = this.x,
pointIndex,
pointIndexAbs,
i,
y,
annotation,
absX,
plotLine;
absX = chart.series[0].xData.reduce(
(prev, curr, index) => {
return Math.abs(curr - x) < Math.abs(prev - x) ? curr : prev;
});
plotLine = chart.xAxis[0].addPlotLine({
color: "#000",
width: 1,
value: absX,
id: absX
});
for (i = 0; i < seriesLen - 1; i++) {
pointIndex = chart.series[i].processedXData.indexOf(x);
if (pointIndex !== -1) {
y = chart.series[i].processedYData[pointIndex];
annotation = chart.renderer.text(
y.toFixed(4).toString(),
chart.xAxis[0].toPixels(absX) - 25,
chart.yAxis[0].toPixels(y)
)
.css({
fill: 'red',
fontSize: '10px'
})
.attr({
zIndex: 6
})
.add();
chart.annotationColl.push({
svgElem: annotation,
x: absX,
y: y,
seriesIndex: i,
plotLine: plotLine
});
}
}
return false;
}
}
}
перерисовать метки на событии рендеринга:
chart: {
zoomType: 'xy',
events: {
render: function() {
var chart = this,
x,
newX,
newY,
actualValue,
absX,
pointIndex,
y;
if (chart.annotationColl && chart.annotationColl.length) {
chart.annotationColl.forEach(function(annotation, i) {
if (annotation.svgElem) {
annotation.svgElem.destroy();
}
absX = chart.series[0].processedXData.reduce(
(prev, curr, index) => {
return Math.abs(curr - annotation.x) < Math.abs(prev - annotation.x) ? curr : prev;
});
pointIndex = chart.series[annotation.seriesIndex].processedXData.indexOf(absX);
y = chart.series[annotation.seriesIndex].processedYData[pointIndex];
newX = chart.xAxis[0].toPixels(annotation.x) - 25;
newY = chart.yAxis[0].toPixels(y);
if (newX >= chart.plotLeft && newX < chart.plotLeft + chart.plotWidth - 35) {
annotation.svgElem = chart.renderer.text(
y.toFixed(4).toString(),
newX,
newY
)
.css({
fill: 'red',
fontSize: '10px'
})
.attr({
zIndex: 6
})
.add();
} else {
annotation.svgElem = null;
}
});
} else {
chart.annotationColl = [];
}
}
}
}
Демо-версия:
Ссылка API: