Highcharts 是否可以添加真实的绘图线并显示与系列的交点?

Highcharts 是否可以添加真实的绘图线并显示与系列的交点?,highcharts,Highcharts,我想知道是否有办法在图表上画一条线,并显示所有系列中与这条线相交的值 为此,我为系列数据标签创建了一个格式化程序,如果每个标签的x值是绘图线的x值,则该格式化程序会查找每个标签,然后仅显示数据标签 plotOptions: { series: { dataLabels: { enabled: true,

我想知道是否有办法在图表上画一条线,并显示所有系列中与这条线相交的值

为此,我为系列数据标签创建了一个格式化程序,如果每个标签的x值是绘图线的x值,则该格式化程序会查找每个标签,然后仅显示数据标签

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
    具有当前在图表上呈现的值-按数据分组
  • 在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 = [];
          }
    
        }
      }
    }
    
    单击点时添加标签:

    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 = [];
          }
    
        }
      }
    }
    
    API参考:

    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 = [];
          }
    
        }
      }
    }