Unable to display dates and values on Chart.js - javascript

I have the following data stored in array:
var labelItems= ["3/27/20", "3/28/20", "3/29/20", "3/30/20", "3/31/20", "4/1/20", "4/2/20", "4/3/20", "4/4/20", "4/5/20", "4/6/20", "4/7/20", "4/8/20", "4/9/20", "4/10/20"]
var dataSets= [27198, 30652, 33925, 37582, 42107, 46809, 52983, 58787, 64606, 69374, 74565, 81865, 88338, 95455, 102525]
I have initialzed my line chart as follows:
var ctx = document.getElementById('lineChart').getContext('2d');
var chart = new Chart(ctx, {
// The type of chart we want to create
type: 'line',
// The data for our dataset
data: {
labels: labelItems,
datasets: [{
label: 'Deaths',
borderColor: 'rgb(255, 99, 132)',
data: dataSets
}]
},
// Configuration options go here
options: {}
});
My issue is that the dates, that is the labels are not displaying on the x-axis nor the datasets on the y-axis. Can someone please help with this?

As the documentation say, you have to add the parser and tooltipFormat properties to the axis (x or y) in order to display the value.
var ctx = document.getElementById('lineChart').getContext('2d');
var chart = new Chart(ctx, {
// The type of chart we want to create
type: 'line',
// The data for our dataset
data: {
labels: labels,
datasets: [{
label: 'Deaths',
borderColor: 'rgb(255, 99, 132)',
data: dataSets
}]
},
// Configuration options go here
options: {
scales: {
xAxis: [
display: true,
type: 'time'
time: {
parser: 'MM/DD/YYYY HH:mm',
tooltipFormat: 'll HH:mm',
unit: 'day',
unitStepSize: 1,
displayFormats: {
'day': 'MM/DD/YYYY'
}
}
]
}
}
});

Related

charts.js add data with date

So Im trying to find an smart way to pass data with dates to chart.js.
On the x-axis i would like to show a time line for example a week,
14/06 15/06 16/06 17/06 18/06 19/06 20/6
But the data will not inculde every day
for example
[{'date': 15/06, 'bought': 2}, {'date': 17/06, 'bought': 5}]
for what I read, I would need to create a new array (same index number as the time period), compare the dates and replace the value depending on the index value...
Is there a better process?
I would like to show a time period for like a year.
LeeLenalee's perfectly shows how Chart.js is instructed to correctly parse your data. In order to obtain a time line, you'll also need to define the x-axis as a time cartesian axis.
Please take a look at below runnable code and see how it works.
new Chart('myChart', {
type: 'line',
data: {
datasets: [{
label: 'Purchases per day',
data: [
{ 'date': '15/06', 'bought': 2 },
{ 'date': '17/06', 'bought': 5 },
{ 'date': '20/06', 'bought': 3 }
],
borderColor: 'rgb(0, 0, 255)',
backgroundColor: 'rgba(0, 0, 255, 0.5)'
}]
},
options: {
parsing: {
xAxisKey: 'date',
yAxisKey: 'bought'
},
scales: {
y: {
ticks: {
stepSize: 1
}
},
x: {
type: 'time',
time: {
parser: 'DD/MM',
unit: 'day',
tooltipFormat:'MMM DD'
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.3.2/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment#2.27.0"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment#0.1.1"></script>
<canvas id="myChart" height="90"></canvas>
You can just provide that array as is to chart.js, you only need to specify which field should be mapped to the x Axis and which field to the yAxis in the parsing block of the options object.
Live example:
var options = {
type: 'line',
data: {
datasets: [
{
label: '# of Votes',
data: [{'date': '15/06', 'bought': 2}, {'date': '17/06', 'bought': 5}, {'date': '20/06', 'bought': 3}],
borderWidth: 1
}
]
},
options: {
parsing: {
xAxisKey: 'date',
yAxisKey: 'bought'
}
}
}
var 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.3.2/chart.js"></script>
</body>

Relative bar chart overlay on line chart in chart.js

I'm trying to build a chart in chart.js, showing price data of a virtual item, with a line chart showing pricing, and a backlay bar chart, showing sales volume, like this:
My issue is, the y-axis is the same for both, meaning the price data is shown at the bottom with unnoticeable differences, since the volume is in the hundreds.
I want the price data to be on the y-axis, with the bars shown relatively, with the highest volume being shown as 100% height, not the values on the y-axis, something more like this:
Is this possible, and how would it be done? Thanks!
Code:
let marketData = [["Nov 28 2018 20: +0",30.332,"103"],["Nov 28 2018 21: +0",25.801,"188"],["Nov 28 2018 22: +0",25.451,"262"],["Nov 28 2018 23: +0",12.484,"693"]];
let lineData = [];
let barData = [];
let labels = [];
marketData.forEach(function(thing) {
labels.push(thing[0].replace(' +0', '00'));
lineData.push(thing[1]);
barData.push(thing[2]);
});
new Chart(document.getElementById("mixed-chart"), {
type: 'bar',
data: {
labels: labels,
datasets: [
{
label: "Price",
type: "line",
borderColor: "#3e95cd",
data: lineData,
fill: false
},
{
label: "Sold",
type: "bar",
backgroundColor: "rgba(0,0,0,0.2)",
data: barData
}
]
},
options: {
title: {
display: true,
text: 'Sale price vs sale volume'
},
legend: { display: false }
}
});
use a second y-axis to give the bar series a different scale
assign each data set to its own axis by using property --> yAxisID
then set the matching id of the y-axis in the scales.yAxes option
see following working snippet...
$(document).ready(function() {
let marketData = [["Nov 28 2018 20: +0",30.332,"103"],["Nov 28 2018 21: +0",25.801,"188"],["Nov 28 2018 22: +0",25.451,"262"],["Nov 28 2018 23: +0",12.484,"693"]];
let lineData = [];
let barData = [];
let labels = [];
marketData.forEach(function(thing) {
labels.push(thing[0].replace(' +0', '00'));
lineData.push(thing[1]);
barData.push(thing[2]);
});
new Chart(document.getElementById("mixed-chart"), {
type: 'bar',
data: {
labels: labels,
datasets: [
{
label: "Price",
type: "line",
borderColor: "#3e95cd",
data: lineData,
fill: false,
yAxisID: 'A' // <-- set y-axis id
},
{
label: "Sold",
type: "bar",
backgroundColor: "rgba(0,0,0,0.2)",
data: barData,
yAxisID: 'B' // <-- set y-axis id
}
]
},
options: {
title: {
display: true,
text: 'Sale price vs sale volume'
},
legend: {display: false},
scales: {
yAxes: [{
id: 'A', // <-- set y-axis id
position: 'left',
}, {
id: 'B', // <-- set y-axis id
position: 'right',
// hide grid lines and labels
gridLines: {
display: false
},
ticks: {
display: false
}
}]
}
}
});
});
<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.2/Chart.bundle.min.js"></script>
<canvas id="mixed-chart"></canvas>

Make Chart.js horizontal bar labels multi-line

Just wondering if there is any way to set the horizontal bar labels for y-axis using chart.js. Here is how I set up the chart:
<div class="box-body">
<canvas id="chart" style="position: relative; height: 300px;"></canvas>
</div>
Javascript:
var ctx = document.getElementById('chart').getContext("2d");
var options = {
layout: {
padding: {
top: 5,
}
},
responsive: true,
animation: {
animateScale: true,
animateRotate: true
},
};
var opt = {
type: "horizontalBar",
data: {
labels: label,
datasets: [{
data: price,
}]
},
options: options
};
if (chart) chart.destroy();
chart= new Chart(ctx, opt);
chart.update();
As you all can see, the first and third labels are too long and cut off. Is there a way to make the label multi-line?
If you want to have full control over how long labels are broken down across lines you can specify the breaking point by providing labels in a nested array. For example:
var chart = new Chart(ctx, {
...
data: {
labels: [["Label1 Line1:","Label1 Line2"],["Label2 Line1","Label2 Line2"]],
datasets: [{
...
});
You can use the following chart plugin :
plugins: [{
beforeInit: function(chart) {
chart.data.labels.forEach(function(e, i, a) {
if (/\n/.test(e)) {
a[i] = e.split(/\n/);
}
});
}
}]
add this followed by your chart options
ᴜꜱᴀɢᴇ :
add a new line character (\n) to your label, wherever you wish to add a line break.
ᴅᴇᴍᴏ
var chart = new Chart(ctx, {
type: 'horizontalBar',
data: {
labels: ['Jan\n2017', 'Feb', 'Mar', 'Apr'],
datasets: [{
label: 'BAR',
data: [1, 2, 3, 4],
backgroundColor: 'rgba(0, 119, 290, 0.7)'
}]
},
options: {
scales: {
xAxes: [{
ticks: {
beginAtZero: true
}
}]
}
},
plugins: [{
beforeInit: function(chart) {
chart.data.labels.forEach(function(e, i, a) {
if (/\n/.test(e)) {
a[i] = e.split(/\n/);
}
});
}
}]
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="ctx"></canvas>

Why does Chartjs line chart does not animate to new values?

I am using a chartjs line chart showing time data where I want to update with new values from an ajax call.
I have time on the X axis (1 days on 15 minutes intervals) , and just numbers for the Y axis.
So it looks like the following..
My setup is as follows.
this.chartSetup = {
type: 'line',
data: {
labels: this.times,
datasets: [{
fill: true,
lineTension: 0.1,
backgroundColor: "rgba(75,192,192,0.4)",
borderColor: "rgba(75,192,192,1)",
label: title,
data: this.vals,
pointRadius: 0,
}]
},
options: {
spanGaps: true,
legend: {
position: 'bottom',
labels: {
boxWidth: 10
}
},
tooltips: {
enabled: false
},
responsive: true,
maintainAspectRatio: false,
scales: {
xAxes: [{
ticks: {
stepSize: 6,
unitStepSize: 5
},
type: 'time',
time: {
displayFormats: {
hour: 'h:mm a',
minute: 'h:mm a',
}
}
}],
},
}
};
Chart.defaults.global.animation.easing = "easeOutBounce";
this.chart = new Chart(this.canvas.nativeElement, this.chartSetup);
When the chart first draws it animates the new values. However, if I then remove the data, and add a new set, it does not animate to the new values.
For example, to mimic new server data, using a timer, if I do the following,
where this.times holds the X data, this.vals holds the Y..
setTimeout(() => {
let temp = this.makeDummyData(20);
//let dataToUpdate = (<any>(this.chart.data)).datasets[0].data;
//let labels = (<any>(this.chart.data)).labels;
this.times.splice(0, this.times.length);
this.vals.splice(0, this.vals.length);
for (let item of temp) {
this.times.push(item.time);
this.vals.push(item.val);
}
this.chart.update();
}, 8000)
The chart does update, but it does not have any animation, it just jumps straight to the new display. If I just date the exiting data without removing it first, does does animate to the new display.
Is there any reason the animation does not work when I replace the data as in the above example?
Thanks in advance for any suggestions

Chartjs - Set start and end value into a Bar Chart

I am working on drowing a Gantt diagram like on Chartjs.
What am I trying to do is painting and HorizontalBarChart with time type, as a mixed type where I set a min value for each bar, however seems it does not work.
My code:
new Chart(document.getElementById("customChart"), {
type: 'horizontalBar',
data: {
labels: ['Item 1', 'Item 2'],
datasets: [
{
type: 'horizontalBar',
label: 'Bar Component1',
data: [new Date(2017,02,26) ],
options:{
scales:{
xAxes: [{
type: 'time',
unit: 'day',
unitStepSize: 1,
time: {
displayFormats: {
'day': 'YYYY-MM-DD'
},
min: new Date(2017,03,24)
}
}]
}
}
},
{
type: 'horizontalBar',
label: 'Bar Component2',
data: [new Date(2017,02,14)],
options:{
scales:{
xAxes: [{
type: 'time',
unit: 'day',
unitStepSize: 1,
time: {
displayFormats: {
'day': 'YYYY-MM-DD'
},
min: new Date(2017,02,10)
}
}]
}
}
}
]
}
});
Is there any workaround in order to implement this? Should I use another library?
Unfortunately, there is no way to configure chart.js to produce a gantt chart because each dataset that you plot on the graph either starts at the origin (the min value set on the scale) or is stacked right on top of each other. You cannot configure a chart to stack bars but show them in different "lanes" (which is what a gantt chart would require).
Even if you try to create multiple scales (which is looks like you are attempting), it will not work because the 2nd bar will still start at the origin (however the 2nd scale's origin would be the min value you specified). In other words, both bars will still touch the y axis.
You had several problems with you chart.js configuration. First, you cannot define scale config in a dataset. Second, you tried to use several time scale options, but they must be inside the time object.
I cleaned up everything just so you can see how to correctly define a chart. Here is a codepen demonstrating this.
Currently [November 2018] chart.js is not able todo so.
However if you are willing to apply a patch, there is a pull request pending, which would implement exactly this feature: https://github.com/chartjs/Chart.js/pull/5262
For my purposes I adapted the code of https://github.com/chartjs/Chart.js/blob/master/src/controllers/controller.bar.js
## -453,10 +453,12 ## module.exports = function(Chart) {
helpers.canvas.clipArea(chart.ctx, chart.chartArea);
- for (; i < ilen; ++i) {
- if (!isNaN(scale.getRightValue(dataset.data[i]))) {
- rects[i].draw();
- }
+ if (dataset.label != 'noshow') {
+ for (; i < ilen; ++i) {
+ if (!isNaN(scale.getRightValue(dataset.data[i]))) {
+ rects[i].draw();
+ }
+ }
}
helpers.canvas.unclipArea(chart.ctx);
Utilizing bar chart like this:
var gapdemo= new Chart(ctx, {
type: 'horizontalBar',
data: {
labels: ["todo1", "todo2", "todo3", "todo4"],
datasets: [{
type: 'horizontalBar',
label: 'noshow',
data: [1,2,4,3],
},{
type: 'horizontalBar',
label: 'showme',
data: [3,2,2,1],
},{
type: 'horizontalBar',
label: 'noshow',
data: [1,5,3,4],
},{
type: 'horizontalBar',
label: 'showme',
data: [2,2,1,4],
}]
},
options: {
scales: {
xAxes: [{
id: 'x-axis-1',
stacked: true
}],
yAxes: [{
id: 'y-axis-1',
stacked: true,
ticks: {beginAtZero: true}
}]
}
}
});
This results in a chart like that:
barchart with gaps
Since version 2.9.0, Chart.js supports floating bars. Individual bars can now be specified with the syntax [min, max].
This makes it possible to draw a Gantt chart.
var dates = [new Date("2019-12-24"), new Date("2019-12-26"), new Date("2019-12-30"), new Date("2020-1-2"), new Date("2020-1-4"), new Date("2020-1-9"), new Date("2020-1-10") ];
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'horizontalBar',
data: {
labels: dates.map((d, i) => "Task " + i).splice(1),
datasets: [
{
label: 'Tasks',
data: dates.map((d, i) => i == 0 ? null : [dates[i - 1], d]).slice(1),
backgroundColor: 'lightblue',
borderWidth: 1
}
]
},
options: {
responsive: true,
scales: {
xAxes: [{
type: 'time',
time: {
displayFormats: {
day: 'YYYY-MM-DD'
}
},
ticks: {
min: dates[0].getTime(),
max: dates[dates.length - 1].getTime()
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.1.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="myChart"></canvas>

Categories