Search code examples
javascripthighchartslinear-regression

Highcharts - linear regression that changes according to vertical line


I have a question that is a follow-up on this question here: Two synchronized vertical lines in highcharts

I just came across this nice example of how to draw a linear fit in Highcharts: https://codepen.io/mushigh/pen/ZEQxXOz

Now, my question is: using this live demo, how could I implement linear fits that change according to the drag of the line?

What I am looking for is:

  • Linear fit from the beginning until the first vertical line;
  • Linear fit from the first until the second vertical line;
  • And linear fit from the second vertical line until the end.

Since the vertical lines are draggable, I am not sure this is possible?


Update:

This extension might get things easier: https://github.com/streamlinesocial/highcharts-regression


Solution

  • Here is my attempt, please take a look at it: https://jsfiddle.net/BlackLabel/prq563Ly/

    1. We need to add the regression line on the initial chart load:

        events: {
          load() {
            let chart = this,
              newData = [];
      
            chart.series[0].data.forEach(d => {
              if (d.category > firstInitialX && d.category < secondInitialX) {
                newData.push([d.category, d.x])
              }
            });
      
            chart.addSeries({
              regression: true,
              name: 'Test input',
              color: 'rgba(223, 83, 83, .5)',
              data: newData,
              regressionSettings: {
                enableMouseTracking: false
              }
            })
          }
        }
      
    2. We need to update the regression line data after dragging the annotations:

      Highcharts.each(Highcharts.charts, function(chart) {
        if (chart !== thisChart) {
          chart.annotations[index].update({
            labels: [{
              point: {
                x: newX
              }
            }],
            shapes: [{
              points: [{
                x: newX,
                xAxis: 0,
                y: 0
              }, {
                x: newX,
                xAxis: 0,
                y: 1000
              }]
            }]
          });
      
      
        }
      
        let firstAnnotation = chart.annotations[0].shapes[0].points[0].x;
        let secondAnnoation = chart.annotations[1].shapes[0].points[0].x
        chart.series.forEach(s => {
          if (s.data.length !== 500) {
            s.remove()
          }
        })
      
        chart.series[0].data.forEach(d => {
          if (d.category > firstAnnotation && d.category < secondAnnoation) {
            newData.push([d.category, d.x])
          }
        });
        chart.addSeries({
          regression: true,
          name: 'Test input',
          color: 'rgba(223, 83, 83, .5)',
          data: newData,
          regressionSettings: {
            enableMouseTracking: false
          }
        })
      });
      }
      

    Let me know what do you think about this kind of solution. Feel free to improve it.