Highcharts 是否可以添加真实的绘图线并显示与系列的交点?
我想知道是否有办法在图表上画一条线,并显示所有系列中与这条线相交的值 为此,我为系列数据标签创建了一个格式化程序,如果每个标签的x值是绘图线的x值,则该格式化程序会查找每个标签,然后仅显示数据标签Highcharts 是否可以添加真实的绘图线并显示与系列的交点?,highcharts,Highcharts,我想知道是否有办法在图表上画一条线,并显示所有系列中与这条线相交的值 为此,我为系列数据标签创建了一个格式化程序,如果每个标签的x值是绘图线的x值,则该格式化程序会查找每个标签,然后仅显示数据标签 plotOptions: { series: { dataLabels: { enabled: true,
plotOptions: {
series: {
dataLabels: {
enabled: true,
className: 'highcharts-data-label-box',
padding: 0,
formatter: function () {
if (valuesToShow.indexOf(this.x) > -1) {
return this.y;
} else {
return null;
}
}
}
}
这是我的演示:
希望找到一种方法,通过注释或其他成本较低的方法来实现相同的结果。可以使用
Highcharts.svgrender
制作自定义标签。然而,在重新绘制图表时需要额外的逻辑,因为标签会改变其位置,而更困难的是,当极端值发生变化时,数据分组近似不同的值
我设法做到了,你可以遵循以下方法:
point.events.中,单击callback从整个事件中查找x位置
一组点。您可以在chart.series.xData
array中找到它。
请注意,chart.series.processedXData
具有当前在图表上呈现的值-按数据分组
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 = [];
}
}
}
}
单击点时添加标签:
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 = [];
}
}
}
}
点:{
活动:{
单击(事件){
var chart=this.series.chart,
seriesLen=chart.series.length,
x=这个.x,
点索引,
点索引,
我
Y
注释,
阿布克斯,
绘图线;
absX=chart.series[0].xData.reduce(
(上一个、当前、指数)=>{
返回Math.abs(curr-x)
在渲染事件上重画标签:
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 = [];
}
}
}
}
图表:{
zoomType:'xy',
活动:{
render:function(){
var图表=此,
x,,
纽克斯,
纽伊,
实际价值,
阿布克斯,
点索引,
Y
if(chart.annotationColl&&chart.annotationColl.length){
chart.annotationColl.forEach(函数(注释,i){
if(annotation.svgElem){
annotation.svgElem.destroy();
}
absX=chart.series[0]。processedXData.reduce(
(上一个、当前、指数)=>{
返回Math.abs(curr-annotation.x)=chart.plotLeft&&newX
演示:
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 = [];
}
}
}
}
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 = [];
}
}
}
}