Acceptable Range Highlighting of Background in Chart.js 2.0

前端 未结 5 969
小鲜肉
小鲜肉 2020-12-30 07:13

I\'m working on building a simple line chart using Chart.js (the 2.0.2 beta) and I\'d like to highlight a particular range of the chart\'s background to highlight an \"accep

相关标签:
5条回答
  • 2020-12-30 07:51

    You can use Box Annotations from chartjs-plugin-annotation (official from chartjs). Specify yMin & yMax, and leave xMin & xMax undefined so that it fills the entire x-axis.

    Example code:

    var chartData = {
      labels: ["January", "February", "March", "April", "May", "June", "July"],
      datasets: [{
        type: "line",
        label: "Dataset 1",
        data: [10,-20,40,45,15,5,20,20],
        fill: false
      }]
    };
    
    var ctx = document.getElementById("chart");
    var chart = new Chart(ctx, {
      type: "bar",
      data: chartData,
      options: {
        annotation: {
          annotations: [{
            drawTime: "beforeDatasetsDraw",
            type: "box",
            xScaleID: "x-axis-0",
            yScaleID: "y-axis-0",
            borderWidth: 0,
            yMin: 25,
            yMax: 40,
            backgroundColor: "rgba(46, 204, 113,0.3)"
          }]
        }
      }
    });
    <canvas id="chart"></canvas>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.4.0/Chart.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-annotation/0.5.7/chartjs-plugin-annotation.js"></script>

    0 讨论(0)
  • 2020-12-30 07:58

    this code will be helpful

    var bgdata = {
    
            datasets: [
            {
            label: "Average Hourly Blood Glucose Reading", 
            fill: false,
    
           data: [
                {
                    "y": 213,
                    "x": 0,
                    "backgroundColor": "rgba(29, 9, 158,0.2)",
                "label":"12:00 AM"
    
                },
                {
                    "y": 199,
                    "x": 1,
                    "backgroundColor": "rgba(29, 9, 158,0.4)",
                "label":"1:00 AM"
    
                },
            {
                    "y": 208,
                    "x": 2,
                    "backgroundColor": "rgba(29, 9, 158,0.6)",
                "label":"2:00 AM"
    
                }
            ]
                }
            ]
         };
    
    0 讨论(0)
  • 2020-12-30 08:07

    The following implements the required functionality in Chart.js 2.* (uses Chart.js 2.1.4, which is the current version at the time of writing):

    https://jsfiddle.net/742zut83/22/

    The implementation is based on extending the line chart type and overriding the draw function. The new draw function checks whether within the line chart's data exists the following, which defines the y-range to highlight:

    yHighlightRange : {
      begin: 6.5,
      end: 12.5
    }
    

    If it does not exist, then the original draw function is called. If it exists, then a rectangle spanning from the left to the right and within the y-range specified is drawn. After the rectangle is drawn, the original draw function is called, in order to complete the drawing of the line chart.

    The first implementation did not draw a rectangle. Among other deficiencies it had, it drew all pixel-lines separately. Like TV scanlines (yes, I'm old). But the old code is here (in case you care about line drawing):

    https://jsfiddle.net/742zut83/17/

    The current code is as follows:

    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 yHighlightRange = chart.config.data.yHighlightRange;
    
        // If the object exists.
        if (yHighlightRange !== undefined) {
          var ctx = chart.chart.ctx;
    
          var yRangeBegin = yHighlightRange.begin;
          var yRangeEnd = yHighlightRange.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 = 'rgba(0, 255, 0, 0.3)';
          // 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: '# of Votes',
          data: [12, 19, 3, 5, 2, 3],
        }],
        // This, if it exists at all, defines the highlight region.
        yHighlightRange: {
          begin: 6.5,
          end: 12.5
        }
      },
      options: {
        scales: {
          yAxes: [{
            ticks: {
              beginAtZero: true
            }
          }]
        }
      }
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.4/Chart.min.js"></script>
    <canvas id="myChart" width="400" height="400"></canvas>

    0 讨论(0)
  • 2020-12-30 08:12

    Chart.js v2.0.2 doesn't provide this functionality out of the box.

    You can however extend or create new type constructors. See http://www.chartjs.org/docs/#advanced-usage-extending-existing-chart-types.

    You should be able to implement either an area type that is bounded by two lines, or you could create a threshold band similar to xnakos answer.

    0 讨论(0)
  • 2020-12-30 08:14

    I ended up placing @xnakos code inside componentDidUpdate() callback. The advantage is that you should not set the opacity of the highlighted area to visible the graph like ctx.fillStyle = 'rgba(0, 255, 0, 0.3)' and no need to overwrite the fill method in @xnakos answer.

    componentDidUpdate() {
      Chart.pluginService.register({
        beforeDraw: (chartInstance) => {
          var chart = chartInstance;
          // Get the object that determines the region to highlight.
          var yHighlightRange = chart.config.data.yHighlightRange;
    
          // If the object exists.
          if (yHighlightRange !== undefined) {
            var ctx = chart.chart.ctx;
    
            var yRangeBegin = yHighlightRange.begin;
            var yRangeEnd = yHighlightRange.end;
    
            var xaxis = chart.scales["x-axis"];
            var yaxis = chart.scales["y-axis"];
    
            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 = yHighlightRange.fillStyle;
            // 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();
          }
        },
      });
    }
    

    and the data object is as follow,

    data = {
      labels: [],
      datasets: [...],
      yHighlightRange: {
        begin: 50,
        end: 100,
        fillStyle: "#7DD8D2",
      },
    };
    
    0 讨论(0)
提交回复
热议问题