Max J.
Max J.

Reputation: 175

How to set vertical lines for new day on x-axis in ChartJS v3.x

I have a graph that displays data of the last 2h, 8h, 24h, or 48h. This can be changed via buttons on the webpage. When the timespan includes midnight, I would like to display vertical lines with little labels (maybe at hover) at midnight displaying the date (or day of the week) of the upcoming day.

I have not found any resources on how to do that in Chartjs 3. How would I do such a task?Desired output, simplified

This is how I create the graph. "time" is an array of epoch times:

chart = new Chart(
    document.getElementById('Chart'),
    {
        type: 'line',
        data:
        {
            labels: time,
            datasets: [
            {
                label: dataObjects[start].label,
                backgroundColor: dataObjects[start].backgroundColor,
                borderColor: dataObjects[start].borderColor,
                fill: dataObjects[start].fill,
                data: dataObjects[start].data,
                yAxisID: 'A',
            }]
        },
        options: {
            elements: {point: {radius: 0.5, borderWidth: 1},
                       line: {borderWidth: 3}},
            maintainAspectRatio: false,
            scales: {
                x:
                {
                    //max: last_time,
                    type: "time",
                    grid: {borderColor: color.time},
                    ticks: {color: color.time},
                    time: {
                        unit: 'hour',
                        tooltipFormat: 'dd.MM. HH:mm',
                        displayFormats: {
                            second: "HH:mm",
                            minute: "HH:mm",
                            hour: "HH:mm",
                            day: "d.MM.",
                            week: "d.MM."
                        },
                    }
                },
                A:
                {
                    type: 'linear',
                    grid: {borderColor: color.time},
                    position: 'left',
                    ticks: {color: color.time},
                    suggestedMin: dataObjects[start].suggestedMin,
                    suggestedMax: dataObjects[start].suggestedMax,
                    title: {text: dataObjects[start].text,
                            display: true,
                            color: color.time}
                }
            },
            plugins: {
                legend: {display: false}
            }
        }
});

Upvotes: 3

Views: 3883

Answers (3)

mmkm
mmkm

Reputation: 89

This is my solution, it uses Luxon to split a range of dates into an interval of days, changes each of those DateTime instances to midnight, then gets a timestamp value from them.

The for loop builds a dictionary of line annotations from the array of timestamps, and assigns that to the ChartJS annotation plugin.

edit: I'm calling this function in created() to update on redraws

drawAnnotations() {
  let annotations = {};
  let arr = this.chartData.datasets[0].data;
  let startDate = DateTime.fromISO(arr[0].x);
  let endDate = DateTime.fromISO(arr[arr.length - 1].x);

  let intervals = Interval.fromDateTimes(
    startDate.startOf("day"),
    endDate.endOf("day")
  )
    .splitBy({ day: 1 })
    .map((date) => date.start.set({ hour: 0 }).valueOf());

  for (let d of intervals) {
    annotations[d] = {
      type: "line",
      xMin: d,
      xMax: d,
      borderColor: "rgb(255, 99, 132)",
      borderWidth: 2,
    };
  }

  this.chartOptions.plugins.annotation.annotations = annotations;
},

Upvotes: 0

LeeLenalee
LeeLenalee

Reputation: 31371

You could use the annotation plugin. In your case you will need to change the string I used to determine the correct x axis placement to the timestamp of the midnight you want and then you have a line there:

const options = {
  type: 'line',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
      label: '# of Votes',
      data: [12, 19, 3, 5, 2, 3],
      borderColor: 'pink'
    }]
  },
  options: {
    plugins: {
      annotation: {
        annotations: {
          line1: {
            type: 'line',
            xMin: 'Green',
            xMax: 'Green',
            label: {
              enabled: true,
              content: 'end value'
            }
          },
          line2: {
            type: 'line',
            xMin: 'Blue',
            xMax: 'Blue',
            label: {
              enabled: true,
              content: 'begin value'
            }
          }
        }
      }
    }
  }
}

const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
  <canvas id="chartJSContainer" width="600" height="400"></canvas>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-annotation/1.3.1/chartjs-plugin-annotation.min.js"></script>
</body>

Upvotes: 2

Alyf Mendon&#231;a
Alyf Mendon&#231;a

Reputation: 151

You can use a mixed chart to create this graph mixing a line chart and a bar chart.

Here you can view one example:

https://codepen.io/alyf-mendonca/pen/dyZZoeB

HTML:


    <div>
      <canvas id="myChart"></canvas>
    </div>
    
    
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

JS:


    const labels = [
            'January',
            'February',
            'March',
            'April',
            'May',
            'June',
        ];
    
        const data = {
      labels: [
        '20:00',
        '21:00',
        '22:00',
        '23:00',
        '00:00',
        '01:00',
        '02:00'
      ],
      datasets: [{
        type: 'line',
        label: 'Bar Dataset',
        data: [20, 21, 23, 22, 21, 20, 23],
        borderColor: 'rgb(255, 99, 132)',
        backgroundColor: 'rgba(255, 99, 132, 0.2)'
      }, {
        type: 'bar',
        label: 'Line Dataset',
        data: [0, 0, 0, 0, 50, 0, 0],
        fill: false,
        borderColor: 'rgb(54, 162, 235)'
      }]
    };
    
        const config = {
            type: 'bar',
            data: data,
            options: {
                scales: {
                    x: {
                        stacked: true
                    }
                }
            },
        };
      
    
    const myChart = new Chart(
          document.getElementById('myChart'),
          config
        );

Upvotes: 1

Related Questions