Related
I want to create stacked bar chart with groups in use chart.js v3. I
my chart output
I did it and i am getting the following image. But here, instead of the sum of label 1 and label2 appearing as 7000, how can I show the intersection of label 1 and label 2 together as 4000 by starting from the x-axis.
type: 'bar',
data: {
labels: labelsVals,
datasets: [
{
label: 'Label 1',
data: seriesValsPaid,
backgroundColor: 'rgba(21, 169, 225, 0.6)',
borderColor: 'rgba(21, 169, 225, 1)',
borderWidth: 1,
stack: 'first',
},
{
label: 'Label 2',
data: seriesValsWaiting,
backgroundColor: 'rgba(21, 122, 225, 0.6)',
borderColor: 'rgba(21, 122, 225, 1)',
borderWidth: 1,
stack: 'first',
},
{
label: 'Label 3',
data: seriesValsOutgoing,
backgroundColor: 'rgba(255, 0, 0, 0.6)',
borderColor: 'rgba(255, 0, 0, 1)',
borderWidth: 1,
stack: 'second',
}
]
},
});
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
'bar-x-axis1': {
stacked: true,
display:false
},
'bar-x-axis2': {
stacked: true,
display:false
},
y: {
stacked: false,
beginAtZero: true
// display:false
}
}
}
This is how I solved the problem.
I want to display text on slices itself rather than displaying it on hover as displayed below
While creating a doughnut chart you'll have to add required data values and labels in code as below,
{
type: 'doughnut',
data: {
datasets: [
{
data: [10, 20, 15, 5, 50],
backgroundColor: [ 'rgb(255, 99, 132)', 'rgb(255, 159, 64)', 'rgb(255, 205, 86)', 'rgb(75, 192, 192)', 'rgb(54, 162, 235)', ],
},
],
labels: ['Red', 'Orange', 'Yellow', 'Green', 'Blue'],
},
options: {
plugins: {
datalabels: {
formatter: (value) => {
return value + '%';
}
}
}
}
}
For more info and documentation check this out : https://quickchart.io/documentation/chart-js/custom-pie-doughnut-chart-labels/
I'm using chart.js and chartjs-plugin-annotation to highlight areas on a graph:
The following config generates the result above:
annotation: {
events: ["click"],
annotations: [
{
type: "box",
drawTime: "beforeDatasetsDraw",
xScaleID: 'x-axis-0',
yScaleID: 'y-axis-0',
xMin: "2019-08-09T07:00:00Z",
xMax: "2019-08-09T09:00:00Z",
yMin: 0,
yMax: 7,
borderWidth: 0,
backgroundColor: "rgba(230,97,79,0.3)",
onClick: function (e) {
console.log("Annotation", e.type, this);
}
}
]
}
I want to be able to highlight a single hour, though:
Anyone if this is possible using the annotations plugin?
To be able to reproduce your request i used annotation type line instead of box.
Annotation type line only accepts borderWidth for thickness of the line.
Because the borderWidth needs to match the column size, i got the width of the chart chart.width, and i divided it to the number of columns chart.data.datasets[0].data.length. Of course i used Chart.js Plugin extension hooks for that:
afterInit (Called after chart has been initialized and before the first update.)
resize (Called after the chart as been resized.)
Code:
var ctx = document.getElementById("myChart");
var dataAnnotation = [
{
type: 'line',
mode: 'vertical',
scaleID: 'x-axis-0',
value: "2019-08-09T08:00:00Z",
borderColor: 'rgba(255, 99, 132, 0.2)',
borderWidth: null,
onClick: function (e) {
console.log("Annotation", e.type, this);
}
},
{
type: 'line',
mode: 'vertical',
scaleID: 'x-axis-0',
value: "2019-08-09T11:00:00Z",
borderColor: 'rgba(255, 99, 132, 0.2)',
borderWidth: null,
onClick: function (e) {
console.log("Annotation", e.type, this);
}
}
];
Chart.plugins.register({
resize: function(chart) {
columns = chart.data.datasets[0].data.length;
chartWidth = chart.width - 40;
setBorderWidth = chartWidth / columns;
annotationsData = chart.options.annotation.annotations.map(function(item){
item.borderWidth = setBorderWidth;
return item;
});
chart.options.annotation.annotations = annotationsData;
chart.update();
},
afterInit: function(chart) {
columns = chart.data.datasets[0].data.length;
chartWidth = chart.width - 40;
setBorderWidth = chartWidth / columns;
annotationsData = dataAnnotation.map(function(item){
item.borderWidth = setBorderWidth;
return item;
});
chart.options.annotation.annotations = annotationsData;
chart.update();
}
});
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: [
"2019-08-09T07:00:00Z",
"2019-08-09T08:00:00Z",
"2019-08-09T09:00:00Z",
"2019-08-09T10:00:00Z",
"2019-08-09T11:00:00Z",
"2019-08-09T12:00:00Z"
],
datasets: [{
label: '# of Tomatoes',
data: [2, 10, 3, 5, 12, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(239, 169, 249, 0.2)',
'rgba(255, 133, 27, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(239, 169, 249, 1)',
'rgba(255, 133, 27, 1)'
],
borderWidth: 1,
fill: false,
lineTension: 0
}]
},
options: {
responsive: true,
scales: {
xAxes: [{
ticks: {
beginAtZero: true,
stepSize: 1,
callback: function(label, index, labels) {
var local = moment.utc(label).toDate();
var format = moment(local).format("dd HH:mm");
return format;
}
}
}],
yAxes: [{
ticks: {
beginAtZero: true,
stepSize: 1
}
}]
},
annotation: {
drawTime: 'afterDraw',
events: ["click"]
}
}
});
Online demo:
https://jsfiddle.net/ZsharE/8nec704L/
Known bugs: click handler works outside annotations !
chartjs-plugin-datalabels supports displaying of inforamtion related to the value, data, context of the graph content. Need to display image along with the text label on each graph based on the values . Refer attached snapshot
Tried custom option for toopltip but basically need to try rendering of html in the plugin data label so as image can also be added
plugins: {
datalabels: {
anchor: 'end',
align: 'start',
font: {
size: 20,
}
}
}
Display image on the bar
Expected Result :
This can be achieved by combining chartjs-plugin-datalabels with chartjs-plugin-labels as follows:
new Chart(document.getElementById('myChart'), {
type: 'bar',
data: {
labels: ['2009', '2010', '2011', '2012'],
datasets: [{
label: 'My First Dataset',
data: [25, 59, 80, 76],
fill: false,
backgroundColor: ['rgba(255, 99, 132, 0.2)', 'rgba(255, 159, 64, 0.2)', 'rgba(255, 205, 86, 0.2)', 'rgba(75, 192, 192, 0.2)'],
borderColor: ['rgb(255, 99, 132)', 'rgb(255, 159, 64)', 'rgb(255, 205, 86)', 'rgb(75, 192, 192)', 'rgb(54, 162, 235)'],
borderWidth: 1
}]
},
options: {
plugins: {
datalabels: {
anchor: 'end',
align : 'start'
},
labels: {
render: 'image',
textMargin: -60,
images: [
null,
null,
{
src: 'https://i.stack.imgur.com/9EMtU.png',
width: 20,
height: 20
},
null
]
}
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
canvas {
max-width: 300px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels"></script>
<script src="https://cdn.jsdelivr.net/gh/emn178/chartjs-plugin-labels/src/chartjs-plugin-labels.js"></script>
<canvas id="myChart" width="10" height="5"></canvas>
I have the below stacked group chart.
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<script>
var barChartData = {
labels: ['January', 'March', 'June', 'September', 'December'],
datasets: [{
label: 'Apple',
borderColor: 'rgba(255, 50, 50,1)',
backgroundColor: 'rgba(255, 50, 50,0.5)',
stack: 'Stack 0',
data: [3,6,4,8,2]
}, {
label: 'Orange',
borderColor: 'rgba(255, 160, 242,1)',
backgroundColor: 'rgba(255, 160, 242,0.5)',
stack: 'Stack 0',
data: [2,1,3,0,1]
}, {
label: 'Pear',
borderColor: 'rgba(79, 158, 255,1)',
backgroundColor: 'rgba(79, 158, 255,0.5)',
stack: 'Stack 0',
data: [3,4,1,5,2]
}, {
label: 'Apple',
borderColor: 'rgba(255, 50, 50,1)',
backgroundColor: 'rgba(255, 50, 50,0.5)',
stack: 'Stack 1',
data: [7,16,10,8,5]
},{
label: 'Mango',
borderColor: 'rgba(100, 244, 97,1)',
backgroundColor: 'rgba(100, 244, 97,0.5)',
stack: 'Stack 1',
data: [4,9,12,5,7]
}, {
label: 'Banana',
borderColor: 'rgba(255, 252, 91,1)',
backgroundColor: 'rgba(255, 252, 91,0.5)',
stack: 'Stack 1',
data: [3,6,13,14,5]
}, {
label: 'Orange',
borderColor: 'rgba(255, 160, 242,1)',
backgroundColor: 'rgba(255, 160, 242,0.5)',
stack: 'Stack 1',
data: [7,12,3,0,2]
}, {
label: 'Cherry',
borderColor: 'rgba(255, 132, 38,1)',
backgroundColor: 'rgba(255, 132, 38,0.5)',
stack: 'Stack 1',
data: [8,4,7,11,6]
}, {
label: 'Pear',
borderColor: 'rgba(79, 158, 255,1)',
backgroundColor: 'rgba(79, 158, 255,0.5)',
stack: 'Stack 1',
data: [8,14,9,12,16]
}]
};
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
legend: {
display:true,
},
tooltips: {
mode: 'x',
intersect: false
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
}
}
});
</script>
I would like to do two things:
1) Remove the redundant Apple, Orange and Pear labels
2) Highlight/Darken just the border on the individual stacks in the graph with the colors of those individual stacks. Like how the legend is.
Any help would be greatly appreciated.
Image of my graph
You can add custom logic to legend options like:
options: {
legend: {
display: true,
labels: {
generateLabels: function (chart) { ...
You can reach the labels here, customize their color, text, you can group them etc. So in this case you have to group the labels by their text first like
const labelTexts = []
const newLabels = []
labels = Chart.defaults.global.legend.labels.generateLabels(chart);
// group labels
labels.map((label) => {
if (labelTexts.indexOf(label.text) === -1) {
labelTexts.push(label.text)
}
})
labelTexts.map((text) => {
labels.map((label) => {
if (label.text === text) {
newLabels.push(label)
}
})
})
Then you can remove the redundant labels like:
for (var i = 0; i < newLabels.length - 2; i++) {
if (newLabels[i].text !== newLabels[i + 1].text) {
newLabels2.push(newLabels[i])
}
}
Check a working example here