B. Smit
B. Smit

Reputation: 63

Chart.js v3.x time series on x axis

so I'm basically pulling my hair as I can't get this to work for hours straight.

I'm trying to do a (I assumed simple) line-graph with on the x-axis time of day in hours and on the y-axis number of views. I'm trying to set the x-axis range as -24 hours until now.

My code is as follows. What am I doing wrong?

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.bundle.min.js"></script>
<div style="width: 500px; height: 500px;"><canvas id="myChart" width="400" height="400"></canvas></div>
    
<script>
    var ctx = document.getElementById('myChart');
    var myChart = new Chart(ctx, {
        type: 'line',
        data: {
            labels: [],
            datasets: [{
                label: '# of Votes',
                data: [{x:'1619701200',y:41},{x:'1619704800',y:9},{x:'1619708400',y:21}]
            }]
        },
        options: {
        scales: {
            x: {
                type: 'time',
                min: Date.now() - (24 * 60 * 60 * 1000),
                max: Date.now()
            }
        }
    }
    });

    </script>

EDIT: the problem is that the x-axis doesn't extend to 24 hours prior to now(). Also, there are 3 values in the dataset, but only two are shown. You can even edit the x-values to whatever you want and the entire graph stays the same.

EDIT2:

Could someone help me get this right? I've pasted my data below: What I am trying to achieve:

  1. X-axis going from now until 24 hours prior with an interval of 1 hour between ticks, formatted as 'd-m-Y H:00:00'. The data now is in seconds since epoch, if I need to change that please let me know!
  2. Y-axis going from 0 to whatever the max is in the dataset
  3. What CDNs do I have to include? I find the documentation on chart.js, moments, adapters etc quite unclear and everything I find on the internet is for prior versions.

Thank you!!

<div style="width: 500px; height: 500px;"><canvas id="myChart" width="400" height="400"></canvas></div>
    <script>
        new Chart(document.getElementById("myChart"), {
        type: 'line',
        data: {
            labels: ['1619701200','1619704800','1619708400','1619715600','1619719200','1619722800','1619726400','1619730000','1619733600','1619737200','1619744400','1619773200','1619780400','1619784000','1619787600','1619791200','1619794800','1619798400','1619802000','1619809200','1619812800','1619816400','1619820000','1619823600','1619856000'],
            datasets: [{ 
                data: [41,9,21,80,277,151,68,88,82,48,12,1,97,36,81,21,63,49,44,15,10,44,81,4,9],
                label: "Views",
                borderColor: "#3e95cd",
                fill: false
            },
            { 
                data: [1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,4,1,1],
                label: "Visitors",
                borderColor: "#3e95cd",
                fill: false
            }
            ]
        }
  </script>

Upvotes: 6

Views: 4266

Answers (2)

J&#252;rgen Fink
J&#252;rgen Fink

Reputation: 3535

We want you to keep your hair :-)

Try the following 2 Options for latest version of Chart.js

Chart.js v3.2.1 (not backwards compatible with v2.xx)

Option 1:

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
   // gets you the latest version of Chart.js, now at v3.2.1

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment"></script>
   // You need moment.js and adapter for time or timeseries to work at x-Axis


<div style="width: 500px; height: 500px">
  <canvas id="myChart" width="400" height="400"></canvas>
</div>


<script>
const startDate = new Date(1619701200*1000);
    // first label from your data, times 1000 to get milliseconds,
    // for last 24 hours from now, see further down below

const myLabels = [];
let nextHour = startDate;

let i = 0; // tip: declare i outside for-loop for better performance

for (i; i < 24; i++) {
  nextHour = new Date((1619701200 + (i*3600)) *1000);
  myLabels.push(nextHour);
};

const ctx = document.querySelector('canvas').getContext('2d');

const myChart3x = new Chart(ctx, {
    type: 'line',
    data: {
        labels: myLabels,
        datasets: [{
          data: [41,9,21,80,277,151,68,88,82,48,12,1,97,36,81,21,63,49,44,15,10,44,81,4,9],
          label: "Views",
          borderColor: "#3e95cd",
          fill: false
        },
        {
          data: [1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,4,1,1],
          label: "Visitors",
          borderColor: "#3e95cd",
          fill: false
        }
        ]
    },
    options: {
      scales: {
        x: {
          type: 'timeseries',
          time: {
            unit: 'hour',  // <-- that does the trick here
            displayFormats: {
              hour: 'D-M-Y H:00:00'
            },
            tooltipFormat: 'D-M-Y H:00:00'  // <-- same format for tooltip
          }
        },
        y: {
          min: 0
        }
      }
    }
  });

</script>

And this is what your chart would look like: enter image description here

If you want to calculate dynamically the last 24 hours from now for your x-Axis, I would suggest to use moment.js instead:

<script>
   // ...

const startDate = moment().subtract(1, 'd');

const myLabels = [];
let nextHour = startDate;
let i = 0;

for (i; i < 24; i++) {
  nextHour = moment().add(i, 'h');
  myLabels.push(nextHour);
}; 

   // ....
</script>

Also, be aware that moment.js uses slightly different formatting string:

'D-M-Y H:00:00' instead of 'd-m-Y H:00:00'

Option 2:

If you have your data in json-format

data: [{x:1620237600000,y:41},{x:1620241200000,y:9},{x:1620244800000,y:21}]

like your first code snippet on top, using min and max at x-Axis: (Advantage: you don't have to define labels-array for x-Axis)

<script>

const ctx = document.querySelector("canvas").getContext("2d");

var myChart = new Chart(ctx, {
  type: "line",
  data: {
    datasets: [{
      label: "Views",
      data: [{x:1620237600000,y:41},{x:1620241200000,y:9},{x:1620244800000,y:21}]
      // x-value without quotes (has to be a number) 
      // and multiply by 1000 to get milliseconds
    },
    {
      label: "Visitors",
      data: [{x:1620237600000,y:1},{x:1620241200000,y:1},{x:1620244800000,y:2}]
    }]
  },
  options: {
    scales: {
      x: {
        type: "time",  // <-- "time" instead of "timeseries"
        min: Date.now() - (24 * 60 * 60 * 1000),
        max: Date.now(),
        time: {
          unit: "hour",  // <-- that does the trick here
          displayFormats: {
            hour: "D-M-Y H:00:00"
          },
          tooltipFormat: "D-M-Y H:00:00"// <-- same format for tooltip
        }
      },
      y: {
        min: 0,
        max: 100
      }
    }
  }
});
</script>

You should get the following:

enter image description here

I hope I understood correctly your need and hope this helps.

Upvotes: 6

It needs more settings, I've searched and by trial/error - credit to this jsfiddle - , these are the results.

See updated working jsfiddle:

/*
        Source: https://jsfiddle.net/microMerlin/3wfoL7jc/
*/

var ctx = document.getElementById('myChart');
var myChart = new Chart(ctx, {
  type: 'line',
  data: {
    datasets: [{
      label: '# of Votes',
      data: [{
        x: '1619701200',
        y: 41
      }, {
        x: '1619704800',
        y: 9
      }, {
        x: '1619708400',
        y: 21
      }]
    }]
  },
  options: {
    responsive: true,
    scales: {
      xAxes: [{
        min: Date.now() - (24 * 60 * 60 * 1000),
        max: Date.now(),
        type: "linear",
        position: "bottom",
        //stacked: true,
        ticks: {
          //beginAtZero: true,
          userCallback: function(t, i) {
            /*console.log("t: " + t.toString());
            console.log("i: " + i.toString());*/
            return i;
          }
        }
      }]
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="width: 500px; height: 500px;"><canvas id="myChart" width="400" height="400"></canvas></div>

Upvotes: 1

Related Questions