Stacked bar charts in chart.js with different values in stacks - javascript

I want to create a stack graph something like this:
Note: Each stack has different value
Is it possible with chart js ? If yes what my data should look like ?
I have tried this:
var data = {
labels: ["2018", "2019"], //Want "value 1,2,3 for 2018 and value 4,5,6 for 2019"
datasets: [
{
label: "Harpo",
fillColor: "blue",
data: [] // What should i use here
},
{
label: "Chico",
fillColor: "red",
data: [] // What should i use here
}
]
};
But this is not what i want.
Any help would be appreciated.

in order to have a stack of 3 bars,
you will need 3 datasets.
to have different colors, use an array for backgroundColor.
see following working snippet...
$(document).ready(function() {
new Chart(document.getElementById("myChart").getContext("2d"), {
type: "bar",
data: {
labels: ["2018", "2019"],
datasets: [
{
backgroundColor: ["#673AB7", "#90A4AE"],
fillColor: "#000000",
data: [1, 4]
},
{
backgroundColor: ["#E1BEE7", "#0D47A1"],
data: [2, 5]
},
{
backgroundColor: ["#BA68C8", "#455A64"],
data: [3, 6]
}
]
},
options: {
legend: {
display: false
},
scales: {
xAxes:[{
stacked: true
}],
yAxes:[{
stacked: true
}],
}
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.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="myChart"></canvas>

Related

Add data dynamically to chart

In my code I'm getting an array of inputs arrayinput[] and an array of numbers arraynumber[] from my local storage. The length of the arrays can vary, but it's always arrayinput.length = arraynumber.length.
Now I want to create a horizontal bar chart with these arrays as data.
So arrayinput is on the y axis and arraynumbers on the x axis. But my problem is I don't know how to do that, because the arrays can have any length.
Is it possible to add the arrays to the chart dynamically?
Here I made an example of what I'm trying to do.
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<div class="chartcontainer">
<canvas id="bar-chart-horizontal" ></canvas>
</div>
let arrayinput = ["apple", "banana", "pineapple", "cherry","peach"] ;
let arraynumber = ["5", "10", "3", "8", "1"];
var number=[];
for(var i=0;i<arrayinput.length;i++){
number[i] = parseInt(arraynumber[i]);
}
new Chart(document.getElementById("bar-chart-horizontal"), {
type: 'horizontalBar',
data: {
//here I want all elements of arrayinut
labels: ["apple", "banana", "pineapple", "cherry","peach"],
datasets: [
{
label: "Number of fruits",
//here I need to create arrayinput.length differnt colors but thats not that important now
backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"],
//here I want the elements of number
data: [5,10,3,8,1]
}
]
},
options: {
legend: { display: false },
title: {
display: true,
text: 'Fruits'
},
scales: {
xAxes: [{
ticks: {
beginAtZero: true
}
}]
},
}
});
Yes it is possible, although you are using a verry outdated version of the lib you might want to consider updating it
V2:
const chart = new Chart(document.getElementById("bar-chart-horizontal"), {
type: 'horizontalBar',
data: {
//here I want all elements of arrayinut
labels: [],
datasets: [{
label: "Number of fruits",
//here I need to create arrayinput.length differnt colors but thats not that important now
backgroundColor: ["#3e95cd", "#8e5ea2", "#3cba9f", "#e8c3b9", "#c45850"],
//here I want the elements of number
data: []
}]
},
options: {
legend: {
display: false
},
title: {
display: true,
text: 'Fruits'
},
scales: {
xAxes: [{
ticks: {
beginAtZero: true
}
}]
},
}
});
const addFruits = () => {
chart.data.labels = ["apple", "banana", "pineapple", "cherry", "peach"];
chart.data.datasets[0].data = [5, 10, 3, 8, 1];
chart.update();
}
addFruits()
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<div class="chartcontainer">
<canvas id="bar-chart-horizontal"></canvas>
</div>
V3:
const chart = new Chart(document.getElementById("bar-chart-horizontal"), {
type: 'bar',
data: {
//here I want all elements of arrayinut
labels: [],
datasets: [{
label: "Number of fruits",
//here I need to create arrayinput.length differnt colors but thats not that important now
backgroundColor: ["#3e95cd", "#8e5ea2", "#3cba9f", "#e8c3b9", "#c45850"],
//here I want the elements of number
data: []
}]
},
options: {
indexAxis: 'y',
plugins: {
legend: {
display: false
},
title: {
display: true,
text: 'Fruits'
},
},
scales: {
y: {
beginAtZero: false
}
},
}
});
const addFruits = () => {
chart.data.labels = ["apple", "banana", "pineapple", "cherry", "peach"];
chart.data.datasets[0].data = [5, 10, 3, 8, 1];
chart.update();
}
addFruits()
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.0/chart.min.js"></script>
<div class="chartcontainer">
<canvas id="bar-chart-horizontal"></canvas>
</div>
You can directly use arrayinput inside the function, same for arraynumber.
HTML:
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<div class="chartcontainer">
<canvas id="bar-chart-horizontal"></canvas>
</div>
Javascript:
var arrayinput = ["apple", "banana", "pineapple", "cherry","peach"] ;
var arraynumber = ["5", "10", "3", "8", "1"];
var number=[];
for(var i=0;i<arrayinput.length;i++){
number[i] = parseInt(arraynumber[i]);
}
new Chart(document.getElementById("bar-chart-horizontal"), {
type: 'horizontalBar',
data: {
//here I want all elements of arrayinut
labels: arrayinput,
datasets: [
{
label: "Number of fruits",
//here I need to create arrayinput.length differnt colors but thats not that important now
backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"],
//here I want the elements of number
data: arraynumber
}
]
},
options: {
legend: { display: false },
title: {
display: true,
text: 'Fruits'
},
scales: {
xAxes: [{
ticks: {
beginAtZero: true
}
}]
},
}
});
For using different colors for the chart, you can roughly estimate the maximum number of entries in arrayinput and generate the color array of that size. For example: If you know that entries in the arrayinput will never exceed 1000, you can make an array of 1000 colors, and can make a new array of out of this as per your requirement.
Like this:
var backgroundColor = ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"];
var colorArray = [];
//Max value of arrayinput is say 5
for(var i=0; i<arrayinput.length; i++) {
colorArray.push(backgroundColor[i]);
}
Use this colorArray in the function directly same like arrayinput.
Live Demo Here: https://codepen.io/Hitesh_Vadher/pen/vYZmdMZ

Chart.js find visible data points following zoom

I am trying to find the currently visible data points following a zoom event using chartjs-plugin-zoom. Following examples I came up with the following onZoomComplete callback, but it is not working.
function getVisibleValues({chart}) {
const x = chart.scales.x;
let visible = chart.data.datasets[0].data.slice(x.minIndex, x.maxIndex + 1);
}
One immediate issue is that chart.data doesn't seem to exist (when using console.log(chart.data) it comes back undefined). Same with x.minIndex and x.maxIndex... Any ideas on what I'm doing wrong would be much appreciated.
Below is how I setup the chart (data is an array of x,y pairs):
ctx = new Chart(document.getElementById(ctx_id), {
type: "scatter",
data: {
datasets: [
{
label: "Data",
lineTension: 0,
showLine: true,
data: data,
},
],
},
options: {
animation: false,
plugins: {
zoom: {
zoom: {
mode: "x",
drag: {
enabled: true,
borderColor: "rgb(54, 162, 235)",
borderWidth: 1,
backgroundColor: "rgba(54, 162, 235, 0.3)",
},
onZoomComplete: getVisibleValues,
},
},
},
},
});
You can access the c.chart.scales["x-axis-0"]._startValue and c.chart.scales["x-axis-0"]._valueRange. These two give the first and last visible values respectively.
These values can be used to get the dataset data available at c.chart.config.data.datasets[0].data, or the label names at c.chart.config.data.labels.
If you only need to get the visible tick labels, you can do this by simply accessing the chart.scales["x-axis-0"].ticks object.
function getVisibleValues(c) {
document.getElementById("visibleTicks").textContent = JSON.stringify(
c.chart.scales["x-axis-0"].ticks // This is one way to obtain the visible ticks
);
const start = c.chart.scales["x-axis-0"]._startValue // This is first visible value
const end = start + c.chart.scales["x-axis-0"]._valueRange // This is the last visible value
document.getElementById("visibleValues").textContent = JSON.stringify(
c.chart.config.data.datasets[0].data.slice(start, end + 1) // Access chart datasets
//Note: You can also get the labels from here, these are available at `c.chart.config.data.labels`
);
}
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: "line",
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: "# of Votes",
data: [12, 19, 3, 5, 2, 3]
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
},
plugins: {
zoom: {
zoom: {
// Boolean to enable zooming
enabled: true,
// Zooming directions. Remove the appropriate direction to disable
// Eg. 'y' would only allow zooming in the y direction
mode: "x",
onZoomComplete: getVisibleValues
}
}
}
}
});
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.3/dist/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom#0.7.5/dist/chartjs-plugin-zoom.min.js"></script>
<html>
<body>
Visible ticks: <span id="visibleTicks">Begin zooming</span><br/>Visible data: <span id="visibleValues">Begin zooming</span>
<div class="myChartDiv" style="width: 400px;">
<canvas id="myChart"></canvas>
</div>
</body>
</html>

Chart.js v3: Tooltip callback doesn't identify clicked dataset of stacked bar chart

In Chart.js v2, the datasetIndex property of ChartTooltipItem[] identifies which segment of a stacked bar chart was clicked. This allowed the tooltip content to be customized for each segment of the stacked bar chart.
In v3, TooltipItem[] provides the datasets but does not identify which one was clicked. There is a datasetIndex field for each TooltipItem, but it just matches the index in TooltipItem[] rather than identify the clicked segment.
Has anyone found a field in the V3 tooltip callback to identified which segment of a stacked bar chart was clicked? Or was this functionality lost in the v3 rewrite?
It just works fine, the only thing that is different is that it seems like in v2 it defaulted to the point mode while now it is using index mode, if you change it back to point it works as expected:
var options = {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: 'red'
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
backgroundColor: 'blue'
}
]
},
options: {
plugins: {
tooltip: {
mode: 'point',
callbacks: {
beforeBody: (ttItems, x) => {
ttItems.forEach((ttItem) => {
console.log('BeforeBody: ', ttItem.datasetIndex, ttItem.dataIndex)
})
},
afterBody: (ttItems, x) => {
ttItems.forEach((ttItem) => {
console.log('AfterBody: ', ttItem.datasetIndex, ttItem.dataIndex)
})
}
}
}
},
scales: {
y: {
stacked: true
},
x: {
stacked: true
}
}
}
}
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.4.1/chart.js"></script>
</body>

How do I remove cartesian axes from chart js?

I am trying to personalize a chart.js. But I can not find how to remove (or hide) the X and Y axes.
I am also interested in not showing data on hover and I would like not to show the reference on the top. I am just starting with chart.js and I only need to do a few graphs.
Thank you :)
This is the graph I currently have
datasets: {
label: "I need help plz",
backgroundColor: gradient,
fill: true,
borderColor: "rgb(0, 50, 100)",
borderWidth: 0.001,
tension: 0.4,
radius: 0,
data: dataset,
},
For removing the references on the top this post was useful Chart.js v2 hide dataset labels
As described in the documentation (https://www.chartjs.org/docs/master/axes/#common-options-to-all-axes) you can set in the options of the scale the display to true or false or 'auto' where auto hides the scale if no dataset is visable that is linked to that axis.
For not showing data on hover you can set the tooltip to enabled: false
Example (y auto display and no x axis):
var options = {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1,
backgroundColor: 'red'
}, ]
},
options: {
plugins: {
tooltip: {
enabled: false
}
},
scales: {
y: {
display: 'auto'
},
x: {
display: false
}
}
}
}
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>

In Chart.js multibar graph, is there a way to highlight a single category?

I have a graph like above. I only want one category with a green border. For example, only x-axis 2235 with a border green.
Or some other way to highlight just 2235 green.
Since I'm using a multi-bar graph, I don't know how to apply borderColor or borderWidth to a single point in the dataset. Any ideas? Thanks!
Hope my snippet will help you.
Long story short: I have no idea how to achieve a similar result using only configuration, but manipulating with your chart after initialization does real magic.
Do not forget about chart.update() when you dynamically change something in your chart.
Cheers!
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<canvas id="myChart" width="400" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.0/Chart.min.js"></script>
<script>
const context = document.getElementById("myChart").getContext('2d');
const chart = new Chart(context, {
type: 'bar',
data: {
labels: ["First", "Second", "Third"],
datasets: [{
label: "Red",
backgroundColor: "red",
borderColor: [],
borderWidth: 4,
data: [4, 3, 5]
},
{
label: "Green",
backgroundColor: "green",
borderColor: [],
borderWidth: 4,
data: [7, 2, 6]
},
{
label: "Blue",
backgroundColor: "blue",
borderColor: [],
borderWidth: 4,
data: [3, 7, 4]
},
]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
const color = "yellow";
const indexOfBordered = 1;
chart.data.datasets.forEach(dataset => {
dataset.borderColor[indexOfBordered] = color;
});
chart.update();
</script>
</body>
</html>

Categories