Chartjs - Set start and end value into a Bar Chart - javascript

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>

Related

Unable to display dates and values on Chart.js

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'
}
}
]
}
}
});

Chart.js - How to push a collection of array into dataset

I have been trying many ways to push the collection of array into the dataset.
Anyone can help me to push an array into stacked chart based on the codepen below?
Here's the example
Codepen stacked bar
Javascript
const getData = ()=>new Array(7).fill('').map(v=>randomScalingFactor());
var barChartData = {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'Dataset 1',
backgroundColor: window.chartColors.red,
data: getData()
}, {
label: 'Dataset 2',
backgroundColor: window.chartColors.blue,
data: getData()
}, {
label: 'Dataset 3',
backgroundColor: window.chartColors.green,
data: getData()
}]
};
var ctx = document.getElementById('canvas').getContext('2d');
window.myBar = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
title: {
display: true,
text: 'Chart.js Bar Chart - Stacked'
},
tooltips: {
mode: 'index',
intersect: false
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
}
}
});
document.getElementById('randomizeData').addEventListener('click', function() {
barChartData.datasets.forEach(dataset=>{
dataset.data = getData();
});
window.myBar.update();
});
Here's the data for arrays
The issues should be the dataset with different colors and total should be the value for Y axis and there should be another collection of array date for X axis and the colors for the dataset should be different. The data for issues and total will be retrieved from Mysql database.
I am using laravel and the table above was achieved using foreach loop.
You really should provide more information. What have you tried, what failed...
Don't expect people do your job, wasting their time so you can nap for an hour. StackOverflow is for specific questions and not for letting others do somebody else's work. And getting data for chart.js is something trivial you can find in any other post about chart.js.
Enough ranting, just letting you know you shouldn't expect answers in the future for questions like that.
The code you posted in your question is quite different to the one from the codepen link, but this can be due to Narendra Jadhav's 'update'. But if confused me enough so I don't know what you want.
You didn't stated if you want to update our data so I didn't implemented updating.
Don't know the use case of this random randomizeData() does, especially with the fixed length of 7. I changed it but as I don't know the reason it may be different to your use case.
I don't know the data format you get from MySQL so I used a possible format. Same as above, could be different to what you want.
Please use an newer version of chart.js and not a year old version. There are no breaking changes, only improvements. Just updating the version eliminated a few bugs, e.g. the strange space between the yAxis and the chart.
Complete code (same as JSBin):
var initialData = [
{
'Barcode Sticker Problem':1,
'Extra':1,
'Labelling Problem':2,
'Stock Accuracy':1,
'Wrong Quality':1
},{
'Barcode Sticker Problem':1,
'Extra':1,
'Labelling Problem':2,
'Stock Accuracy':1,
'Wrong Quality':3
},
{
'Barcode Sticker Problem':2,
'Extra':2,
'Labelling Problem':1,
'Stock Accuracy':2,
'Wrong Quality':3
}
]
const colors = [
'red',
'blue',
'green'
]
var barChartData = {
labels: Object.keys(initialData[0]),
datasets: []
};
for (var i = 0; i < initialData.length; i++) {
barChartData.datasets.push(
{
label: 'Dataset ' + (i+1),
backgroundColor: colors[i % colors.length],
data: Object.values(initialData[i])
}
)
}
var barChartOptions = {
title: {
display: false,
text: 'Chart.js Stacked Bar Chart'
},
tooltips: {
mode: 'index',
intersect: false
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true,
ticks: {
precision: 0
}
}]
}
}
var ctx = document.getElementById('canvas').getContext('2d');
window.myBar = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: barChartOptions
});
document.getElementById('randomizeData').addEventListener('click', function() {
barChartData.datasets.forEach(dataset=>{
var newData = []
for (var i = 0; i < dataset.data.length; i++) {
newData.push(Math.floor(Math.random()*3)+1)
}
dataset.data = newData
});
window.myBar.update();
});

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

Chart.js how define max tick of polarArea?

I look for way to use polarArea but with limit scale (line of tick) defined at 100. Actualy the scale display scale based in max value, but I want max fixed.
var data = {
datasets: [{
data: [10,20,30,40],
}],
labels: ["Red","Green","Yellow","Grey","Blue"]
};
var polarArea = new Chart(ctx, {
data: data,
type: 'polarArea',
options: {
scale: {
ticks: {
beginAtZero: true
}
}
}
});
This marked with arrow green as I want the graph.
Can you help me?
var data = {
datasets: [{
data: [10,20,30,40],
}],
labels: ["Red","Green","Yellow","Grey"]
};
var polarArea = new Chart(ctx, {
data: data,
type: 'polarArea',
options: {
scale: {
ticks: {
min: 0,
max: 100
}
}
}
});
A JSFiddle would be super helpful for your exact situation, but based on the information provided, this should do it for you. http://jsfiddle.net/andrewborem/vup9o5fx/

Categories