Search code examples
highchartsreact-highchartsangular2-highcharts

How to Add a Custom Box in Between Two Points in HighCharts


I have looked into the highcharts documentation and cannot find a way to render a custom box in between a line connected between two data points. Here's the ref of How I want it to be created. Please suggest me a way to come up with this implementation or is this feasible to create a UI like this using HighchartsMock Ref

I tried creating a box and placing it on the graph but it doesn't work


Solution

  • You can use Highcharts SVGRenderer to create such boxes with text. Using the chart.events.renderer() callback function you can generate and update labels that will be placed between points.

    Highcharts.chart('container', {
      chart: {
        type: 'line',
        events: {
          render: function() {
            const chart = this;
            chart.series.forEach(function(series) {
              const xAxis = series.xAxis,
                yAxis = series.yAxis;
    
              let prevPoint;
    
              series.points.forEach(function(point) {
                if (prevPoint) {
                  const growth = `Growth ${point.y - prevPoint.y}`,
                    x1 = xAxis.toPixels(point.x, true),
                    y1 = yAxis.toPixels(point.y, true),
                    x2 = xAxis.toPixels(prevPoint.x, true),
                    y2 = yAxis.toPixels(prevPoint.y, true),
                    labelX = chart.plotLeft + x2 + (x1 - x2) / 2,
                    labelY = chart.plotTop + y2 + (y1 - y2) / 2;
    
                                if (!point.customLabel) {
                                    point.customLabel = chart.renderer.label(growth, 0, 0).attr({
                                        fill: 'white',
                                        stroke: series.color,
                                        'stroke-width': 2,
                                        zIndex: 5,
                                        r: 12,
                                        padding: 6
                                    }).add();
                                }
                                
                                const labelBBox = point.customLabel.getBBox();
                                point.customLabel.attr({
                                    x: labelX - labelBBox.width / 2,
                                    y: labelY - labelBBox.height / 2,
                                    opacity: series.visible ? 1 : 0
                                });
                }
    
                prevPoint = point;
              })
            });
          }
        }
      },
      series: [{
        data: [2, 2.5, 3, 3, 4, 5],
            lineWidth: 3,
            marker: {
                symbol: 'square'
            }
      }]
    });
    <script src="https://code.highcharts.com/highcharts.js"></script>
    <script src="https://code.highcharts.com/modules/accessibility.js"></script>
    
    <div id="container"></div>

    Demo: https://jsfiddle.net/BlackLabel/hytckLxb/
    API: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer
    https://api.highcharts.com/highcharts/chart.events.render
    https://api.highcharts.com/class-reference/Highcharts.Axis#toPixels