I generate a graph where I have 3 groups of data:
bottom
middle
top
Each bar has the top values at the top of the bar, then the middle value and then the bottom value.
When Chart.js displays the tooltip, I have first the bottom value, then the middle and the the top. So, it is the opposite of the order in the bar.
To display the values I added this code
var stackedBarChartOptions = {
responsive: true,
maintainAspectRatio: false,
tooltips: {
mode: 'label',
callbacks: {
label: function (tooltipItem, data) {
return data.datasets[tooltipItem.datasetIndex].label + ": " +
tooltipItem.yLabel;
}
}
}
}
Is it possible to order the list of tool tips?
in the tooltip label callback, we can choose any index to display.
in your callback, you're displaying the index passed to the callback.
tooltipItem.datasetIndex
instead, let's display the reverse order...
data.datasets.length - 1 - tooltipItem.datasetIndex
but we will also have to add the callback for labelColor,
to display the correct color box for the specific label.
see following working snippet...
var chart_canvas = document.getElementById('myChart');
var stackedLine = new Chart(chart_canvas, {
type: 'bar',
data: {
labels: ['A'],
fill: true,
datasets: [
{
label: 'Low',
data: [67.8],
backgroundColor: '#D6E9C6'
},
{
label: 'Moderate',
data: [20.7],
backgroundColor: '#FAEBCC'
},
{
label: 'High',
data: [11.4],
backgroundColor: '#EBCCD1'
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
tooltips: {
mode: 'label',
callbacks: {
labelColor: function (tooltipItem, data) {
return {backgroundColor: data.data.datasets[data.data.datasets.length - 1 - tooltipItem.datasetIndex].backgroundColor};
},
label: function (tooltipItem, data) {
return data.datasets[data.datasets.length - 1 - tooltipItem.datasetIndex].label + ": " + data.datasets[data.datasets.length - 1 - tooltipItem.datasetIndex].data[tooltipItem.index];
}
}
},
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<canvas id="myChart"></canvas>
Related
Wondering how I can move the text more to the left and create a new line between the labels. As you can see the "label" and "percentage" are on top of each other.
I'm using ChartJS v2.8.0 and ChartJS Plugin Labels 1.1.0
Current Look:
Desired Look:
Current code:
var chart = new Chart(ctx, {
type: 'pie',
data: {
labels: ['T-Shirts', 'Sweaters'],
datasets: [{
backgroundColor: [$('#chart-color-1').val(), $('#chart-color-2').val()],
data: [$('#attire_1_percent').val(), $('#attire_2_percent').val()],
borderWidth: 0
}]
},
options: {
maintainAspectRatio: false,
legend: {
display: false
},
plugins: {
labels: [{
render: "label",
fontColor: '#fff',
},
{
render: 'percentage',
fontColor: '#fff',
}
],
},
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
return data.labels[tooltipItem.index] + ": " + data.datasets[0].data[tooltipItem.index] + "%"
}
},
},
}
});
I am trying to create a stacked bar chart (with chart.js 3.7+) which uses the entire canvas:
new Chart(..., {
type: 'bar',
data: {
labels: ['a','b','c','d','e'],
datasets: [{
backgroundColor: '#ff00ff',
data: [20,40,60,40,20],
},{
backgroundColor: '#00ff00',
data: [100,200,300,200,100],
}]
},
options: {
maintainAspectRatio: false,
responsive: true,
plugins: {
legend: { display: false },
},
scales: {
x: {
display: false,
stacked: true
},
y: {
display: true,
stacked: true
}
}
}
});
When I use a normal bar chart the graph is stretched to use up all the vertical space:
But when I stack the bars the combined longest bar doesn't use up all the vertical space:
How can I get the stacked bar chart to stretch to use all available vertical space?
See example here.
You could sum your arrays, find the max value in the resulting array and set the options.scales.y.max property with this value :
let data1 = [20,40,60,40,20];
let data2 = [100,200,300,200,100];
let sum = data1.map(function (num, idx) {
return num + data2[idx];
});
let max = Math.max(...sum);
var options =
{
maintainAspectRatio: false,
responsive: true,
plugins: {
legend: { display: false },
},
scales: {
x: {
display: false,
stacked: true
},
y: {
display: true,
stacked: true,
max: max
}
}
};
var mychart = new Chart(document.getElementById('mycanvas2').getContext('2d'), {
type: 'bar',
data: {
labels: ['a','b','c','d','e'],
datasets: [{
backgroundColor: '#ff00ff',
data: data1
},{
backgroundColor: '#00ff00',
data: data2
}]
},
options: options
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.min.js"></script>
<div style="width:400px; height: 200px">
<canvas id="mycanvas2"></canvas>
</div>
According to this issue with chart.js you can configure the y-axis bounds to fit the data:
options: {
scales: {
x: {
display: false,
stacked: true
},
y: {
display: true,
stacked: true,
bounds: 'data' <----------
}
}
}
Just a warning: I am new to chart.js!
I have a couple of horizontal bar charts and it works fine except one issue that I cannot shake off. I have 5 labels in y-axis but the legend on top of the graph only shows one small rectangle in the color of the first (topmost) bar and even that does not display the label itself, followed by list of labels. I thought it would display each label next to small bar same color as in chart.
Unfortunately, this is an intranet app and I cannot provide a link but here is what I have (data is passed to this function from an ajax call):
function drawRespChart(chartLabels, chartData) {
var ctx = $("#rtChart");
console.log("Labels Array: " + chartLabels);
console.log("Data Array: " + chartData);
if (chartRespTime)
chartRespTime.destroy();
var chart = {
labels: chartLabels,
datasets: [
{
label: chartLabels,
backgroundColor: ["#c45850", "#e8c3b9", "#3cba9f", "#8e5ea2", "#3e95cd"],
data: chartData
}
]
};
chartRespTime = new Chart(ctx, {
type: 'horizontalBar',
data: chart,
datalabels: {
anchor: 'end',
align: 'start',
},
options: {
title: {
display: true,
text: 'IDC Database Response Time (mili-seconds)'
},
legend: {
display: true,
labels: {
fontColor: 'rgb(255, 99, 132)'
}
},
scales: {
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Count'
},
ticks: {
major: {
fontStyle: 'bold',
fontColor: '#FF0000'
}
}
}],
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Response Time (ms)'
}
}]
},
plugins: {
datalabels: {
color: 'white',
display: function (context) {
return context.dataset.data[context.dataIndex] > 15;
},
font: {
weight: 'bold'
},
formatter: Math.round
}
},
maintainAspectRatio: true,
responsive: true,
showInlineValues: true,
centeredInllineValues: true,
tooltipCaretSize: 0
}
});
}
This is what I see in console window:
Labels Array: 0-350,350-700,700-1000,1000-1500
Data Array: 5065,32,27,3
What I see as legend is one rectangle, same color as first bar, followed by list of labels.
It seems that charts.js labels only works when you split the datasets.
Leaving an example.
https://jsfiddle.net/code4mk/1j62ey38/
datasets: [ {
label: 'Result',
fill:false,
data: aDatasets1,
backgroundColor: '#E91E63',
},
{
label: 'Result2',
fill:false,
data: aDatasets2,
backgroundColor: '#E91E93',
}];
I'm working with a scatter chart in chart.js and I need to modify the info what I show when I'm above a point. I think the box that contains this information is called tooltip.
Below I show what I have now,
What I want to do is modify the first one, and put 14:52 like the x-axis.
In the x-axis was easy,
options: {
scales: {
xAxes: [{
type: 'linear',
position: 'bottom',
ticks: {
callback: function(value, index, values) {
var time = String(value);
if (time.length == 3){
time = '0' + time;
}
var hour = time[0] + time[1];
var min = time[2] + time[3];
var label = hour + ':' + min;
return label;
}
}
}]
}
}
And I suppose here I have to use the same function, but I don't know where. I'm not able to access to the box with the information, isn't its name tooltips? For example, I'm doing the code below but nothing change.
tooltips:{
title: "New title"
}
How can I modify that box?
Thank you very much
The title and other items on the tooltip can be customized using callback functions. The correct syntax looks as follows.
tooltips:{
callbacks: {
title: (tooltipItem, data) => "New title"
}
}
Please also have a look on the following more complex sample derived from https://www.chartjs.org/samples/latest/tooltips/callbacks.html. It should make no difference whether you work with a scatter or a line chart.
new Chart(document.getElementById('myChart'), {
type: 'line',
data: {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'My First dataset',
borderColor: 'red',
backgroundColor: 'red',
data: [15, 22, 18, 28, 8, 13, 24],
fill: false,
}, {
label: 'My Second dataset',
borderColor: 'blue',
backgroundColor: 'blue',
data: [5, 31, 15, 22, 19, 29, 12],
fill: false,
}]
},
options: {
responsive: true,
title: {
display: true,
text: 'Chart.js Line Chart - Custom Information in Tooltip'
},
tooltips: {
mode: 'index',
callbacks: {
title: (tooltipItem, data) => data.labels[tooltipItem[0].index],
footer: (tooltipItems, data) => {
var sum = 0;
tooltipItems.forEach(function(tooltipItem) {
sum += data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
});
return 'Sum: ' + sum;
},
},
footerFontStyle: 'normal'
},
hover: {
mode: 'index',
intersect: true
},
scales: {
xAxes: [{
display: true,
scaleLabel: {
show: true,
labelString: 'Month'
}
}],
yAxes: [{
display: true,
scaleLabel: {
show: true,
labelString: 'Value'
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="myChart" height="100"></canvas>
Iam trying to add an euro sign to the tooltips of my grouped bar chart using ChartJS. Snipped:
tooltips: {
mode: 'label',
callbacks: {
label: function(tooltipItem, data) {
return data['datasets'][0]['data'][tooltipItem['index']] + '€';
}
}
}
This code works for my linechart, but not for my grouped bar chart. I want my bar chart to look like the following, when I hover it:
But there is no euro sign in my chart, it just display its value. What am I doing wrong?
Thank you.
** Edit
So my full options looked like the following:
options: {
title: {
display: true,
text: 'Title',
},
scales: {
yAxes: [{
scaleLabel: {
display: true,
labelString: 'Wert in €'
}
}],
xAxes: [{
scaleLabel: {
display: true,
labelString: 'Zeitintervall'
}
}]
},
tooltips: {
mode: 'label',
callbacks: {
label: function(tooltipItem, data) {
return data['datasets'][0]['data'][tooltipItem['index']] + '€';
}
}
}
}
As soon as i removed the scales, it is showing the euro sign.
So my options now look like the following:
options: {
title: {
display: true,
text: 'Title'
},
tooltips: {
mode: 'label',
callbacks: {
label: function(tooltipItem, data) {
return data['datasets'][0]['data'][tooltipItem['index']] + ' €';
}
}
}
}
But now i got another problem, it shows the same value for two different bars:
You can see clearly that the values are not the same. Whats the problem here?
This can be achieved using the following tooltips label callback function :
tooltips: {
mode: 'label',
callbacks: {
label: function(t, d) {
var dstLabel = d.datasets[t.datasetIndex].label;
var yLabel = t.yLabel;
return dstLabel + ': ' + yLabel + ' €';
}
}
}
FYI: This has nothing to do with scales. It would work perfectly fine along with scales
ᴡᴏʀᴋɪɴɢ ᴇxᴀᴍᴘʟᴇ ⧩
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
datasets: [{
label: 'DST1',
backgroundColor: '#3e95cd',
data: [3, 2, 4, 5, 1]
}, {
label: 'DST2',
backgroundColor: '#8e5ea2',
data: [2, 4, 1, 2, 5]
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
stepSize: 1
}
}]
},
title: {
display: true,
text: 'Title'
},
tooltips: {
mode: 'label',
callbacks: {
label: function(t, d) {
var dstLabel = d.datasets[t.datasetIndex].label;
var yLabel = t.yLabel;
return dstLabel + ': ' + yLabel + ' €';
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.js"></script>
<canvas id="ctx"></canvas>
A bit late to the party, but I have recently discovered JavaScript's built-in formatter for currencies, that saves you having to play about with strings and could be helpful here, and is reusable elsewhere in your code!:
const gbp = new Intl.NumberFormat('en-GB', {
style: 'currency',
currency: 'GBP',
minimumFractionDigits: 2
});
Being English I have of course done it in GBP, but I found that changing the en-GB to de-DE and the 'GBP' to 'EUR' worked absolutely fine. Even formatting the decimal points and thousand separators correctly.
EDIT: including how to actually give the formatter a number to format would be useful wouldn't it!
gbp.format(10000); // Returns £10,000.00