Chartjs-Plot time on Y axis

0👍

Based on the example specified in the comments, here is the StackBlitz with the chart.

A couple of remakrs:

  • I found it more convenient to convert hh:mm data to minutes
var sunsetHours = ['20:18', '20:18', '20:15'].map(hour => {
  var hourMinutes = hour.split(':');
  var minutes = parseInt(hourMinutes[0]) * 60 + parseInt(hourMinutes[1]);
  return minutes;
});
  • to achieve something similar to the example from the comments, the code below creates 1440 1441 possible labels for the yAxis (for each possible minute). The getHourString() function converts minutes to labels (e.g. 121 becomes 02:01)
var yLabels = [];
var stepMinutes = 60;
for (var minute = 0; minute <= 1440; minute += 1) {
  yLabels.push(getHourString(minute));
}

/* removed fragment */

function getHourString(minute) {
  var hours = Math.floor(minute / 60);
  var minutes = minute % 60;
  return `${Math.floor(hours / 10) > 0 ? hours : "0" + hours}:${Math.floor(minutes / 10) > 0 ? minutes : "0" + minutes}`;
}
  • as a bonus I’ve added also custom tooltip so that when you hover on the point it will get 20:18 instead of the 1218
tooltips: {
  callbacks: {
    label: (tooltipItem, data) => {
      // console.log(tooltipItem);
      return yLabels[tooltipItem.yLabel];
    }
  }
}
  • I’ve noticed also that only the first point is red, so I’ve changed this
backgroundColor: ['rgba(255, 99, 132, 0.2)'],
borderColor: ['rgba(255, 99, 132, 1)'],

to this

backgroundColor: 'rgba(255, 99, 132, 0.2)',
borderColor: 'rgba(255, 99, 132, 1)',

0👍

The trickiest part is the date parsing and formatting. But if you do it right, it is very powerful.

You find the full example in my JSBin.

let sData = {}
sData.label = ['19.09.19', '21.09.19', '22.09.19']
sData.time = ['20:18', '20:18', '20:15']

let chartData = {}
chartData.label = parseDate(sData.label)
chartData.time = parseTime(sData.time)

function parseDate(dates){
  let parsedDates = []
  for (let x = 0; x < dates.length; x++) {
    parsedDates.push(moment(dates[x], "DD.MM.YYYY").format('YYYY-MM-DD'))
  }
  return parsedDates
}

function parseTime(times){
  let parsedTime = []
  for (let x = 0; x < times.length; x++) {
    let words = times[x].split(':')
    parsedTime.push(parseInt(words[0])*60 + parseInt(words[1]))   
  }
  return parsedTime
}

let ctx = document.getElementById('chart');

let time_data = {
  labels: chartData.label,
  datasets: [{
    label: 'Sunset',
    data: chartData.time,
    backgroundColor: 'rgba(255, 99, 132, 0.2)',
    borderColor: 'rgba(255, 99, 132, 1)',
    borderWidth: 1
  }]
};

let time_options = {
  responsive: true,
  title: {
    display: true,
    text: 'Sunset'
  },
  legend: {
    display: false
  },
  tooltips: {
    callbacks: {
      label: function(tooltipItem, data){
        let value = parseInt(tooltipItem.value)
        if (value%60 < 10)
          return Math.floor(value/60) + ":" + 0 + value%60
        else
          return Math.floor(value/60) + ":" + value%60
      },
      title: function(tooltipItem, data){
        let label = tooltipItem[0].label
        console.log(label)
        console.log(moment(label).format('DD.MM.YYYY'))
        return moment(label).format('DD.MM.YYYY')
      }
    },
    displayColors: false
  },
  scales: {
    xAxes: [{
      type: 'time',
      time: {
        minUnit: 'day',
        unitStepSize: 1,
        displayFormats: {
          day: 'DD.MM.' 
        }
      }
    }],
    yAxes: [{
      ticks: {
        //min: 0,
        //max: 1440,
        precision: 0,
        callback: function(value, index, values) {
          if (value%60 < 10)
            return Math.floor(value/60) + ":" + 0 + value%60
          else 
            return Math.floor(value/60) + ":" + value%60
        }
      }      
    }]
  }
};

let chart = new Chart(ctx, {
  type: "line",
  data: time_data,
  options: time_options
});

Leave a comment