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>
Related
I am using chart.js for my project. As you can see in the following code, chart.js uses different minimum and maximum values for y-axis for line and bar graphs for same data. In the given code, 1100-1700 is the value range for line graph whereas 0-2000 is the value range used for bar graph.
I like to make same minimum and maximum values for both line and bar graphs. One option is to find minimum, maximum and step-size values my own and use the properties min, max and ticks.stepSize under scales. But finding minimum, maximum and step-size for a given data data is a serious task.
For my requirement, default minimum ,maximum and stepSize used by chart.js for line graph is fine and I would like to use the same values for bar graph also.
I could first render line graph, get these values from this graph (like scales.y.min) and then use it for bar graph, which is perfectly working
Is there a way I could get the default min, max, stepSize values used by chart.js for line graph before actually drawing the graph? Any answers or pointers are really appreciated. Thanks
var chart1 = new Chart(document.getElementById('chart1'),
{
type: 'line',
data:
{
labels: ['a','b','c'],
datasets:
[
{
label: 'A',
data: [1212,1122, 1188, 1617, 1116],
borderColor: 'green',
}
]
}
});
var chart2 = new Chart(document.getElementById('chart2'),
{
type: 'bar',
data:
{
labels: ['a','b','c'],
datasets:
[
{
label: 'A',
data: [1212,1122, 1188, 1617, 1116],
backgroundColor: 'green',
}
]
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
<div style="width:300px;height:200px"><canvas id="chart1"></canvas></div>
<div style="width:300px;height:200px"><canvas id="chart2"></canvas></div>
The first thing you could do is to set beginAtZero to false to Y axis of bar chart because is set to true by default:
https://github.com/chartjs/Chart.js/blob/v3.9.1/src/controllers/controller.bar.js#L636-L650
Then you can set the same scale config to both charts.
options: { // options of charts
scales: {
y: {
beginAtZero: false,
}
}
}
var chart1 = new Chart(document.getElementById('myChart1'),
{
type: 'line',
data:
{
labels: ['a','b','c'],
datasets:
[
{
label: 'A',
data: [1212,1122, 1188, 1617, 1116],
borderColor: 'green',
}
]
},
options: {
scales: {
y: {
beginAtZero: false,
}
}
}
});
var chart2 = new Chart(document.getElementById('myChart2'),
{
type: 'bar',
data:
{
labels: ['a','b','c'],
datasets:
[
{
label: 'A',
data: [1212,1122, 1188, 1617, 1116],
backgroundColor: 'green',
}
]
},
options: {
scales: {
y: {
beginAtZero: false,
}
}
}
});
.myChartDiv {
max-width: 300px;
max-height: 200px;
}
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.9.1/dist/chart.min.js"></script>
<html>
<body>
<div class="myChartDiv">
<canvas id="myChart1" width="300" height="200"/>
</div>
<div class="myChartDiv">
<canvas id="myChart2" width="300" height="200"/>
</div>
</body>
</html>
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'
}
}
]
}
}
});
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>
I have the following array:
Where the arrays keys are the dates and the only element I want to plot, of each set, is the weight. Look:
I am putting the code as follows. Notice that I am already grouping in the date attribute the whole set belonging to each that key.
var ctx = document.getElementById("barChart").getContext("2d");
var data = {
labels: ['21/03/2018','01/04/2018','02/04/2018','04/04/2018','05/04/2018','06/04/2018'],
datasets: [
{
label: '21/03/2018',
data: [12, 0, 0]
},
{
label: '01/04/2018',
data: [15.00, 15.00,15.00]
},
{
label: '02/04/2018',
data: [25.00, 25.00, 25.00]
},
{
label: '04/04/2018',
data: [25.00, 25.00, 25.00]
},
{
label: '05/04/2018',
data: [-8.14,-7.93, -7.84]
},
{
label: '06/04/2018',
data: [-35.9 ,-38.1, -37.5]
},
]
};
var myBarChart = new Chart(ctx, {
type: 'bar',
data: data,
});
But in this way ChartJs does not understand that it only needs to plot the data set present in the "data" attribute and grouping them by the key. Plotting the graph in the wrong way.
How could I plot the data correctly knowing that they are already grouped?
You need to organize your data as such:
var ctx = document.getElementById("canvas").getContext("2d");
var data = {
labels: ['21/03/2018','01/04/2018','02/04/2018','04/04/2018','05/04/2018','06/04/2018'],
datasets: [
{
data: [12, 15.00, 25.00, 25.00, -8.14, -35.9]
},{
data: [0, 15.00, 25.00, 25.00, -7.93, -38.1]
},{
data: [0, 15.00, 25.00, 25.00, -7.84, -37.5]
}
]
};
var myBarChart = new Chart(ctx, {
type: 'bar',
data: data,
options:{
legend: 'none'
}
});
I took your legend out as it's useless in this case. To look at it in the coding persepective, whatever index the date in labels is at needs to correlate with the index of the information you want to display in that grouping. data[0] refers to labels[0] and so on.
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>