I want to create a chart.js plugin to create waterfall charts.
I am new to working with chart.js. I was thinking to extend the bar-chart to create a waterfall chart.
The draw function in the bar chart controller is as follows:
draw: function(ease) {
var me = this;
var easingDecimal = ease || 1;
helpers.each(me.getMeta().data, function(rectangle, index) {
var d = me.getDataset().data[index];
if (d !== null && d !== undefined && !isNaN(d)) {
rectangle.transition(easingDecimal).draw();
}
}, me);
},
THe full bar chart controller js file can be found here:
https://github.com/chartjs/Chart.js/tree/master/src/controllers
Since Chart.js v2.9.0., we can use floating bars to easily create waterfall charts. Individual bars may since be specified with the syntax [min, max].
Given an array of values [3, 5, 4, 2, 6], we need to produce the following data (last entry being the computed value for the 'Total' bar):
[[0, 3], [3, 8], [8, 12], [12, 14], [14, 20], 20]
The only additional thing left to do is defining a tooltips.callback function that computes the correct value to be shown in the tooltips.
tooltips: {
callbacks: {
label: (tooltipItem, data) => {
const v = data.datasets[0].data[tooltipItem.index];
return Array.isArray(v) ? v[1] - v[0] : v;
}
}
},
Please have a look at the following code sample that produces a waterfall chart out of the baseData array.
let baseData = [
{ label: 'A', value: 3 },
{ label: 'B', value: 5 },
{ label: 'C', value: 4 },
{ label: 'D', value: 2 },
{ label: 'E', value: 6 }
];
const labels = baseData.map(o => o.label).concat('Total');
const data = [];
let total = 0;
for (let i = 0; i < baseData.length; i++) {
const vStart = total;
total += baseData[i].value;
data.push([vStart, total]);
}
data.push(total);
const backgroundColors = data.map((o, i) => 'rgba(255, 99, 132, ' + (i + (11 - data.length)) * 0.1 + ')');
new Chart('waterfall', {
type: 'bar',
data: {
labels: labels,
datasets: [{
data: data,
backgroundColor: backgroundColors,
barPercentage: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
legend: {
display: false
},
tooltips: {
callbacks: {
label: (tooltipItem, data) => {
const v = data.datasets[0].data[tooltipItem.index];
return Array.isArray(v) ? v[1] - v[0] : v;
}
}
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="waterfall" height="200"></canvas>
If the chart should start with the 'Total' bar, simply reverse labels, data and backgroundColors arrays as follows.
data: {
labels: labels.reverse(),
datasets: [{
data: data.reverse(),
backgroundColor: backgroundColors.reverse(),
...
I created a chartjs plugin for waterfall charts.
See https://github.com/MartinDawson/chartjs-plugin-waterfall
This plugin works by checking if any of your datasets contain a property called dummyStack that is set to true. The stack property must be used in conjunction with dummyStack for this plugin to work properly. If dummyStack is true then it hides the label, tooltip and sets the color invisible. When you use stacking with this it creates the affect of a floating bar as shown in the image above that we can use for waterfall charts as chartjs-2 doesn't support waterfall charts by default.
import waterFallPlugin from 'chartjs-plugin-waterfall';
var chart = new Chart(ctx, {
plugins: [waterFallPlugin]
});
const data = {
datasets: [
{
label: 'Closing Costs',
data: [50],
backgroundColor: '#e8cdd7',
stack: 'stack 1',
},
{
label: 'Purchase Price',
data: [700],
backgroundColor: '#d29baf',
stack: 'stack 1',
},
{
data: [200],
dummyStack: true,
stack: 'stack 2',
},
{
label: 'Opening Loan Balance',
data: [550],
backgroundColor: '#bb6987',
stack: 'stack 2',
},
{
label: 'Initial Cash Investment',
data: [200],
backgroundColor: '#a53860',
stack: 'stack 3',
},
],
};
It also has line steps from bar to bar.
You can use the plugin recommented by Chart.JS https://github.com/everestate/chartjs-plugin-waterfall (Ref: https://www.chartjs.org/docs/2.7.2/notes/extensions.html)
Installation
npm install --save chartjs-plugin-waterfall
Usage
import waterFallPlugin from 'chartjs-plugin-waterfall';
var chart = new Chart(ctx, {
plugins: [waterFallPlugin]
});
Related
In this example with universalTransition turned on, after the pie chart of colorBy:'data' is sorted, it is inconsistent with the corresponding relationship between labels and colors in the bar chart, how to make their colors consistent.
Makepie will be out of service on February 15, you can run follow code on ECharts examples editor.
const dataset = {
dimensions: ['name', 'score'],
source: [
['Hannah Krause', 314],
['Zhao Qian', 351],
]
};
const pieOption = {
// dataset: [dataset],
// 顺序排序数据
dataset: [dataset].concat({
transform: {
type: 'sort',
config: { dimension: 'score', order: 'desc' },
},
}),
series: [
{
type: 'pie',
// 通过 id 关联需要过渡动画的系列
id: 'Score',
radius: [0, '50%'],
universalTransition: true,
animationDurationUpdate: 1000,
// 取排序后的数据
datasetIndex: 1,
}
]
};
const barOption = {
dataset: [dataset],
xAxis: {
type: 'category'
},
yAxis: {},
series: [
{
type: 'bar',
// 通过 id 关联需要过渡动画的系列
id: 'Score',
// 每个数据都是用不同的颜色
colorBy: 'data',
encode: { x: 'name', y: 'score' },
universalTransition: true,
animationDurationUpdate: 1000
}
]
};
option = barOption;
setInterval(() => {
option = option === pieOption ? barOption : pieOption;
// 使用 notMerge 的形式可以移除坐标轴
myChart.setOption(option, true);
}, 2000);
Your dataset order by 'desc' on pie chart.
but it's not used on bar chart.
Maybe your two charts should be sorted in the same order
dataset: [dataset].concat({
transform: {
type: 'sort',
config: { dimension: 'score', order: 'desc' },
},
}),
I'm trying to make a a combination of a candlestick chart (representing stock data) and a bar chart (representing volume).
I already have them displayed on one chart but the display and layout I'm having trouble with.
For one, the candlestick and bar data are placed side-by-side rather than stacked on top of each other. Another error is the scale of the volume data for the bar chart is not represented properly in the y-axis (which uses data from candlesticks as basis).
Here is my current code to render the chart:
chart = new Chart(ctx, {
type: 'candlestick',
data: {
labels: labelsData,
datasets: [{
label: "My Data",
data: chartData
},
{
label: 'Volume',
data: volData,
type: 'bar'
}]
}
});
labelsData contains the Date values for each item entry
chartData contains JSON object with c,h,l,o,t (close,high,low,open,date) to
represent stock data for each item entry
volData is an array containing numbers to represent volume for each item entry
What should I add to make the candlesticks and bars placed on the same column, as well as have the bars have their own scale so they do not overshoot the height of the chart?
It seems you need to scale the volume data since it's two different value units in Y,
It seems like currentlty there isn't support for this in chartJs I created a feature request, follow the link to see the two issues that were closed due to this.
https://github.com/apexcharts/apexcharts.js/issues/2068
With default configuration you're not easily able to add barcharts.
Here is steps you need to do;
Base config:
const config = {
// type: 'candlestick', // you must remove this, this option is braking the chart
data: {
datasets: []
},
options: {
parsing: false, // must be here, solves another stupid problem
spanGaps: true, // for better performance
animation: false, // for better performance
pointRadius: 0, // for better performance
plugins: {
title: {
display: false,
text: 'Fiyat Grafiği'
},
},
responsive: true,
maintainAspectRatio: false,
scales: {
x: {
type: 'timeseries',
},
y: {
type: 'linear',
},
volume: {
type: 'linear',
beginAtZero: true,
position: 'right',
max: maxVolume * 10, // maxVolume should be the maximum number of volumes
grid: {
display: false, // for better presentation
},
ticks: {
display: false, // for better presentation
},
}
},
interaction: {
intersect: false,
mode: 'index',
},
}
};
Second step is preparing the datasets;
let dataSets = [
{
type: 'candlestick', // this must stay
label: 'Financial Graph',
data: data['klines'].map(function (kline) {
return {
'x': moment(kline['from']),
'o': kline['open_price'],
'c': kline['close_price'],
'h': kline['high_price'],
'l': kline['low_price']
};
}),
color: {
up: 'rgb(26, 152, 129)', // those colors are better than defaults
down: 'rgb(239, 57, 74)', // those colors are better than defaults
unchanged: '#999', // those colors are better than defaults
},
borderColor: {
up: 'rgb(26, 152, 129)',
down: 'rgb(239, 57, 74)',
unchanged: '#999',
},
order: 10,
yAxisID: 'y', // this must stay
},
{
type: 'bar',
label: 'Volume',
data: data['klines'].map(function (kline) {
return {
'x': moment(kline['from']), // i used moment, feel free to use your own time library
'y': kline.quote_asset_volume,
}
}),
backgroundColor: data['klines'].map(function (kline) {
return kline.open_price < kline.close_price ? 'rgb(26, 152, 129)' : 'rgb(239, 57, 74)' // for better presentation
}),
borderColor: '#fff',
borderWidth: 1,
order: 12,
yAxisID: 'volume', // this must stay
barPercentage: 0.5, // this must stay
barThickness: 6, // this must stay
maxBarThickness: 8, // this must stay
},
]
Result;
First of all, sorry for combining multiple questions in to one. The only reason is all of them are related (hopefully) to one particular chart type.
QUESTION 1: The horizontal baseline is not appearing.
Actual
Requirement
QUESTION 2: Fraction values.
Is there a way to display only integers? I don't need fraction values in grid lines. Please see the above screenshot.
QUESTION 3: Vertical Line annotation text placement.
The annotation text for the vertical black bold line is coming to the right of it hence it is getting cut. Please see the second chart in the following screenshot
This actually needs to appear like this (to the bottom of the line and the annotation text needs to come a bit below base line labels). Please see the following screenshot
Is that is not possible, is there any way to place the annotation text to the left of this line so that it doesn't get cut and the entire annotation text stays inside the chart?
Below is the chart script I am using:
google.charts.load('current', {packages: ['corechart', 'bar']});
google.charts.setOnLoadCallback(drawHorizontalChart_portal_name_stella_york_horz_month_points);
function drawHorizontalChart_portal_name_stella_york_horz_month_points() {
var data = google.visualization.arrayToDataTable([
["", "Goal Achieved", {role: 'style'}, "GOAL 13.1 points", {role: 'style'}, {role: 'annotation'}],
["", 1.5, "opacity: .75;", 13.1, "opacity: 0;", "GOAL 13.1 points"]
]);
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, {
calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation"
}, 3, 4, 5]);
var options = {
title: '',
width: '100%',
height: 120,
chartArea: {
width: '90%',
height: 70
},
hAxis: {
title: '',
minValue: 0,
gridlines: {
count: 6
}
},
bar: {
groupWidth: "60%"
},
legend: {
position: "top"
},
series: {
0: {
color: '#70b5c5',
visibleInLegend: false
}, // Goal Achieved
1: {
color: '#000000',
type: 'line',
annotations: {
textStyle: {
color: '#000000',
textPosition: 'vertical'
},
stemColor: 'none',
vertical: true
}
} // Target Goal
}
};
var chart = new google.visualization.BarChart(document.getElementById("portal-name-stella-york-horz-month-points"));
chart.draw(view, options);
drawVAxisLine(chart, 13.1);
}
jQuery(window).resize(function() {
drawHorizontalChart_portal_name_stella_york_horz_month_points();
});
function drawVAxisLine(chart, value) {
var layout = chart.getChartLayoutInterface();
var chartArea = layout.getChartAreaBoundingBox();
var svg = chart.getContainer().getElementsByTagName('svg')[0];
var xLoc = layout.getXLocation(value)
svg.appendChild(createLine(xLoc, chartArea.top + chartArea.height, xLoc, chartArea.top, '#000000', 2)); // axis line
}
function createLine(x1, y1, x2, y2, color, w) {
var line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('x1', x1);
line.setAttribute('y1', y1);
line.setAttribute('x2', x2);
line.setAttribute('y2', y2);
line.setAttribute('stroke', color);
line.setAttribute('stroke-width', w);
return line;
}
1) horizontal baseline
the horizontal baseline does not appear because you have a string value in the first column
this creates a discrete axis
// string used here --> ["", 1.5, "opacity: .75;", 13.1, "opacity: 0;", "GOAL 13.1 points"]
instead, use a continuous x-axis (number, date, etc...)
// number --> [1, 1.5, "opacity: .75;", 13.1, "opacity: 0;", "GOAL 13.1 points"]
in order to hide the axis label, as done using the string, we can provide custom axis ticks
we can use object notation to provide both the value (v:) and the formatted value (f:)
which allows us to provide an empty string for the formatted value
just make sure the tick value matches the value provided in the first column above.
vAxis: {
gridlines: {
color: 'transparent'
},
ticks: [{v: 1, f: ''}]
}
note: a continuous axis will also cause other gridlines to appear,
we can remove those by making them transparent...
2) Fraction values
we can provide a format string for the axis labels...
hAxis: {
format: '0' // <-- format as integer
},
3) annotation text placement
the only available option here is stem.length
we can provide a negative value to move the annotation to the left...
stem: {
color: 'transparent',
length: -128
},
however, the actual position will not remain constant as the chart is resized
when the chart is smaller, the text will be farther away from the line (larger closer).
instead, we can manually move the annotation text, on the chart's 'ready' event.
but we should still use a negative stem length, to ensure the annotation appears to the left, and prevent from being cut. otherwise, we'll end up moving a cut annotation.
and since we're moving the annotation below the axis,
we need to increase chartArea.bottom or else it will be cut there as well.
finally, the chart will reset the annotation's position on any interactivity,
such as hover. we must use a MutationObserver to keep the annotation in the new position.
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(drawHorizontalChart_portal_name_stella_york_horz_month_points);
function drawHorizontalChart_portal_name_stella_york_horz_month_points() {
var data = google.visualization.arrayToDataTable([
["", "Goal Achieved", {role: 'style'}, "GOAL 13.1 points", {role: 'style'}, {role: 'annotation'}],
[1, 1.5, "opacity: .75;", 13.1, "opacity: 0;", "GOAL 13.1 points"]
]);
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, {
calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation"
}, 3, 4, 5]);
var options = {
title: '',
width: '100%',
height: 132,
chartArea: {
height: '100%',
width: '100%',
top: 36,
left: 18,
right: 18,
bottom: 48
},
hAxis: {
title: '',
minValue: 0,
gridlines: {
count: 6
},
format: '0'
},
bar: {
groupWidth: "60%"
},
legend: {
position: "top"
},
series: {
0: {
color: '#70b5c5',
visibleInLegend: false
}, // Goal Achieved
1: {
color: '#000000',
type: 'line',
annotations: {
textStyle: {
color: '#000000'
},
stem: {
color: 'transparent',
length: -128
},
vertical: true
}
} // Target Goal
},
vAxis: {
gridlines: {
color: 'transparent'
},
ticks: [{v: 1, f: ''}]
}
};
var chart = new google.visualization.BarChart(document.getElementById("portal-name-stella-york-horz-month-points"));
google.visualization.events.addListener(chart, 'ready', function () {
// get x location of goal
var layout = chart.getChartLayoutInterface();
var xLoc = drawVAxisLine(chart, layout, data.getValue(0, 3));
// prevent annotation reset
var observer = new MutationObserver(function () {
var annotationText = data.getValue(0, data.getNumberOfColumns() -1);
Array.prototype.forEach.call(chart.getContainer().getElementsByTagName('text'), function(annotation) {
// find annotation
if ((annotation.textContent === annotationText) &&
(annotation.getAttribute('fill') === options.series[1].annotations.textStyle.color)) {
// move annotation
annotationBounds = annotation.getBBox();
annotation.setAttribute('x',
xLoc - (annotationBounds.width / 2)
);
annotation.setAttribute('y',
layout.getYLocation(0) + (parseInt(annotation.getAttribute('font-size')) * 3)
);
}
});
});
observer.observe(chart.getContainer(), {
childList: true,
subtree: true
});
});
chart.draw(view, options);
}
jQuery(window).resize(function() {
drawHorizontalChart_portal_name_stella_york_horz_month_points();
});
function drawVAxisLine(chart, layout, value) {
var chartArea = layout.getChartAreaBoundingBox();
var svg = chart.getContainer().getElementsByTagName('svg')[0];
var xLoc = layout.getXLocation(value)
svg.appendChild(createLine(xLoc, chartArea.top + chartArea.height, xLoc, chartArea.top, '#000000', 2)); // axis line
return xLoc;
}
function createLine(x1, y1, x2, y2, color, w) {
var line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('x1', x1);
line.setAttribute('y1', y1);
line.setAttribute('x2', x2);
line.setAttribute('y2', y2);
line.setAttribute('stroke', color);
line.setAttribute('stroke-width', w);
return line;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="portal-name-stella-york-horz-month-points"></div>
note: you should wait for the 'ready' event before making any changes / adding elements to the chart.
I am creating a horizontal bar chart using Google charts and I want to position the horizontal axis tick labels between ticks (offset tick label to the right by half a tick). There is also no guarantee that each label will be the same number of characters. Is there any functionality to achieve this?
This is my function for creating the chart
function drawChart() {
var data = google.visualization.arrayToDataTable([
["Performance", "Level", { role: "style" }],
["PL", 1.01, "#5aa66d"]
]);
var view = new google.visualization.DataView(data);
view.setColumns([0, 1,
{
calc: function (dt, rowIndex) { return 'PL=' + (dt.getValue(rowIndex, 1)).toString()} ,
sourceColumn: 1,
type: "string",
role: "annotation"
},
2]);
var options = {
width: 600,
height: 100,
bar: { groupWidth: "80%" },
legend: { position: "none" },
hAxis: {
minValue: 0,
maxValue: 3,
ticks: [
{ v: 0, f: 'Col1' },
{ v: 1, f: 'Col2' },
{ v: 2, f: 'Col3' },
{ v: 3, f: 'Col4' }
]
}
};
var chart = new google.visualization.BarChart(document.getElementById("barchart_values"));
chart.draw(view, options);
}
This is the chart currently
https://imgur.com/LvQEbtY
and this is what I want to achieve:
https://imgur.com/hwvIOG2
EDIT:
For ideas, right before chart.draw I add an event listener and find all the text tags and modify the 'x' attribute to re-position the tick labels. This works, but it also affects the on-bar data label which is a problem.
google.visualization.events.addListener(chart, 'ready', function () {
var elements = document.getElementById("barchart_values").getElementsByTagName("text");
for (var i = 0; i < elements.length; i++) {
elements[i].setAttribute('x', (Number(elements[i].getAttribute('x')) + (chart.getChartLayoutInterface().getBoundingBox('chartarea').width / 4 / 2))); //chart width / tick count / 2
}
});
first, we won't be able to offset the grid lines and use the ticks option.
let's offset the grid lines by making the major transparent and the minor visible.
we can also offset the baseline by setting to a negative value.
baseline: -0.5,
minorGridlines: {
color: '#cccccc',
count: 1
},
gridlines: {
color: 'transparent',
count: 4
},
then, in order to have custom tick labels, we can use your original idea to change them manually.
just need a unique attribute to separate them from the bar labels.
here, the text-anchor attribute is used.
if (elements[i].getAttribute('text-anchor') === 'middle') {
elements[i].textContent = 'Col' + parseInt(elements[i].textContent) + 1;
}
see following working snippet...
google.charts.load('current', {
packages:['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
["Performance", "Level", { role: "style" }],
["PL", 1.01, "#5aa66d"]
]);
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, {
calc: function (dt, rowIndex) { return 'PL=' + (dt.getValue(rowIndex, 1)).toString()} ,
sourceColumn: 1,
type: "string",
role: "annotation"
}, 2]);
var options = {
width: 600,
height: 100,
bar: { groupWidth: "80%" },
legend: { position: "none" },
hAxis: {
baseline: -0.5,
minorGridlines: {
color: '#cccccc',
count: 1
},
gridlines: {
color: 'transparent',
count: 4
},
minValue: 0,
maxValue: 3,
}
};
var chart = new google.visualization.BarChart(document.getElementById("barchart_values"));
google.visualization.events.addListener(chart, 'ready', function () {
var elements = document.getElementById("barchart_values").getElementsByTagName("text");
for (var i = 0; i < elements.length; i++) {
if (elements[i].getAttribute('text-anchor') === 'middle') {
elements[i].textContent = 'Col' + (parseInt(elements[i].textContent) + 1);
}
}
});
chart.draw(view, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="barchart_values"></div>
the above will ensure all the labels remain visible, just simply moving them, could cause them to be pushed off the visible portion of the chart.
Excellent and free library from chart.js. I'm transferring my charts from Google charts to chart.js, because I can use them offline and it seems more responsive to window's changes of size. Furthermore I realised that my viewers in China could not see my Google charts because Google services are blocked in China.
I've been reading the documentation regarding stacked vertical bar charts, but I can't figure out, how to make a chart like this. In all examples I saw for stacked bar charts, the number of items is the same for each bar.
Can I make only two vertical stacked datasets? It's because the right bar has more items than the left one. Or do I need n datasets, being n the number of items, of the bar which has more items?
Code
I want to group one dataset per (stacked) bar, but I can't.
var ctx = document.getElementById("barChart").getContext('2d');
var labels = ["standing costs", "running costs"];
var dataset = [
{
type: 'bar',
label: ["cost1", "cost2", "cost3", "cost4"],
data: [1, 2, 1, 3],
stack: "standing costs",
backgroundColor: [
'navy',
'blue',
'aqua',
'teal'
]
},
{
type: 'bar',
label: ["cost5", "cost6", "cost7", "cost8"],
data: [5, 1, 3, 0],
stack: "running costs",
backgroundColor: [
'green',
'lime',
'yellow',
'white'
]
}
];
var options = {
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true
}]
}
};
var content = {
type: 'bar',
data: {
labels: labels,
datasets: dataset
},
options
};
new Chart(ctx, content);
#import url("https://cdnjs.cloudflare.com/ajax/libs/colors/1.0/colors.min.css");
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.0/Chart.bundle.min.js"></script>
<canvas id="barChart"></canvas>
Quick Solution :
Vertical Stacked Bar Chart
var chart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Standing costs', 'Running costs'], // responsible for how many bars are gonna show on the chart
// create 12 datasets, since we have 12 items
// data[0] = labels[0] (data for first bar - 'Standing costs') | data[1] = labels[1] (data for second bar - 'Running costs')
// put 0, if there is no data for the particular bar
datasets: [{
label: 'Washing and cleaning',
data: [0, 8],
backgroundColor: '#22aa99'
}, {
label: 'Traffic tickets',
data: [0, 2],
backgroundColor: '#994499'
}, {
label: 'Tolls',
data: [0, 1],
backgroundColor: '#316395'
}, {
label: 'Parking',
data: [5, 2],
backgroundColor: '#b82e2e'
}, {
label: 'Car tax',
data: [0, 1],
backgroundColor: '#66aa00'
}, {
label: 'Repairs and improvements',
data: [0, 2],
backgroundColor: '#dd4477'
}, {
label: 'Maintenance',
data: [6, 1],
backgroundColor: '#0099c6'
}, {
label: 'Inspection',
data: [0, 2],
backgroundColor: '#990099'
}, {
label: 'Loan interest',
data: [0, 3],
backgroundColor: '#109618'
}, {
label: 'Depreciation of the vehicle',
data: [0, 2],
backgroundColor: '#109618'
}, {
label: 'Fuel',
data: [0, 1],
backgroundColor: '#dc3912'
}, {
label: 'Insurance and Breakdown cover',
data: [4, 0],
backgroundColor: '#3366cc'
}]
},
options: {
responsive: false,
legend: {
position: 'right' // place legend on the right side of chart
},
scales: {
xAxes: [{
stacked: true // this should be set to make the bars stacked
}],
yAxes: [{
stacked: true // this also..
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="ctx" width="700"></canvas>
apology for not giving explanation.
updated for v3
<div style="height: 500px">
<canvas id="chart_1" ></canvas>
</div>
<script>
chart = new Chart(document.getElementById('chart_1').getContext('2d'), {
type: 'bar',
data: {
labels: ["One", "Two", "Three"],
datasets: [{
label: 'Blue',
data: [100, 110, 120],
backgroundColor: 'blue',
},
{
label: 'Red',
data: [30, 20, 10],
backgroundColor: 'red',
},
]
},
options: {
plugins: {
title: {
display: true,
text: 'Example',
font: {
size: 14
}
},
},
responsive: true,
maintainAspectRatio: false,
scales: {
x: {
stacked: true,
},
y: {
stacked: true
}
}
}
});
</script>