How to feed hour and minute data into chartJS - javascript

I'm trying to make a line chart using Chart.js. My data is of the form:
var result = [{x:"18:00",y:"230"},{x:"19:00",y:"232"},{x:"20:00",y:"236"},{x:"22:00",y:"228"}];
Where x represents the time with hours and minutes. I fed the data like this
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["00:00","01:00","02:00","03:00","04:00","05:00","06:00","07:00","08:00","09:00","10:00","11:00","12:00","13:00","14:00","15:00","16:00","17:00","18:00","19:00","20:00","21:00","22:00","23:00","24:00"],
datasets: [{
label: 'Voltage Fluctuation',
data: result,
borderWidth: 1
}]
},
options: {
scales: {
xAxes: [{
type: 'time',
position: 'bottom',
unit: 'minute',
time: {
displayFormats: {
hour: 'HH:mm'
}
}
}],
},
}
});
And I'm getting an empty chart. Where am I going wrong? I feel I'm doing something wrong with my labels since they don't show up on the chart but I don't understand how. Is there any way I can feed datalabels with momentjs?

You cannot just pass the result array to data, as it isn't in correct format. data property expects an array of numbers. So, you need to parse the labels (using moment.js) and data from result array before using them for the chart.
Here is how labels and data should be parsed from the result array and fed to the chart :
var result = [{ x: "18:00", y: "230" }, { x: "19:00", y: "232" }, { x: "20:00", y: "236" }, { x: "22:00", y: "228" }];
// parse labels and data
var labels = result.map(e => moment(e.x, 'HH:mm'));
var data = result.map(e => +e.y);
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'Voltage Fluctuation',
data: data,
borderWidth: 1
}]
},
options: {
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'hour',
displayFormats: {
hour: 'HH:mm'
}
}
}]
},
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="myChart"></canvas>

Related

Handle Date Gaps in Chart JS

I am plotting a graph using chart js. I have a couple of inconsistent data. For instance, the example data I have shared starts with 1909 and the next is 1960. In other cases, they are properly displayed: 1980, 1981, 1982...
Is there a way for me to handle specific data with gaps? For instance, have the year displayed sequentially.
const ctx = canvas.getContext("2d");
const myChart = new Chart(ctx, {
type: "line",
data: {
labels: labels,
datasets: [{
label: "Country Population",
data: data,
}, ],
},
options: {
scales: {
x: {
title: {
display: true,
text: "Year",
},
xAxes: [{
type: 'time',
time: {
unit: 'year'
}
}]
},
y: {
title: {
display: true,
text: "Population",
},
},
},
},
});
How library you are using time and chart? I use chart(v3.8) and luxon(time) seems to work
const exampleData = [{
"x": +new Date('1909'),
"y": 48900202
},
{
"x": +new Date('1960'),
"y": 889030
},
{
"x": +new Date('1961'),
"y": 890203
},
{
"x": +new Date('1983'),
"y": 8904
},
]
const chartCfg = {
type: 'line',
data: {
datasets: [{
borderColor: 'green',
backgroundColor: 'green',
borderWidth: 1,
pointStyle: 'cross',
data: exampleData,
label: 'example',
}, ],
},
options: {
maintainAspectRatio: false,
animation: false,
parsing: false,
interaction: {
mode: 'index',
},
scales: {
x: {
type: 'time',
time: {
displayFormats: {
year: 'yyyy',
},
},
},
},
},
};
const chartCtx = document.getElementById('chart').getContext('2d');
const chart = new Chart(chartCtx, chartCfg);
chart.canvas.parentNode.style.height = '300px';
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/luxon/2.4.0/luxon.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-adapter-luxon/1.1.0/chartjs-adapter-luxon.min.js"></script>
<canvas id="chart""></canvas>

label on the x-axis does not show completely in Chart.js

I have a data from the backend(flask-sqlalchemy with mysql) in which data contains date in integer for week, month and year that looks like this:
in this case the x represents the week of the year:
let month_true = [
{
bob: {
"base-certificate": 60,
"case-certificate": 1,
"standard-certificate": 7,
},
x: 9,
},
{
bob: {
"base-certificate": 30,
"case-certificate": 4,
"standard-certificate": 5,
},
x: 11,
},
];
The first thing I did was to map the data and change the x into a readable format for Javascript and chart.js, using a function that converts week of the year number to actual date:
the function:
function getDateOfWeek(w, y) {
var d = 1 + (w - 1) * 7; // 1st of January + 7 days for each week
return new Date(y, 0, d);
}
Mapping through the data:
let newData = month_true.map(function (m) {
let dateObject = new Date();
let year = dateObject.getFullYear();
const weekDate = getDateOfWeek(m.x, year);
let r = new Date(Date.parse(weekDate));
const newd = {
x: r.setHours(0, 0, 0, 0),
base: m.bob["base-certificate"],
case: m.bob["case-certificate"],
standard: m.bob["standard-certificate"],
};
return newd;
});
let newdate = newData.map(function (d) {
return d.x;
});
now construct the chart:
let ctx = document.getElementById("chart").getContext("2d");
let config = {
//labels: newdate,
type: "bar",
data: {
datasets: [
{
label: "base",
data: newData,
parsing: {
xAxisKey: "x",
yAxisKey: "base",
},
},
{
label: "Case",
data: newData,
parsing: {
xAxisKey: "x",
yAxisKey: "case",
},
},
{
label: "Standard",
data: newData,
parsing: {
xAxisKey: "x",
yAxisKey: "standard",
},
},
],
},
options: {
scales: {
x: {
ticks: {
beginAtZero: true,
},
offset: true,
type: "time",
time: {
//isoWeekday: true,
unit: "week",
},
},
},
},
};
let myChart = new Chart(ctx, config);
It got plotted but the x-axis is not showing the second label:
enter image description here
what can I can do tomake the labels appear completely?
This is because by default the time scale auto generates ticks, if you dont want to include the labels from your data you need to set ticks.source to data:
options: {
scales: {
x: {
type: 'time',
ticks: {
source: 'data'
}
}
}
}

ChartJs: HorizontalBar Missing Background Colours

I have the following chart using ChartJs 2.7.3 that is supposed to show a 10yr span in a red bar. For some reason, the background is not applying correctly for that bar (if you hover the chart you still get the correct hover tooltip)
$(() => {
var ctx = $("#Chart")[0];
var chart = new Chart(ctx, {
type: 'horizontalBar',
data: {
labels: ['ABC'],
datasets: [{
label: 'ABC',
data: [{
t: '2015-3-15',
y: 10
}],
backgroundColor: 'rgba(255,0,0,1)'
}]
},
options: {
scales: {
xAxes: [{
type: 'time',
time: {
min: '2010-1-01',
max: '2030-1-01'
}
}]
}
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"></script>
<canvas id="Chart" height="50"></canvas>
If I switch the chart type from a horizontalBar to a normal bar, then it works as expected:
$(() => {
var ctx = $("#Chart")[0];
var chart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['ABC'],
datasets: [{
label: 'ABC',
data: [{
t: '2015-3-15',
y: 10
}],
backgroundColor: 'rgba(255,0,0,1)'
}]
},
options: {
scales: {
xAxes: [{
type: 'time',
time: {
min: '2010-1-01',
max: '2030-1-01'
}
}]
}
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"></script>
<canvas id="Chart" height="50"></canvas>
What am I missing for the horizontalBar chart?
I cannot tell why your code is not working but can propose a different approach to solve the problem.
Please have a look at your amended code below. In order to get rid of annoying JavaScript warnings, I use the latest stable versio nof Chart.js (2.3.0).
I included two bars since I expect that the data can be of dynamic size. It should however also work for a single bar. I didn't know however what to do with the y value, this depends on your use case.
$(() => {
var data = [{
l: 'ABC',
t: '2015-3-15',
y: 10
}, {
l: 'XYZ',
t: '2020-11-05',
y: 20
}];
var ctx = $("#Chart")[0];
var chart = new Chart(ctx, {
type: 'horizontalBar',
data: {
yLabels: data.map(o => o.l),
datasets: [{
label: 'ABC',
data: data.map(o => moment(o.t, 'YYYY-M-DD')),
backgroundColor: ['rgba(255,0,0, 0.5)', 'rgba(0,255,0,0.5)']
}]
},
options: {
legend: {
display: false
},
scales: {
xAxes: [{
type: 'time',
time: {
parser: 'YYYY-M-DD',
unit: 'year',
tooltipFormat: 'YYYY/M/D'
},
ticks: {
min: '2010-1-01',
max: '2030-1-01'
}
}]
}
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="Chart" height="80"></canvas>

Chartjs not displaying timed data

I'm new to chartjs, but after googling around, i still cannot figure out, why would I not get data charted out. I'm using "parser" attribute to parse string and providing expected display format with min/max values, but no data is shown
var ctx = document.getElementById("canvas");
var chart = new Chart(ctx, {
type: 'horizontalBar',
data: {
labels: ["labelA", "labelB"],
datasets: [{
data: ["10:32", "00:12"],
borderWidth: 1
}]
},
options: {
responsive: 'true',
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}],
xAxes: [{
type: 'time',
time: {
parser: 'm:s',
unit: 'minute',
unitStepSize: 1,
min: '00:00',
max: '20:00',
displayFormats: {
'minute': 'mm:ss'
}
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
<canvas id="canvas" height="100"></canvas>
In my opinion your code looks good and should work. Semantically, however, the use of the timeline is not quite correct. Your bars actually represent durations.
Please have a look at your amended code that works now with durations instead of times:
function asSeconds(value) {
const tokens = value.split(':');
return Number(tokens[0]) * 60 + Number(tokens[1]);
}
function format(seconds) {
return moment.utc(seconds * 1000).format("mm:ss");
}
new Chart('canvas', {
type: 'horizontalBar',
data: {
labels: ['labelA', 'labelB'],
datasets: [{
label: 'My Dataset',
data: ['10:32', '00:12'].map(v => asSeconds(v)),
backgroundColor: ['red', 'blue'],
borderWidth: 1
}]
},
options: {
responsive: 'true',
scales: {
xAxes: [{
ticks: {
min: 0,
stepSize: 60,
max: asSeconds('20:00'),
callback: s => format(s)
}
}]
},
tooltips: {
callbacks: {
label: (tooltipItem, data) => format(data.datasets[0].data[tooltipItem.index])
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="canvas" height="80"></canvas>

Custom alphanumerical values in chart.js?

I am trying to make a simple horizontal bar chart with Chart.js with some languages ('Spanish', 'English', ...) in the y-axis and its CEFR Level (from A1 to C2) in the x-axis instead of some numerical level (1-10 for example).
Is there a way to have a bar chart without pure numerical values in the x-axis?
That is what I'm getting right now with this code:
var spokenLangChart = new Chart(ctx, {
type: 'horizontalBar',
data: {
labels: ['Spanish', 'English', 'German'],
datasets: [{
label: 'CEF Level',
labels: ['A1', 'A2', 'B1', 'B2', 'C1', 'C2'],
data: ['C2', 'C1', 'B1'],
backgroundColor: "rgba(255,153,0,0.4)"
}]
},
options: {
scales: {
xAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
Currently, ChartJS does not support directly two axis without numerical values. But you can accomplish this with callbacks as you can see on my example:
var ctx = document.getElementById('chart');
var xLabels = ["A","B","C","D","E","F","G","H","I","J","K"]; //Put here your x labels
var spokenLangChart = new Chart(ctx, {
type: 'horizontalBar',
data: {
labels: ['Spanish', 'English', 'German'], //Put here your x labels
datasets: [{
label: 'CEF Level',
labels: ['A1', 'A2', 'B1', 'B2', 'C1', 'C2'],
data: ['C2', 'C1', 'B1'],
backgroundColor: "rgba(255,153,0,0.4)"
}]
},
options: {
scales: {
xAxes: [{
ticks: {
//Returns the x labels
callback: function(value, index, values) {
return xLabels[index];
}
},
}]
},
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<canvas id="chart" width="200" height="100"></canvas>
Or look at JSFiddle.
I hope it helps you.
So thanks to Julian Schmuckli I was able to fix this. Since it wasn't entirely solved I'm going to post my own answer so I can share the result.
var ctx = document.getElementById('spokenLangChart').getContext('2d');
var xLabels = ['A1', 'A2', 'B1', 'B2', 'C1', 'C2'];
var spokenLangChart = new Chart(ctx, {
type: 'horizontalBar',
data: {
labels: ['Spanish', 'English', 'German'], //Put here your x labels
datasets: [{
label: 'CEF Level',
data: [5, 4, 3],
backgroundColor: "rgba(255,153,0,0.4)"
}]
},
options: {
legend: {
position: 'bottom'
},
title: {
display: true,
text: 'Spoken Languages'
},
scales: {
xAxes: [{
ticks: {
beginAtZero: true,
//Returns the x labels
callback: function (value, index, values) {
return xLabels[index];
}
}
}]
}
}
});
It's very important that you put beginAtZero: true, otherwise it will put your lowest value as zero and as I hadn't numerical values it was a bit difficult to spot the error.
Here's the final result:

Categories