bumblebee
bumblebee

Reputation: 131

How to set X coordinate for each bar with react chart js 2?

I want to make a chart with min and max vertical lines and bars between them. I can't find information how to set bars' X coordinate or make custom line plot with vertical 'bars' instead of points. And also I don't understand how to scale X axis, why MAX is left-side MIN? Min=22.5, Max=24.5 plot

let plot_options = {
    showScale: true,
    pointDot: true,
    showLines: true,
    maintainAspectRatio: false,
    annotation: {
        annotations: [
            {
                type: 'line',
                mode: 'vertical',
                scaleID: 'y-axis-0',
                value: min,
                borderColor: 'red',
                borderWidth: 2,
                label: {
                    backgroundColor: 'red',
                    content: 'Min',
                    enabled: true,
                },
            },
            {
                type: 'line',
                mode: 'vertical',
                scaleID: 'y-axis-0',
                value: max,
                borderColor: 'red',
                borderWidth: 2,
                label: {
                    backgroundColor: 'red',
                    content: 'MAX',
                    enabled: true,
                },
            },
        ]
    },
    title: {
        display: true,
        text: plotHeader,
    },
    responsive: true,
    legend: {
        display: false,
    },
    scales: {
        xAxes: [{
            scaleLabel: {
                display: true,
                labelString: labelx
            },
            ticks: {
                min: min,
                max: max
            }
        }],
        yAxes: [{
            scaleLabel: {
                display: true,
                labelString: labely
            },
            ticks: {
                beginAtZero: true,
            },
        }]
    },
}

data = {
        barPercentage: 0.5,
        barThickness: 6,
        maxBarThickness: 8,
        minBarLength: 2,
        labels: labels,
        datasets: [{
                    data: values,
                    borderColor: BLUE,
                    backgroundColor: BLUE
                }]
      }
<Bar options={plot_options}  data={data} plugins={ChartAnnotation}  />

That's what I expect: plot2

Upvotes: 1

Views: 1915

Answers (1)

uminder
uminder

Reputation: 26150

This solution is based on this answer for the positioning of the bars on a linear x-axis.

You can further use the Plugin Core API to draw the vertical min and max lines with their labels directly on the canvas. The API offers a number of hooks that can be used to perform custom code. In your case, you could use the afterDraw hook together with CanvasRenderingContext2D.

Please take a look at the runnable code below and see how it works. It should not be too hard to make similar code work with react-chartjs-2.

new Chart("chart", {
  type: 'bar',
  plugins: [{
    afterDraw: chart => {
      let ctx = chart.chart.ctx;
      ctx.save();
      let xAxis = chart.scales['x-axis-0'];      
      let yAxis = chart.scales['y-axis-0'];      
      let dataset = chart.data.datasets[0];
      [dataset.min, dataset.max].forEach((v, i) => {      
        var x = xAxis.getPixelForValue(+v * 1000);
        ctx.fillStyle = 'red';
        ctx.font = '14px Arial';
        ctx.textAlign = 'center';        
        ctx.fillText(i == 0 ? 'Min' : 'Max', x, yAxis.top + 14);
        ctx.fillStyle = 'gray';
        ctx.font = '12px Arial';
        ctx.fillText(v, x, yAxis.bottom + 20);
        ctx.beginPath();
        ctx.moveTo(x, yAxis.top + 20);
        ctx.strokeStyle = 'red';
        ctx.lineTo(x, yAxis.bottom + 3);
        ctx.stroke();
      });
      ctx.restore();
    }
  }],  
  data: {
    datasets: [{
      min: 22.5,
      max: 24.5,
      data: [
        { x: '22.83', y: 18 },
        { x: '23.17', y: 15 },
        { x: '23.44', y: 13 },
        { x: '24.32', y: 20 }
      ],
      borderColor: 'blue',
      backgroundColor: 'blue',
      barThickness: 20
    }]
  },
  options: {
    legend: {
      display: false,
    },
    scales: {
      xAxes: [{
        offset: true,
        type: 'time',
        time: {
          parser: 'X',
          unit: 'millisecond',
          displayFormats: {
            millisecond: 'X'
          }
        },
        ticks: {
          source: 'data',
          min: '22.5',
          callback: (v, i, values) => values[i].value / 1000
        },
        gridLines: {
          display: false
        },
      }],
      yAxes: [{
        ticks: {
          beginAtZero: true,
          max: 22,
          stepSize: 2
        }
      }]
    }
  }
});
canvas {
  max-width: 500px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.min.js"></script>
<canvas id="chart" height="200"></canvas>

Upvotes: 1

Related Questions