Can Chart.js v2.x generate a combined stacked bar chart with 2 unstacked lines utilizing one y-axis? If so, how?
Below fiddle has 2 y-axis. The descending line, would render better if the right y-axis had a maximum value of 6000 as does the left axis.
jsfiddle example.
Below is the code for reference.
// set default no fill beneath the line
Chart.defaults.global.elements.line.fill = false;
// stacked bar with 2 unstacked lines - nope
var barChartData = {
labels: ['2016', '2017', '2018', '2019'],
datasets: [{
type: 'bar',
label: 'a',
yAxisID: "y-axis-0",
backgroundColor: "rgba(217,83,79,0.75)",
data: [1000, 2000, 4000, 5000]
}, {
type: 'bar',
label: 'b',
yAxisID: "y-axis-0",
backgroundColor: "rgba(92,184,92,0.75)",
data: [500, 600, 700, 800]
}, {
type: 'line',
label: 'c',
yAxisID: "y-axis-0",
backgroundColor: "rgba(51,51,51,0.5)",
data: [1500, 2600, 4700, 5800]
}, {
type: 'line',
label: 'd',
yAxisID: "y-axis-1",
backgroundColor: "rgba(151,187,205,0.5)",
data: [5000, 3000, 1000, 0]
}]
};
var ctx = document.getElementById("chart").getContext("2d");
// allocate and initialize a chart
var ch = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
title: {
display: true,
text: "Chart.js Bar Chart - Stacked"
},
tooltips: {
mode: 'label'
},
responsive: true,
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true,
position: "left",
id: "y-axis-0",
}, {
stacked: false,
position: "right",
id: "y-axis-1",
}]
}
}
});
Turns out, I just needed a modification or two so that the 2 y-axis use the same scale. See this jsfiddle. Now the chart renders better. The key, in my case, is adding a ticks node and these two properties to both yAxes objects:
ticks: {
beginAtZero: true,
suggestedMax: 5800
}
Naturally, the suggestedMax value would not be hard coded. Further, since the 2 scales are now the same, I hid the right scale with this property setting display: false.
As the fiddle shows, we now have 2 unstacked lines on a stacked bar chart nicely rendered.
Use this as the data for the graph:
var barData = {
labels: ['test1','test2'],
datasets: [
{
label: 'stack1',
backgroundColor: 'yellow',
borderColor: 'white',
borderWidth: 1,
stack: '1',
data: [5,4,3,2,1]
},
{
label: 'stack2',
backgroundColor: 'blue',
borderColor: 'white',
borderWidth: 1,
stack: '2',
data: [1,2,3,4,5]
}
]
};
This is the component to render the data:
<Bar data={barData} options={{scales: { xAxes: [{stacked:true}} }], yAxes:[{stacked:true}}] } }}}} />
Related
I'm graphing some stocks data and I wanted to put the volume in a smaller gray bar dataset at the bottom, like in Yahoo Finance.
What I want:
The small grey dataset is at the bottom.
What I get:
Three different Y scales and the size of the volume dataset is the same a the other.
My code:
When I create the chart:
new Chart(context, {
type: 'line',
data: {
labels: timestamps.map(n =>
(new Date(n * 1000)).toLocaleString()
),
datasets: [
dataset,
vdataset
]
},
options: {
maintainAspectRatio: false,
scales: {
xAxis: {
// type: 'time'
ticks: {
//autoSkip: true,
maxTicksLimit: 10
}
},
yAxes: [{
id: 'volume',
display: false
}],
y: {
beginAtZero: false
},
},
animation: {
duration: 0
},
plugins: {
autocolors: false,
annotation: {
annotations
}
},
tooltips: {
mode: 'nearest'
},
hover: {
intersect: false
}
}
});
The volume dataset:
{
type: 'bar',
label: `Volume`,
data: ...,
backgroundColor: 'transparent',
borderColor: 'grey',
fill: 'origin',
pointRadius: 0,
borderWidth: 2,
yAxisID: 'volume'
}
you need to give every dataset a yAxisID and then you should name your axis with that id like this:
Data:
var data = {
labels: labels,
datasets: [{
label: 'My First Dataset',
data: generateTestSeries(),
fill: false,
borderColor: 'rgb(75, 192, 192)',
tension: 0.1,
yAxisID: "something",
},
{
label: 'My Second Dataset',
data: generateTestSeries(),
fill: false,
borderColor: 'rgb(182, 50, 192)',
tension: 0.1,
yAxisID: "volume",
},
]
};
Scales:
scales: {
volume: {
axis: "y",
min: -80,
max: 60,
position: 'right',
},
something: {
axis: "y",
min: -20,
max: 70,
position: 'left',
}
}
Also you shouldn't have the list yAxes, that was how axes were defined in chartjs 2.x
Here is a fiddle to see this in use: JSFiddle
edit: If you want an invisible axis just set display to false as seen in the now updated Fiddle.
I have used horizontal bar chart from chart.js where i need percentage values to be shown next to each bar at right side? here is the bar sample image.
click here to view sample image of bar chart
Also these are the options i have tried :
xAxes: [
{
ticks: {
min: 0,
max: 100
},
grid: {
offset: false
}
},
],
yAxes: [
{
gridLines: {
display: false,
},
display: "right",
barPercentage: 0.8,
minBarLength: 2,
},
],
Is there any option which can turn the percentage values on at he right side of the horizontal bar chart?
Please click below image to see the expected output
click image expected output
You can make use of the datalabels plugin
Example:
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.3.0/dist/chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#2.0.0-rc"></script>
<canvas id="myChart" width="850" height="520"></canvas>
<script>
var ctx = document.getElementById('myChart');
Chart.register(ChartDataLabels);
Chart.defaults.set('plugins.datalabels', {
color: '#FE777B'
});
var myChart = new Chart(ctx, {
type: 'bar',
plugins: [ChartDataLabels],
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
data: [12, 19, 3, 5, 2, 3],
label: 'Advisor Closed MTD',
backgroundColor: 'rgb(192,111,94)',
barThickness: 25,
datalabels: {
color: '#FFCE56'
}
}],
},
options: {
indexAxis: 'y',
responsive: false,
plugins: {
datalabels: {
formatter: (val, context) => (`${val}%`),
anchor: 'end',
align: 'end',
labels: {
value: {
color: 'blue'
}
}
}
}
}
});
</script>
I'm using a chartJS Horizontal Bar to visualize some data & the annotation plugin to add vertical lines in the plot area.
What I want to accomplish: showing annotation values/color-box in the tooltip.
What I've done thus far: I've added in bar charts to get the values in the tooltip. (see images & code below).
Where I'm stuck: I would like to hide/offset aBar 1 & aBar 2; in other words, I don't want these bars to appear at all, but I do want the entries to appear in the tooltip. (please see second image).
Current Output
Desired Output
Code
var ctx = document.getElementById("myChart").getContext("2d");
var myChart = new Chart(ctx, {
type: 'horizontalBar',
data: {
labels: false, // RANGE
datasets: [
{
type: 'horizontalBar',
label: 'Bar 1',
backgroundColor: 'rgba(121,185,29,0.85)',
stack: 'Stack 0',
data: [
16 ],
borderColor: 'white',
borderWidth: 0.5
},
{
type: 'horizontalBar',
label: 'Bar 2',
backgroundColor: 'rgba(246,171,0,0.3125)',
stack: 'Stack 0',
data: [
24 ]
},
{
type: 'horizontalBar',
label: 'Bar 3',
backgroundColor: 'rgba(226,33,27,0.5)',
stack: 'Stack 0',
data: [
80 ]
},
{
type: 'horizontalBar',
label: 'aBar 1',
backgroundColor: '#20C5CB',
stack: 'Stack 1',
data: [
6 ]
},
{
type: 'horizontalBar',
label: 'aBar 2',
backgroundColor: '#7f3391',
stack: 'Stack 2',
data: [
120 ]
},
]
},
options: {
responsive: true,
legend:false,
responsive: true,
maintainAspectRatio: false,
title: false,
tooltips: {
mode: 'index',
intersect: true,
bodyFontSize:10,
titleFontSize:0,
titleMarginBottom:0,
},
plugins: {
labels:false,
},
scales: {
xAxes: [{
ticks: {
max: 124,
min: 0,
stepSize: 10
}
}]
},
annotation: {
annotations: [
{
type: 'line',
mode: 'vertical',
scaleID: 'x-axis-0',
value: 6,
borderColor: '#20C5CB',
borderWidth: 3,
borderDash: [6,3],
label: {
enabled: false,
content: 'Annotation 2',
fontSize: 8,
fontStyle: 'normal',
rotation: 0,
xPadding: 2,
yPadding: 2,
cornerRadius: 1,
}
},
{
type: 'line',
mode: 'vertical',
scaleID: 'x-axis-0',
value: 120,
borderColor: '#7f3391',
borderWidth: 3,
label: {
enabled: false,
content: 'Annotation 1',
fontSize: 8,
fontStyle: 'normal',
rotation: 0,
xPadding: 2,
yPadding: 2,
cornerRadius: 1,
}
}
]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-annotation/0.5.7/chartjs-plugin-annotation.min.js"></script>
<canvas id="myChart"></canvas>
Add the hidden tag to datasets of the series you want to hide like this:
type: 'horizontalBar',
label: 'aBar 1',
backgroundColor: '#20C5CB',
stack: 'Stack 1',
hidden: true,
data: [6],
and use a callback to the label tooltip like this:
tooltips: {
mode: 'index',
intersect: true,
bodyFontSize:10,
titleFontSize:0,
titleMarginBottom:0,
callbacks: {
label: function(tooltipItem, data) {
return data.datasets.map(ds => ds.label + ': ' + ds.data[tooltipItem.index])
}
}
},
Found solution here: Chartjs show hidden data on tooltip
I have a simple bar chart and I'm using the datalabels plugin to place labels inside each bar and at the top.
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['One', "Two"],
datasets: [{
data: [40, .5],
backgroundColor: [
'rgba(255, 99, 132)',
'rgba(54, 162, 235)'
],
borderWidth: 1
}]
},
options: {
legend: {
display: false
},
tooltips: {
enabled: false
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
max: 40
},
}],
xAxes: [{
maxBarThickness: 50
}]
},
plugins: {
datalabels: {
display: true,
anchor: 'end',
align: 'top',
color: 'white',
offset: -30,
font: {
weight: 'bold',
size: 14
}
}
}
}
});
But sometimes, I'll have a value that doesn't allow enough room for the label. See second bar on https://jsfiddle.net/myckxLun/1/.
I want to make sure I have X amount of room for these labels. I've tried minBarLength for the Y-axis - but all this does is force the bar length to be a min pixel value and doesn't adjust the graph (i.e. the bar length is inaccurate).
Ideas on how I can fix this? Thanks!
I following the example of Chart.js for a stacked colum graph
http://www.chartjs.org/samples/latest/charts/bar/stacked-group.html
But when I try to replicate for my graph... the stack parameter does not works.
I use the version 2.4.
Here is my code
var color = Chart.helpers.color;
var barChartData = {
labels: [1,2,3,4,5,6,7]<?php // echo ($asse) ?> ,
datasets: [
{
label: '2016',
backgroundColor: color('#FCB441').alpha(0.5).rgbString(),
borderColor: '#FCB441',
borderWidth: 1,
data: [2,4,6,8,10,12,14] ,
stack: 0,
},
{
label: '2017',
backgroundColor: color('#FF0000').alpha(0.5).rgbString(),
borderColor: '#FF0000',
borderWidth: 2,
data: [2,4,6,8,10,12,14] ,
stack: 0,
},
{
label: '3',
backgroundColor: color('#FFFF00').alpha(0.5).rgbString(),
borderColor: '#FFFF00',
borderWidth: 2,
data: [1,2,3,4,5,6,7] ,
stack: 1,
},
]
};
window.onload = function() {
var ctx = document.getElementById('Chart_<?php echo $this->id ?>').getContext('2d');
window.myBar = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
tooltips: {
mode: 'index',
intersect: false
},
responsive: true,
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true
}]
}
}
});
};
`});
Here is my graph:
My Graph
I still don't get it where's my mistake, it seems like the demo code.
Thanks in advice.
Phil