Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Range Highlighting of Background in Chart.js

From this question I'm looking to turn into a multiple range highlight

But there 1 annoying bug I didn't succeed to solve

  • background is superposing, if you uncheck a dataset on the top, background alpha change

Here my work so far: https://jsfiddle.net/742zut83/588/

Why the custom draw function executed for each dataset? Once highlights done originalLineDraw is returned

draw : function() {
  var chart = this.chart;
  // Get the object that determines the region to highlight.
  var yHighlightRanges = chart.config.data.yHighlightRanges;

  let ctx = chart.chart.ctx;

  yHighlightRanges.forEach(function(Range) {

    var yRangeBegin = Range.begin;
    var yRangeEnd = Range.end;

    var xaxis = chart.scales['x-axis-0'];
    var yaxis = chart.scales['y-axis-0'];

    var yRangeBeginPixel = yaxis.getPixelForValue(yRangeBegin);
    var yRangeEndPixel = yaxis.getPixelForValue(yRangeEnd);

    ctx.save();

    // The fill style of the rectangle we are about to fill.
    ctx.fillStyle = Range.rgb;
    // Fill the rectangle that represents the highlight region. The parameters are the closest-to-starting-point pixel's x-coordinate,
    // the closest-to-starting-point pixel's y-coordinate, the width of the rectangle in pixels, and the height of the rectangle in pixels, respectively.
    ctx.fillRect(xaxis.left, Math.min(yRangeBeginPixel, yRangeEndPixel), xaxis.right - xaxis.left, Math.max(yRangeBeginPixel, yRangeEndPixel) - Math.min(yRangeBeginPixel, yRangeEndPixel));

    ctx.restore();
  });

  // Apply the original draw function for the line chart.
  originalLineDraw.apply(this, arguments);
}

var ctx = document.getElementById("myChart");

// The original draw function for the line chart. This will be applied after we have drawn our highlight range (as a rectangle behind the line chart).
var originalLineDraw = Chart.controllers.line.prototype.draw;
// Extend the line chart, in order to override the draw function.
Chart.helpers.extend(Chart.controllers.line.prototype, {
  draw : function() {
    var chart = this.chart;
    // Get the object that determines the region to highlight.
    var yHighlightRanges = chart.config.data.yHighlightRanges;

    let ctx = chart.chart.ctx;
    
    yHighlightRanges.forEach(function(Range) {
    
      var yRangeBegin = Range.begin;
      var yRangeEnd = Range.end;

      var xaxis = chart.scales['x-axis-0'];
      var yaxis = chart.scales['y-axis-0'];

      var yRangeBeginPixel = yaxis.getPixelForValue(yRangeBegin);
      var yRangeEndPixel = yaxis.getPixelForValue(yRangeEnd);

      ctx.save();

      // The fill style of the rectangle we are about to fill.
      ctx.fillStyle = Range.rgb;
      // Fill the rectangle that represents the highlight region. The parameters are the closest-to-starting-point pixel's x-coordinate,
      // the closest-to-starting-point pixel's y-coordinate, the width of the rectangle in pixels, and the height of the rectangle in pixels, respectively.
      ctx.fillRect(xaxis.left, Math.min(yRangeBeginPixel, yRangeEndPixel), xaxis.right - xaxis.left, Math.max(yRangeBeginPixel, yRangeEndPixel) - Math.min(yRangeBeginPixel, yRangeEndPixel));

      ctx.restore();
    });

    // Apply the original draw function for the line chart.
    originalLineDraw.apply(this, arguments);
  }
});

var myChart = new Chart(ctx, {
  type: 'line',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [
        {
        label: 'Season 1',
        data: [12, 17, 3, 5, 9, 3],
        fill: false,
        borderColor: 'rgba(0, 200, 0, 1)'
        },
      {
        label: 'Season 2',
        data: [5, 14, 3, 15, 9, 13],
        fill: false,
        borderColor: 'rgba(200, 0, 0, 1)'
        }
    ],
    // This, if it exists at all, defines the highlight region.
    yHighlightRanges : [
        {
        begin: 0,
        end: 6,
        rgb: 'rgba(100, 100, 100, 0.2)'
      },
      {
        begin: 6,
        end: 12,
        rgb: 'rgba(200, 100, 200, 0.2)'
      },
      {
        begin: 12,
        end: 18,
        rgb: 'rgba(0, 100, 200, 0.2)'
      }
    ]
  },
  options: {
    scales: {
      yAxes: [{
        ticks: {
          beginAtZero:true
        }
      }]
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<canvas id="myChart" width="400" height="400"></canvas>
like image 630
Dylan Delobel Avatar asked Mar 17 '18 22:03

Dylan Delobel


1 Answers

Why not using simply the annotation plugin?

Here is your example with annotation plugin, using Box annotations:

var ctx = document.getElementById("myChart");

var myChart = new Chart(ctx, {
  type: 'line',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [
    	{
        label: 'Season 1',
        data: [12, 17, 3, 5, 9, 3],
        fill: false,
        borderColor: 'rgba(0, 200, 0, 1)'
    	},
      {
        label: 'Season 2',
        data: [5, 14, 3, 15, 9, 13],
        fill: false,
        borderColor: 'rgba(200, 0, 0, 1)'
    	}
    ]
  },
  options: {
    scales: {
      yAxes: [{
      	id: 'y-axis-1',
        ticks: {
          beginAtZero:true
        }
      }]
    },
    annotation: {
      drawTime: "afterDraw",
      annotations: [{
      	id: 'box1',
        type: 'box',
        yScaleID: 'y-axis-1',
        yMin: 0,
        yMax: 6,
        backgroundColor: 'rgba(100, 100, 100, 0.2)',
        borderColor: 'rgba(100, 100, 100, 0.2)',
      },{
      	id: 'box2',
        type: 'box',
        yScaleID: 'y-axis-1',
        yMin: 6,
        yMax: 12,
        backgroundColor: 'rgba(200, 100, 200, 0.2)',
        borderColor: 'rgba(200, 100, 200, 0.2)',
      },{
      	id: 'box3',
        type: 'box',
        yScaleID: 'y-axis-1',
        yMin: 12,
        yMax: 18,
        backgroundColor: 'rgba(0, 100, 200, 0.2)',
        borderColor: 'rgba(0, 100, 200, 0.2)',
      }]
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-annotation/0.5.7/chartjs-plugin-annotation.min.js"></script>

<canvas id="myChart" width="400" height="400"></canvas>

And this is your fiddle updated: https://jsfiddle.net/beaver71/50L21shp/

like image 123
beaver Avatar answered Sep 20 '22 05:09

beaver