Link to jsFiddle
google.charts.load('current', {
'packages': ['corechart']
});
//Input data
var data = [
['Data', 'CAT1', 'CAT2', 'CAT3', 'CAT4'],
['Provisions', 5, 0, 0, 0],
];
// Set a callback to run when the Google Visualization API is loaded.
google.charts.setOnLoadCallback(drawChart);
// Callback that creates and populates a data table,
// instantiates the pie chart, passes in the data and
// draws it.
function drawChart() {
var options = {
colors: ['#00699B', '#087EB4', '#CBE7F7', '8A6996'],
isStacked: true,
chartArea: {
width: '40%'
},
bar: {
groupWidth: "40%"
},
// tooltip: { isHtml: true },
trigger: 'both',
vAxis: {
gridlines: {
color: '#0000006b',
minValue: 0,
baseline: 0
},
format: "$ #,###"
},
};
var dataTable = google.visualization.arrayToDataTable(data);
//Formatters
var intergerFormatter = new google.visualization.NumberFormat({
groupingSymbol: ",",
fractionDigits: 0
});
for (var i = 0; i < data[0].length; i++) {
intergerFormatter.format(dataTable, i);
}
var view = new google.visualization.DataView(dataTable);
var cols = [0];
for (var i = 1; i < data[0].length; i++) {
cols.push({
sourceColumn: i,
type: "number",
label: data[0][i]
});
cols.push({
calc: createTooltip(i),
type: "string",
role: "tooltip",
});
}
view.setColumns(cols);
var chart = new google.visualization.ColumnChart(document.getElementById('provision_chart'));
chart.draw(view, options);
function createTooltip(col) {
return function(dataTable, row) {
var html = dataTable.getColumnLabel(col) + ":" + "\n";
html += "4 " + dataTable.getValue(row, 0) + "\n";
html += "$ " + intergerFormatter.formatValue(dataTable.getValue(row, col)) + " total" + "\n";
return html;
};
}
}
The grid lines on a stacked bar type google charts are not rendering properly.
As per the data, $5 is recorded against Category1, but when it's rendered the bar is slightly over $5.
Can someone suggest a fix?
removing the option --> format: "$ #,###" -- reveals the problem
although the tick mark displays --> $ 5 -- the actual number used is 4.5
see following working snippet...
google.charts.load('current', {
'packages': ['corechart']
});
//Input data
var data = [
['Data', 'CAT1', 'CAT2', 'CAT3', 'CAT4'],
['Provisions', 5, 0, 0, 0],
];
// Set a callback to run when the Google Visualization API is loaded.
google.charts.setOnLoadCallback(drawChart);
// Callback that creates and populates a data table,
// instantiates the pie chart, passes in the data and
// draws it.
function drawChart() {
var options = {
colors: ['#00699B', '#087EB4', '#CBE7F7', '8A6996'],
isStacked: true,
chartArea: {
width: '40%'
},
bar: {
groupWidth: "40%"
},
// tooltip: { isHtml: true },
trigger: 'both',
vAxis: {
gridlines: {
color: '#0000006b',
minValue: 0,
baseline: 0
},
//format: "$ #,###"
},
};
var dataTable = google.visualization.arrayToDataTable(data);
//Formatters
var intergerFormatter = new google.visualization.NumberFormat({
groupingSymbol: ",",
fractionDigits: 0
});
for (var i = 0; i < data[0].length; i++) {
intergerFormatter.format(dataTable, i);
}
var view = new google.visualization.DataView(dataTable);
var cols = [0];
for (var i = 1; i < data[0].length; i++) {
cols.push({
sourceColumn: i,
type: "number",
label: data[0][i]
});
cols.push({
calc: createTooltip(i),
type: "string",
role: "tooltip",
});
}
view.setColumns(cols);
var chart = new google.visualization.ColumnChart(document.getElementById('provision_chart'));
chart.draw(view, options);
function createTooltip(col) {
return function(dataTable, row) {
var html = dataTable.getColumnLabel(col) + ":" + "\n";
html += "4 " + dataTable.getValue(row, 0) + "\n";
html += "$ " + intergerFormatter.formatValue(dataTable.getValue(row, col)) + " total" + "\n";
return html;
};
}
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="provision_chart" style="width: 500px; height: 500px;"></div>
to correct, you can add a decimal place to the format --> $ #,##0.0
or provide your own vAxis.ticks in an array --> [0, 1, 2, 3, 4, 5, 6]
see following working snippet...
google.charts.load('current', {
'packages': ['corechart']
});
//Input data
var data = [
['Data', 'CAT1', 'CAT2', 'CAT3', 'CAT4'],
['Provisions', 5, 0, 0, 0],
];
// Set a callback to run when the Google Visualization API is loaded.
google.charts.setOnLoadCallback(drawChart);
// Callback that creates and populates a data table,
// instantiates the pie chart, passes in the data and
// draws it.
function drawChart() {
var options = {
colors: ['#00699B', '#087EB4', '#CBE7F7', '8A6996'],
isStacked: true,
chartArea: {
width: '40%'
},
bar: {
groupWidth: "40%"
},
// tooltip: { isHtml: true },
trigger: 'both',
vAxis: {
gridlines: {
color: '#0000006b',
minValue: 0,
baseline: 0
},
format: "$ #,###",
ticks: [0, 1, 2, 3, 4, 5, 6]
},
};
var dataTable = google.visualization.arrayToDataTable(data);
//Formatters
var intergerFormatter = new google.visualization.NumberFormat({
groupingSymbol: ",",
fractionDigits: 0
});
for (var i = 0; i < data[0].length; i++) {
intergerFormatter.format(dataTable, i);
}
var view = new google.visualization.DataView(dataTable);
var cols = [0];
for (var i = 1; i < data[0].length; i++) {
cols.push({
sourceColumn: i,
type: "number",
label: data[0][i]
});
cols.push({
calc: createTooltip(i),
type: "string",
role: "tooltip",
});
}
view.setColumns(cols);
var chart = new google.visualization.ColumnChart(document.getElementById('provision_chart'));
chart.draw(view, options);
function createTooltip(col) {
return function(dataTable, row) {
var html = dataTable.getColumnLabel(col) + ":" + "\n";
html += "4 " + dataTable.getValue(row, 0) + "\n";
html += "$ " + intergerFormatter.formatValue(dataTable.getValue(row, col)) + " total" + "\n";
return html;
};
}
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="provision_chart" style="width: 500px; height: 500px;"></div>
the getColumnRange(colIndex) method can assist in building the ticks dynamically
the method returns an object {} with properties for min and max for the column index provided
see following working snippet for an example...
google.charts.load('current', {
'packages': ['corechart']
});
//Input data
var data = [
['Data', 'CAT1', 'CAT2', 'CAT3', 'CAT4'],
['Provisions', 5, 0, 0, 0],
];
// Set a callback to run when the Google Visualization API is loaded.
google.charts.setOnLoadCallback(drawChart);
// Callback that creates and populates a data table,
// instantiates the pie chart, passes in the data and
// draws it.
function drawChart() {
var options = {
colors: ['#00699B', '#087EB4', '#CBE7F7', '8A6996'],
isStacked: true,
chartArea: {
width: '40%'
},
bar: {
groupWidth: "40%"
},
// tooltip: { isHtml: true },
trigger: 'both',
vAxis: {
gridlines: {
color: '#0000006b',
minValue: 0,
baseline: 0
},
format: "$ #,###"
},
};
var dataTable = google.visualization.arrayToDataTable(data);
//Formatters
var intergerFormatter = new google.visualization.NumberFormat({
groupingSymbol: ",",
fractionDigits: 0
});
for (var i = 0; i < data[0].length; i++) {
intergerFormatter.format(dataTable, i);
}
var view = new google.visualization.DataView(dataTable);
var cols = [0];
var ticksY = [];
var maxY = null;
var minY = null;
for (var i = 1; i < view.getNumberOfColumns(); i++) {
var range = view.getColumnRange(i);
if (maxY === null) {
maxY = Math.ceil(range.max);
} else {
maxY = Math.max(maxY, Math.ceil(range.max));
}
if (minY === null) {
minY = Math.floor(range.min);
} else {
minY = Math.min(minY, Math.floor(range.min));
}
}
for (var i = minY; i <= maxY + 1; i++) {
ticksY.push(i);
}
options.vAxis.ticks = ticksY;
for (var i = 1; i < data[0].length; i++) {
cols.push({
sourceColumn: i,
type: "number",
label: data[0][i]
});
cols.push({
calc: createTooltip(i),
type: "string",
role: "tooltip",
});
}
view.setColumns(cols);
var chart = new google.visualization.ColumnChart(document.getElementById('provision_chart'));
chart.draw(view, options);
function createTooltip(col) {
return function(dataTable, row) {
var html = dataTable.getColumnLabel(col) + ":" + "\n";
html += "4 " + dataTable.getValue(row, 0) + "\n";
html += "$ " + intergerFormatter.formatValue(dataTable.getValue(row, col)) + " total" + "\n";
return html;
};
}
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="provision_chart" style="width: 500px; height: 500px;"></div>
Related
I have searched a lot and included a thousand separator in tooltips. But I would like to make it work everywhere there is text. Where I live we use "." to separate thousands and "," for decimal.
I didn't find a simple way to put the title in the middle of the doughnut.
This is what I have:
Chart.defaults.global.defaultFontColor = '#7792b1';
var ctx = document.getElementById('myChart').getContext('2d');
var dataset = [{
label: 'Volume de Operações',
data: [254000.87, 355000.57],
backgroundColor: ['#4bb8df', '#6290df']
}]
var chart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: ['CALL', 'PUT'],
datasets: dataset
},
options: {
rotation: 1 * Math.PI,
circumference: 1 * Math.PI,
legend: {
display: false
},
cutoutPercentage: 60,
plugins: {
labels: [{
render: 'label',
arc: true,
fontStyle: 'bold',
position: 'outside'
}, {
render: 'percentage',
fontColor: '#ffffff',
precision: 1
}],
},
title: {
display: true,
fontSize: 15,
text: [
dataset.reduce((t, d) => t + d.data.reduce((a, b) => a + b), 0),
'Volume Total'
],
position: 'bottom'
},
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
var dataLabel = data.labels[tooltipItem.index];
var value = ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index].toLocaleString();
if (Chart.helpers.isArray(dataLabel)) {
dataLabel = dataLabel.slice();
dataLabel[0] += value;
} else {
dataLabel += value;
}
return dataLabel;
}
}
}
}
});
<canvas id="myChart" style="max-width: 450px"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0"></script>
<script src="https://cdn.jsdelivr.net/gh/emn178/chartjs-plugin-labels/src/chartjs-plugin-labels.js"></script>
In short:
Global thousand separator: (.)
Title in the middle of doughnut
Tooltip without label: Only value
To not show a title in your tooltip you will have to only return the value in your custom label calback. So your callback will become this:
label: function(tooltipItem, data) {
return data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index].toLocaleString();
}
There is no build in way to get the title in the middle of the circle, you will have to write a custom plugin for that.
To replace the thousand serperator in the percentage label, you will have to write a custom render. So instead render: 'percentage'. You will get something like this:
// custom render
{
render: function (args) {
// args will be something like:
// { label: 'Label', value: 123, percentage: 50, index: 0, dataset: {...} }
return '$' + args.value;
}
}
You will have to make the logic so the value gets transformed to a percentage still
EDIT custom tooltip so you dont see the color in front.
Chart.defaults.global.defaultFontColor = '#7792b1';
var ctx = document.getElementById('myChart').getContext('2d');
var dataset = [{
label: 'Volume de Operações',
data: [254000.87, 355000.57],
backgroundColor: ['#4bb8df', '#6290df']
}]
var chart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: ['CALL', 'PUT'],
datasets: dataset
},
options: {
rotation: 1 * Math.PI,
circumference: 1 * Math.PI,
legend: {
display: false
},
cutoutPercentage: 60,
plugins: {
labels: [{
render: 'label',
arc: true,
fontStyle: 'bold',
position: 'outside'
}, {
render: 'percentage',
fontColor: '#ffffff',
precision: 1
}],
},
title: {
display: true,
fontSize: 15,
text: [
dataset.reduce((t, d) => t + d.data.reduce((a, b) => a + b), 0),
'Volume Total'
],
position: 'bottom'
},
tooltips: {
enabled: false,
custom: function(tooltipModel) {
// Tooltip Element
var tooltipEl = document.getElementById('chartjs-tooltip');
// Create element on first render
if (!tooltipEl) {
tooltipEl = document.createElement('div');
tooltipEl.id = 'chartjs-tooltip';
tooltipEl.innerHTML = '<table></table>';
document.body.appendChild(tooltipEl);
}
// Hide if no tooltip
if (tooltipModel.opacity === 0) {
tooltipEl.style.opacity = 0;
return;
}
// Set caret Position
tooltipEl.classList.remove('above', 'below', 'no-transform');
if (tooltipModel.yAlign) {
tooltipEl.classList.add(tooltipModel.yAlign);
} else {
tooltipEl.classList.add('no-transform');
}
function getBody(bodyItem) {
return bodyItem.lines[0].split(': ')[1].replace('.', ',');
}
// Set Text
if (tooltipModel.body) {
var titleLines = tooltipModel.title || [];
var bodyLines = tooltipModel.body.map(getBody);
var innerHtml = '<thead>';
innerHtml += '</thead><tbody>';
bodyLines.forEach(function(body, i) {
var colors = tooltipModel.labelColors[i];
var style = 'background:' + colors.backgroundColor;
style += '; border-color:' + colors.borderColor;
style += '; border-width: 2px';
var span = '<span style="' + style + '"></span>';
innerHtml += '<tr><td>' + span + body + '</td></tr>';
});
innerHtml += '</tbody>';
var tableRoot = tooltipEl.querySelector('table');
tableRoot.innerHTML = innerHtml;
}
// `this` will be the overall tooltip
var position = this._chart.canvas.getBoundingClientRect();
// Display, position, and set styles for font
tooltipEl.style.opacity = 1;
tooltipEl.style.position = 'absolute';
tooltipEl.style.left = position.left + window.pageXOffset + tooltipModel.caretX + 'px';
tooltipEl.style.top = position.top + window.pageYOffset + tooltipModel.caretY + 'px';
tooltipEl.style.fontFamily = tooltipModel._bodyFontFamily;
tooltipEl.style.fontSize = tooltipModel.bodyFontSize + 'px';
tooltipEl.style.fontStyle = tooltipModel._bodyFontStyle;
tooltipEl.style.padding = tooltipModel.yPadding + 'px ' + tooltipModel.xPadding + 'px';
tooltipEl.style.pointerEvents = 'none';
}
/*
callbacks: {
label: function(tooltipItem, data) {
return data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index].toLocaleString();
},
}*/
}
}
});
#chartjs-tooltip {
opacity: 1;
position: absolute;
background: rgba(0, 0, 0, .7);
color: white;
border-radius: 3px;
-webkit-transition: all .1s ease;
transition: all .1s ease;
pointer-events: none;
-webkit-transform: translate(-50%, 0);
transform: translate(-50%, 0);
}
<canvas id="myChart" style="max-width: 450px"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0"></script>
<script src="https://cdn.jsdelivr.net/gh/emn178/chartjs-plugin-labels/src/chartjs-plugin-labels.js"></script>
You might want to add some dots as thousand seperators in the tooltip but thats up to you. Best place to do it is in the getBody method.
I am currently working on Google Charts with below Version.
google.charts.load('upcoming', {packages: ['corechart']);
When i enter a mouse on axis and legend tooltip comes with black box as per attached image.
I also tried "Current" and "42" version but still getting a same issue as in attached image. I am facing this issue with Firefox.
Google Line Chart- Tooltip with balck box in Firefox
Is it a bug in Google Chart API or anything else?
tooltip seems to work fine here
any code / css / chart options you can share?
see following working snippet...
google.charts.load('current', {
callback: drawChart,
packages: ['corechart']
});
function drawChart() {
var dataTable = new google.visualization.DataTable({
cols: [
{id: 'x', label: 'Date', type: 'date'},
{id: 'y', label: 'Fn', type: 'number'},
{id: 'z', label: 'Shade', type: 'number'}
]
});
var formatDate = new google.visualization.DateFormat({
pattern: 'MMM-dd-yyyy'
});
var oneDay = (1000 * 60 * 60 * 24);
var startDate = new Date(2016, 10, 27);
var endDate = new Date();
var ticksAxisH = [];
var dateRanges = [
{start: new Date(2017, 0, 1), end: new Date(2017, 0, 20)},
{start: new Date(2017, 1, 5), end: new Date(2017, 1, 10)}
];
var maxShade = 200;
for (var i = startDate.getTime(); i < endDate.getTime(); i = i + oneDay) {
// x = date
var rowDate = new Date(i);
var xValue = {
v: rowDate,
f: formatDate.formatValue(rowDate)
};
// y = 2x + 8
var yValue = (2 * ((i - startDate.getTime()) / oneDay) + 8);
// z = null or max shade
var zValue = null;
dateRanges.forEach(function (range) {
if ((rowDate.getTime() >= range.start.getTime()) &&
(rowDate.getTime() <= range.end.getTime())) {
zValue = maxShade;
}
});
// add data row
dataTable.addRow([
xValue,
yValue,
zValue
]);
// add tick every 7 days
if (((i - startDate.getTime()) % 7) === 0) {
ticksAxisH.push(xValue);
}
}
var container = document.getElementById('chart_div');
var chart = new google.visualization.ChartWrapper({
chartType: 'ComboChart',
dataTable: dataTable,
options: {
chartArea: {
bottom: 64,
top: 48
},
hAxis: {
slantedText: true,
ticks: ticksAxisH
},
legend: {
position: 'top'
},
lineWidth: 4,
series: {
// line
0: {
color: '#00acc1'
},
// area
1: {
areaOpacity: 0.6,
color: '#ffe0b2',
type: 'area',
visibleInLegend: false
},
},
seriesType: 'line'
}
});
chart.draw(container);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
I'm trying to get the sum of all values of a stackedBar and include this total in tooltip.
Note: my datasets aren't static, this is an example
var barChartData = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: 'Corporation 1',
backgroundColor: "rgba(220,220,220,0.5)",
data: [50, 40, 23, 45, 67, 78, 23]
}, {
label: 'Corporation 2',
backgroundColor: "rgba(151,187,205,0.5)",
data: [50, 40, 78, 23, 23, 45, 67]
}, {
label: 'Corporation 3',
backgroundColor: "rgba(151,187,205,0.5)",
data: [50, 67, 78, 23, 40, 23, 55]
}]
};
window.onload = function() {
var ctx = document.getElementById("canvas").getContext("2d");
window.myBar = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
title:{
display:true,
text:"Chart.js Bar Chart - Stacked"
},
tooltips: {
mode: 'label',
callbacks: {
label: function(tooltipItem, data) {
var corporation = data.datasets[tooltipItem.datasetIndex].label;
var valor = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
var total = eval(data.datasets[tooltipItem.datasetIndex].data.join("+"));
return total+"--"+ corporation +": $" + valor.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');
}
}
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
}
}
});
};
Now total is the sum per dataset and I need the sum per stackedBar.
Example
Label A: value A
Label B: value B
Label C: value C
TOTAL: value A + value B + value C
It is possible to get that total value?
Thanks, Idalia.
First you should know that if you return an array instead of a single string in the callback of the tooltip, it will display all the strings in your array as if it were different datasets (see this answer for more details).
So I edited a little bit your callback to the following:
callbacks: {
label: function(tooltipItem, data) {
var corporation = data.datasets[tooltipItem.datasetIndex].label;
var valor = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
// Loop through all datasets to get the actual total of the index
var total = 0;
for (var i = 0; i < data.datasets.length; i++)
total += data.datasets[i].data[tooltipItem.index];
// If it is not the last dataset, you display it as you usually do
if (tooltipItem.datasetIndex != data.datasets.length - 1) {
return corporation + " : $" + valor.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');
} else { // .. else, you display the dataset and the total, using an array
return [corporation + " : $" + valor.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,'), "Total : $" + total];
}
}
}
You can see the full code in this jsFiddle, and here is its result :
i modified tektiv answer to show Total only for active sets and move it to tooltips footer.
tooltips: {
mode: 'label',
callbacks: {
afterTitle: function() {
window.total = 0;
},
label: function(tooltipItem, data) {
var corporation = data.datasets[tooltipItem.datasetIndex].label;
var valor = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
window.total += valor;
return corporation + ": " + valor.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " ");
},
footer: function() {
return "TOTAL: " + window.total.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " ");
}
}
}
Shorter version of Gaspar's answer:
tooltips: {
callbacks: {
footer: (tooltipItems, data) => {
let total = tooltipItems.reduce((a, e) => a + parseInt(e.yLabel), 0);
return 'Total: ' + total;
}
}
}
Example: https://jsfiddle.net/g3ba60zc/2/
In the other answers you replace the last dataset, with this you don't need to
tooltips: {
callbacks: {
title: function(tooltipItems, data) {
return _this.chart.data.labels[tooltipItems[0].index];
},
footer: function(tooltipItems, data) {
let total = 0;
for (let i = 0; i < tooltipItems.length; i++) {
total += parseInt(tooltipItems[i].yLabel, 10);
}
return 'Total: ' + total;
}
}
}
Ps: It's typescript lang.
#Haider this is what you were looking for, I had the same problem.
I have reused your code and built upon it #tektiv
I have made one small change where instead of building into the label I have made use of the afterbody. This removes the key color
afterBody code:
afterBody: function (tooltipItem, data) {
var corporation = data.datasets[tooltipItem[0].datasetIndex].label;
var valor = data.datasets[tooltipItem[0].datasetIndex].data[tooltipItem[0].index];
var total = 0;
for (var i = 0; i < data.datasets.length; i++)
total += data.datasets[i].data[tooltipItem[0].index];
return "Total : $" + total;
}
Full code here at JSFiddle
Picture demonstration of the finished tooltip
Using Chart.js 2.5.0
var valor = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
returns a string value. To calculate the correct sum value you have to add a parseFloat statement:
tooltips: {
mode: 'label',
callbacks: {
afterTitle: function() {
window.total = 0;
},
label: function(tooltipItem, data) {
var corporation = data.datasets[tooltipItem.datasetIndex].label;
var valor = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
//THIS ONE:
valor=parseFloat(valor);
window.total += valor;
return corporation + ": " + valor.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " ");
},
footer: function() {
return "TOTAL: " + window.total.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " ");
}
}
}
If you are on older ChartJs version you have to handle this in a different way. I'm using Chart.js Version 2.7.2 and this is how I handled it:
tooltips: {
mode: 'label',
callbacks: {
footer: function (data) {
var total = 0;
for (var i = 0; i < data.length; i++) {
total += data[i].yLabel;
}
return 'Total: ' + total
}
}
}
Chart.js made their own, very satisfying solution:
options: {
interaction: {
intersect: false,
mode: 'index',
},
plugins: {
tooltip: {
callbacks: {
footer: footer,
}
}
}
}
and somewhere else in your code:
const footer = (tooltipItems) => {
let sum = 0;
tooltipItems.forEach(function(tooltipItem) {
sum += tooltipItem.parsed.y;
});
return 'Sum: ' + sum;
};
Worked just fine for me!
I made half a donut chart with Google charts and I have a problem that the sum of visible percentage is equal to 50%. Is there any possible solution ?
Image of my chart
you can override the text displayed on the slice by using the following config option...
pieSliceText: 'value'
then in the data, set the formatted value of the cells to the correct percentage...
var data = [
['Task', 'Hours'],
// use formatted values
['A', {v: 19.2, f: '38.4%'}],
['B', {v: 30.8, f: '61.6%'}],
[null, 50]
];
the following working snippet uses the same approach,
but calculates the correct percentages,
rather than hard-coding...
google.charts.load('current', {
callback: function () {
var data = [
['Task', 'Hours'],
['A', 19.2],
['B', 30.8],
[null, 50.0]
];
var total = 0;
for (var i = 1; i < data.length; i++) {
if (data[i][0] !== null) {
total += data[i][1];
}
}
var numberFormat = new google.visualization.NumberFormat({
pattern: '#,##0.0',
suffix: '%'
});
var dataTable = google.visualization.arrayToDataTable(data);
for (var i = 0; i < dataTable.getNumberOfRows(); i++) {
if (dataTable.getValue(i, 0) !== null) {
dataTable.setFormattedValue(i, 1, numberFormat.formatValue(((dataTable.getValue(i, 1) / total) * 100)));
}
}
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
var options = {
height: 400,
chartArea: {
top: 24
},
colors: ['#8BC34A', '#64B5F6'],
legend: 'none',
pieHole: 0.4,
pieStartAngle: 270,
pieSliceText: 'value',
slices: {
2: {
color: 'transparent'
}
},
theme: 'maximized',
width: 400
};
chart.draw(dataTable, options);
},
packages: ['corechart']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
I'd like to be able to show/hide the lines on my line graph when clicking the relevant key in the legend, is this possible?
To hide show lines on your GWT Visualization LineChart, follow these steps:-
1.Create a DataView object based on an existing DataTable object:
DataTable dataTable = DataTable.create();
DataView dataView = DataView.create(dataTable);
2.Hide the column of the curve/line that you want to hide in the DataView:
dataView.hideColumns(new int[]{<id_of_the_column>});
3.Draw the entire chart again based on the DataView:
chart.draw(dataView, getOptions());
Please note that there is a caveat here, step 3 is a costly step, for us it is taking almost 20-30 sec. for the the new graph to be drawn. But if the data is not large it should be manageable in your context.
Note: You will have to make your own legend with a checkbox and do the above stuff when user checks/unchecks a checkbox.
If you don't need to include scaling and animation then one option is just hide data using lineWidth and areaOpacity values;
<head>
<script type='text/javascript' src='https://www.google.com/jsapi'></script>
<script>
function updateTable() {
// quick data - cleaned up for this example real data sources
data = new Array();
data[0] = new Array();
data[0][0] = "Day";
data[0][1] = "Metric 1";
data[0][2] = "Metric 2";
data[0][3] = "Metric 3";
data[1] = new Array();
data[1][0] = 1;
data[1][1] = 200;
data[1][2] = 50;
data[1][3] = 400;
data[2] = new Array();
data[2][0] = 2;
data[2][1] = 440;
data[2][2] = 140;
data[2][3] = 40;
data[3] = new Array();
data[3][0] = 3;
data[3][1] = 300;
data[3][2] = 500;
data[3][3] = 600;
var gdata = google.visualization.arrayToDataTable(data);
var options = {
// title: 'kala',
hAxis: {title: 'Days', titleTextStyle: {color: '#333'}}
,vAxis: {minValue: 0}
,height: 300
,width: 600
,chartArea: {left: 60}
,lineWidth: 2
,series: {0:{color: 'black', areaOpacity: 0.3, lineWidth: 2}
,1:{color: 'red', areaOpacity: 0.3, lineWidth: 2}
,2:{color: 'purple', areaOpacity: 0.3, lineWidth: 2}}
};
var chart = new google.visualization.AreaChart(document.getElementById('my_chart'));
chart.draw(gdata, options);
google.visualization.events.addListener(chart,
'select',
(function (x) { return function () { AreaSelectHander(chart, gdata, options)}})(1));
}
function AreaSelectHander(chart, gdata, options) {
// when ever clicked we enter here
// more code needed to inspect what actually was clicked, now assuming people
// play nicely and click only lables...
var selection = chart.getSelection();
var view = new google.visualization.DataView(gdata);
console.log(options);
// click and data index are one off
i = selection[0].column - 1;
// just simple reverse
if (options.series[i].lineWidth == 0) {
options.series[i].lineWidth = 2;
options.series[i].areaOpacity = 0.3;
}
else {
options.series[i].lineWidth = 0;
options.series[i].areaOpacity = 0.0;
}
chart.draw(gdata, options);
}
</script>
<script type='text/javascript'>
google.load('visualization', '1', {packages:['table', 'corechart']});
google.setOnLoadCallback(updateTable);
</script>
</head>
<body>
<div id='my_chart'></div>
</body>
Following code display goggle line chart and have functionality to hide/show graph line by clicking on legend label. #graph_sales_data is id of div which display chart and sales_data_graph is variable containg record.
function drawChart() {
if (sales_data_graph.length > 1)
{
$('#graph_sales_data').show();
var data = new google.visualization.arrayToDataTable(sales_data_graph);
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.ChartWrapper({
chartType: 'LineChart',
containerId: 'graph_sales_data',
dataTable: data,
colors: ['#ea6f09', '#fb250d', '#0ac9c6', '#2680be', '#575bee', '#6bd962', '#ff0000', '#000000'],
options: {
width: 1200,
height: 500,
fontSize: 10,
pointSize: 10
}
});
// create columns array
var columns = [0];
/* the series map is an array of data series
* "column" is the index of the data column to use for the series
* "roleColumns" is an array of column indices corresponding to columns with roles that are associated with this data series
* "display" is a boolean, set to true to make the series visible on the initial draw
*/
var seriesMap = [{
column: 1,
roleColumns: [1],
display: true
}, {
column: 2,
roleColumns: [2],
display: true
}, {
column: 3,
roleColumns: [3],
display: true
}, {
column: 4,
roleColumns: [4],
display: true
}, {
column: 5,
roleColumns: [5],
display: true
}, {
column: 6,
roleColumns: [6],
display: true
}, {
column: 7,
roleColumns: [7],
display: true
}, {
column: 8,
roleColumns: [8],
display: true
}];
var columnsMap = {};
var series = [];
for (var i = 0; i < seriesMap.length; i++) {
var col = seriesMap[i].column;
columnsMap[col] = i;
// set the default series option
series[i] = {};
if (seriesMap[i].display) {
// if the column is the domain column or in the default list, display the series
columns.push(col);
}
else {
// otherwise, hide it
columns.push({
label: data.getColumnLabel(col),
type: data.getColumnType(col),
sourceColumn: col,
calc: function() {
return null;
}
});
// backup the default color (if set)
if (typeof(series[i].color) !== 'undefined') {
series[i].backupColor = series[i].color;
}
series[i].color = '#CCCCCC';
}
for (var j = 0; j < seriesMap[i].roleColumns.length; j++) {
//columns.push(seriesMap[i].roleColumns[j]);
}
}
chart.setOption('series', series);
function showHideSeries() {
var sel = chart.getChart().getSelection();
// if selection length is 0, we deselected an element
if (sel.length > 0) {
// if row is undefined, we clicked on the legend
if (sel[0].row == null) {
var col = sel[0].column;
if (typeof(columns[col]) == 'number') {
var src = columns[col];
// hide the data series
columns[col] = {
label: data.getColumnLabel(src),
type: data.getColumnType(src),
sourceColumn: src,
calc: function() {
return null;
}
};
// grey out the legend entry
series[columnsMap[src]].color = '#CCCCCC';
}
else {
var src = columns[col].sourceColumn;
// show the data series
columns[col] = src;
series[columnsMap[src]].color = null;
}
var view = chart.getView() || {};
view.columns = columns;
chart.setView(view);
chart.draw();
}
}
}
google.visualization.events.addListener(chart, 'select', showHideSeries);
// create a view with the default columns
var view = {
columns: columns
};
chart.draw();
}
else
{
$('#graph_sales_data').hide();
}
}