Chart.js how to display multiple labels on multi bar stacked chart - charts

How can i display different labels under each column and also have another label for the entire group?
As you can see in the picture below i want to use fontawesome icons for each column but another label for the main group. I found other answers how to use fa icons but don't know how to position them under each bar.
The trendlines which connect distinct columns are not so important but would be great if i can find out how to add them also.
Also the chart needs to be scrollable as it can hold lots of data and the labels need to be shown. I found some examples with scroll as well.
Any info is highly appreciated. Or are there any other open source chart frameworks in which i could implement this or something similar to fit my needs?

using google charts...
on the chart's 'ready' event,
you can use chart method --> getChartLayoutInterface()
var chartLayout = chart.getChartLayoutInterface();
the interface has a method --> getBoundingBox()
which will return the position of requested chart element
to get the position of a bar...
var barBounds = chartLayout.getBoundingBox('bar#0#0');
where the first #0 is the series, and the second is the row,
'bar#0#0' would get the first bar on the first row
we can also get the position of the axis label...
var labelBounds = chartLayout.getBoundingBox('hAxis#0#label#0');
we can use a combination of the bar and label bounds to position the icon
we want the left position from the bar, and the top position from the label
see following working snippet,
a column property is used to store the icon name,
the x-axis labels are used for the group
once the icon is in position, the axis label is moved down to make room
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = new google.visualization.DataTable({
cols: [
{label: 'x', type: 'string'},
{label: 'file', type: 'number', p: {icon: 'fa-file'}},
{label: 'database', type: 'number', p: {icon: 'fa-database'}},
{label: 'random', type: 'number', p: {icon: 'fa-random'}},
],
rows: [
{c:[{v: 'Label 1'}, {v: 11}, {v: 6}, {v: 15}]},
{c:[{v: 'Label 2'}, {v: 8}, {v: null}, {v: 12}]},
{c:[{v: 'Label 3'}, {v: 6}, {v: 8}, {v: 18}]},
{c:[{v: 'Label 4'}, {v: null}, {v: 1}, {v: 16}]},
]
});
var options = {
bar: {
groupWidth: '50%',
width: 20
},
colors: ['#ffc107', '#d32f2f', '#00bcd4'],
height: 600,
legend: 'none',
title: 'Capacities',
width: 1000,
};
var container = document.getElementById('chart_div');
var chart = new google.visualization.ColumnChart(container);
google.visualization.events.addListener(chart, 'ready', function () {
// initialize bounds variables
var axisLabels = container.getElementsByTagName('text');
var chartLayout = chart.getChartLayoutInterface();
var chartBounds = chartLayout.getChartAreaBoundingBox();
var containerBounds = container.getBoundingClientRect();
var labelIndex;
// add icons
for (var r = 0; r < data.getNumberOfRows(); r++) {
var barBounds;
var icon;
var iconBounds;
var labelBounds = chartLayout.getBoundingBox('hAxis#0#label#' + r);
for (var c = 1; c < data.getNumberOfColumns(); c++) {
barBounds = chartLayout.getBoundingBox('bar#' + (c - 1) + '#' + r);
if (barBounds !== null) {
icon = container.appendChild(document.createElement('i'));
icon.className = 'fa ' + data.getColumnProperty(c, 'icon');
icon.style.position = 'absolute';
iconBounds = icon.getBoundingClientRect();
icon.style.top = (containerBounds.top + labelBounds.top) + 'px';
icon.style.left = (barBounds.left + containerBounds.left + (barBounds.width / 2) - (iconBounds.width / 2)) + 'px';
}
}
// move axis label down
labelIndex = -1;
Array.prototype.forEach.call(axisLabels, function(label) {
if (label.getAttribute('text-anchor') === 'middle') {
labelIndex++;
if (labelIndex === r) {
label.setAttribute('y', (parseFloat(label.getAttribute('y')) + (iconBounds.height * 2)));
}
}
});
}
});
chart.draw(data, options);
});
i {
color: #00bcd4;
}
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

Related

Google Chart mouse over skipping data point [duplicate]

I want to add a custom tooltip to my charts by using the default one and for example just append some text to it.
Is this even possible, or to i have to create it all by myself with html?
data= google.visualization.arrayToDataTable([
["Element", "Duration ", { role: "style" }, { role: 'tooltip' }],
["Count", 23515, "orange", ???],
]);
How it is (Default Tooltip):
How i want it:
Append the duration as readable time, but still keep the default tooltip
it's not possible to add content to the default tooltip via standard functionality
to do so requires manipulating the tooltip directly when it is shown
the following working snippet listens for the 'onmouseover' event on the chart
then modifies the tooltip (if found)
using the row # passed as a property of the event argument
keep in mind, the style (font-size) will change according to the size of the chart
the snippet copies the style from the existing lines
google.charts.load('current', {
callback: function () {
var dataTable = new google.visualization.DataTable({
cols: [
{label: 'Element', type: 'string'},
{label: 'Duration', type: 'number'},
{role: 'style', type: 'string'}
],
rows: [
{c:[{v: 'Amazon Elastic Transcoder'}, {v: 3116, f: '3,116 s'}, {v: 'orange'}]},
{c:[{v: 'Amazon Elastic Transcoder'}, {v: 8523, f: '8,523 s'}, {v: 'cyan'}]}
]
});
var options = {
backgroundColor: 'transparent',
legend: 'none',
theme: 'maximized',
hAxis: {
textPosition: 'none'
},
tooltip: {
isHtml: true
}
};
var container = document.getElementById('chart_div');
var chart = new google.visualization.ColumnChart(container);
google.visualization.events.addListener(chart, 'onmouseover', function (props) {
var duration = dataTable.getValue(props.row, 1);
var hours = parseInt( duration / 3600 ) % 24;
var minutes = parseInt( duration / 60 ) % 60;
var seconds = duration % 60;
var tooltip = container.getElementsByTagName('ul');
var tooltipLabel = container.getElementsByTagName('span');
if (tooltip.length > 0) {
// increase tooltip height
tooltip[0].parentNode.style.height = '95px';
// add new li element
var newLine = tooltip[0].appendChild(document.createElement('li'));
newLine.className = 'google-visualization-tooltip-item';
// add span for label
var lineLabel = newLine.appendChild(document.createElement('span'));
lineLabel.style.fontFamily = tooltipLabel[0].style.fontFamily;
lineLabel.style.fontSize = tooltipLabel[0].style.fontSize;
lineLabel.style.color = tooltipLabel[0].style.color;
lineLabel.style.margin = tooltipLabel[0].style.margin;
lineLabel.style.textDecoration = tooltipLabel[0].style.textDecoration;
lineLabel.innerHTML = dataTable.getColumnLabel(1) + ': ';
// add span for value
var lineValue = newLine.appendChild(document.createElement('span'));
lineValue.style.fontFamily = tooltipLabel[0].style.fontFamily;
lineValue.style.fontSize = tooltipLabel[0].style.fontSize;
lineValue.style.fontWeight = tooltipLabel[0].style.fontWeight;
lineValue.style.color = tooltipLabel[0].style.color;
lineValue.style.margin = tooltipLabel[0].style.margin;
lineValue.style.textDecoration = tooltipLabel[0].style.textDecoration;
lineValue.innerHTML = hours + 'h ' + minutes + 'm ' + seconds + 's';
}
});
chart.draw(dataTable, options);
},
packages:['corechart']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
to add content to the tooltip using standard functionality requires replacing the tooltip altogether
the best result will be using html tooltips
to use html tooltips, two things must be in place
first, need html column property on tooltip column
{role: 'tooltip', type: 'string', p: {html: true}}
next, need tooltip.isHtml: true in the config options
the tooltip can be provided directly in the data,
or add dynamically, as in the following snippet...
google.charts.load('current', {
callback: function () {
var dataTable = new google.visualization.DataTable({
cols: [
{label: 'Element', type: 'string'},
{label: 'Duration', type: 'number'},
{role: 'style', type: 'string'}
],
rows: [
{c:[{v: 'Amazon Elastic Transcoder'}, {v: 3116, f: '3,116 s'}, {v: 'orange'}]},
{c:[{v: 'Amazon Elastic Transcoder'}, {v: 8523, f: '8,523 s'}, {v: 'cyan'}]}
]
});
dataTable.addColumn({role: 'tooltip', type: 'string', p: {html: true}});
for (var i = 0; i < dataTable.getNumberOfRows(); i++) {
var duration = dataTable.getValue(i, 1);
var hours = parseInt( duration / 3600 ) % 24;
var minutes = parseInt( duration / 60 ) % 60;
var seconds = duration % 60;
var tooltip = '<div class="ggl-tooltip"><span>' +
dataTable.getValue(i, 0) + '</span><div>' +
dataTable.getColumnLabel(1) + ': <span>' +
dataTable.getFormattedValue(i, 1) + '</span></div><div>' +
dataTable.getColumnLabel(1) + ': <span>' +
hours + 'h ' + minutes + 'm ' + seconds + 's</span></div></div>';
dataTable.setValue(i, 3, tooltip);
}
var options = {
backgroundColor: 'transparent',
legend: 'none',
theme: 'maximized',
hAxis: {
textPosition: 'none'
},
tooltip: {
//trigger: 'selection',
isHtml: true
}
};
var container = document.getElementById('chart_div');
var chart = new google.visualization.ColumnChart(container);
chart.draw(dataTable, options);
},
packages:['corechart']
});
.ggl-tooltip {
border: 1px solid #E0E0E0;
font-family: Arial, Helvetica;
font-size: 10pt;
padding: 12px 12px 12px 12px;
}
.ggl-tooltip div {
padding-top: 6px;
}
.ggl-tooltip span {
font-weight: bold;
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

Google Charts - How to append text to default tooltip

I want to add a custom tooltip to my charts by using the default one and for example just append some text to it.
Is this even possible, or to i have to create it all by myself with html?
data= google.visualization.arrayToDataTable([
["Element", "Duration ", { role: "style" }, { role: 'tooltip' }],
["Count", 23515, "orange", ???],
]);
How it is (Default Tooltip):
How i want it:
Append the duration as readable time, but still keep the default tooltip
it's not possible to add content to the default tooltip via standard functionality
to do so requires manipulating the tooltip directly when it is shown
the following working snippet listens for the 'onmouseover' event on the chart
then modifies the tooltip (if found)
using the row # passed as a property of the event argument
keep in mind, the style (font-size) will change according to the size of the chart
the snippet copies the style from the existing lines
google.charts.load('current', {
callback: function () {
var dataTable = new google.visualization.DataTable({
cols: [
{label: 'Element', type: 'string'},
{label: 'Duration', type: 'number'},
{role: 'style', type: 'string'}
],
rows: [
{c:[{v: 'Amazon Elastic Transcoder'}, {v: 3116, f: '3,116 s'}, {v: 'orange'}]},
{c:[{v: 'Amazon Elastic Transcoder'}, {v: 8523, f: '8,523 s'}, {v: 'cyan'}]}
]
});
var options = {
backgroundColor: 'transparent',
legend: 'none',
theme: 'maximized',
hAxis: {
textPosition: 'none'
},
tooltip: {
isHtml: true
}
};
var container = document.getElementById('chart_div');
var chart = new google.visualization.ColumnChart(container);
google.visualization.events.addListener(chart, 'onmouseover', function (props) {
var duration = dataTable.getValue(props.row, 1);
var hours = parseInt( duration / 3600 ) % 24;
var minutes = parseInt( duration / 60 ) % 60;
var seconds = duration % 60;
var tooltip = container.getElementsByTagName('ul');
var tooltipLabel = container.getElementsByTagName('span');
if (tooltip.length > 0) {
// increase tooltip height
tooltip[0].parentNode.style.height = '95px';
// add new li element
var newLine = tooltip[0].appendChild(document.createElement('li'));
newLine.className = 'google-visualization-tooltip-item';
// add span for label
var lineLabel = newLine.appendChild(document.createElement('span'));
lineLabel.style.fontFamily = tooltipLabel[0].style.fontFamily;
lineLabel.style.fontSize = tooltipLabel[0].style.fontSize;
lineLabel.style.color = tooltipLabel[0].style.color;
lineLabel.style.margin = tooltipLabel[0].style.margin;
lineLabel.style.textDecoration = tooltipLabel[0].style.textDecoration;
lineLabel.innerHTML = dataTable.getColumnLabel(1) + ': ';
// add span for value
var lineValue = newLine.appendChild(document.createElement('span'));
lineValue.style.fontFamily = tooltipLabel[0].style.fontFamily;
lineValue.style.fontSize = tooltipLabel[0].style.fontSize;
lineValue.style.fontWeight = tooltipLabel[0].style.fontWeight;
lineValue.style.color = tooltipLabel[0].style.color;
lineValue.style.margin = tooltipLabel[0].style.margin;
lineValue.style.textDecoration = tooltipLabel[0].style.textDecoration;
lineValue.innerHTML = hours + 'h ' + minutes + 'm ' + seconds + 's';
}
});
chart.draw(dataTable, options);
},
packages:['corechart']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
to add content to the tooltip using standard functionality requires replacing the tooltip altogether
the best result will be using html tooltips
to use html tooltips, two things must be in place
first, need html column property on tooltip column
{role: 'tooltip', type: 'string', p: {html: true}}
next, need tooltip.isHtml: true in the config options
the tooltip can be provided directly in the data,
or add dynamically, as in the following snippet...
google.charts.load('current', {
callback: function () {
var dataTable = new google.visualization.DataTable({
cols: [
{label: 'Element', type: 'string'},
{label: 'Duration', type: 'number'},
{role: 'style', type: 'string'}
],
rows: [
{c:[{v: 'Amazon Elastic Transcoder'}, {v: 3116, f: '3,116 s'}, {v: 'orange'}]},
{c:[{v: 'Amazon Elastic Transcoder'}, {v: 8523, f: '8,523 s'}, {v: 'cyan'}]}
]
});
dataTable.addColumn({role: 'tooltip', type: 'string', p: {html: true}});
for (var i = 0; i < dataTable.getNumberOfRows(); i++) {
var duration = dataTable.getValue(i, 1);
var hours = parseInt( duration / 3600 ) % 24;
var minutes = parseInt( duration / 60 ) % 60;
var seconds = duration % 60;
var tooltip = '<div class="ggl-tooltip"><span>' +
dataTable.getValue(i, 0) + '</span><div>' +
dataTable.getColumnLabel(1) + ': <span>' +
dataTable.getFormattedValue(i, 1) + '</span></div><div>' +
dataTable.getColumnLabel(1) + ': <span>' +
hours + 'h ' + minutes + 'm ' + seconds + 's</span></div></div>';
dataTable.setValue(i, 3, tooltip);
}
var options = {
backgroundColor: 'transparent',
legend: 'none',
theme: 'maximized',
hAxis: {
textPosition: 'none'
},
tooltip: {
//trigger: 'selection',
isHtml: true
}
};
var container = document.getElementById('chart_div');
var chart = new google.visualization.ColumnChart(container);
chart.draw(dataTable, options);
},
packages:['corechart']
});
.ggl-tooltip {
border: 1px solid #E0E0E0;
font-family: Arial, Helvetica;
font-size: 10pt;
padding: 12px 12px 12px 12px;
}
.ggl-tooltip div {
padding-top: 6px;
}
.ggl-tooltip span {
font-weight: bold;
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

Google chart table formatting cell as percentage

I am trying to format a cell in a google chart table as a percentage field.
For a column it works with :
var flow_format2 = new google.visualization.NumberFormat( {suffix: '%', negativeColor: 'red', negativeParens: true, fractionDigits: 0} );
But as far as I can read there is no possibility for a row, therefore I would like to do it on cell level - is that possible?
Is it with setProperty I need to do it and what is the formatting syntax.
you can use the formatValue method of NumberFormat to get the formatted string
rather than applying to the entire column
then you can manually setFormattedValue on the DataTable cell
to change the color, use setProperty to change the cell's 'style' property
the chart must be drawn afterwards
--or--
when the chart's 'ready' event fires, you can change the cell value using the DOM
the Table chart produces a normal set of html <table> tags
following is a working snippet, demonstrating both approaches...
google.charts.load('current', {
callback: function () {
var dataTable = new google.visualization.DataTable({
cols: [
{label: 'Name', type: 'string'},
{label: 'Amount', type: 'number'},
],
rows: [
{c:[{v: 'Adam'}, {v: -1201}]},
{c:[{v: 'Mike'}, {v: 2235}]},
{c:[{v: 'Stephen'}, {v: -5222}]},
{c:[{v: 'Victor'}, {v: 1288}]},
{c:[{v: 'Wes'}, {v: -6753}]}
]
});
var container = document.getElementById('chart_div');
var tableChart = new google.visualization.Table(container);
var patternFormat = {
suffix: '%',
negativeColor: '#FF0000',
negativeParens: true,
fractionDigits: 0
};
// create the formatter
var formatter = new google.visualization.NumberFormat(patternFormat);
// format cell - first row
dataTable.setFormattedValue(0, 1, formatter.formatValue(dataTable.getValue(0, 1)));
if (dataTable.getValue(0, 1) < 0) {
dataTable.setProperty(0, 1, 'style', 'color: ' + patternFormat.negativeColor + ';');
}
google.visualization.events.addOneTimeListener(tableChart, 'ready', function () {
// format cell via DOM - third row
var tableCell = container.getElementsByTagName('TR')[3].cells[1];
tableCell.innerHTML = formatter.formatValue(dataTable.getValue(2, 1));
if (dataTable.getValue(2, 1) < 0) {
tableCell.style.color = patternFormat.negativeColor;
}
});
tableChart.draw(dataTable, {
allowHtml: true
});
},
packages: ['table']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

How to give style to x-axis of google charts?

I am implementing google charts and I want to give style to x-axis data. I found there the following code to do this.
hAxis:{
title: 'Month',
textStyle :{
fontSize : 10
}
}
I want to underline the text data and change cursor style to the pointer. I searched on the google chart website but didn't get.
you can modify the text elements directly,
when the 'ready' event fires on the chart
you can select which axis labels to modify by using the 'text-anchor' attribute
x-axis labels have a value of 'middle', y-axis 'end'
see following working snippet...
google.charts.load('current', {
callback: function () {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Category');
data.addColumn('number', 'Value');
data.addRows([
['Category A', 200],
['Category B', 110],
['Category D', 310],
['Category E', 280],
['Category F', 175]
]);
var options = {
hAxis: {
textStyle: {
fontSize : 10
},
title: 'Month'
},
height: 400,
width: 600
};
var chartContainer = document.getElementById('chart_div');
var chart = new google.visualization.ComboChart(chartContainer);
google.visualization.events.addListener(chart, 'ready', function () {
// modify x-axis labels
var labels = chartContainer.getElementsByTagName('text');
Array.prototype.forEach.call(labels, function(label) {
if (label.getAttribute('text-anchor') === 'middle') {
label.style.textDecoration = 'underline';
label.style.cursor = 'pointer';
}
});
});
chart.draw(data, options);
},
packages: ['corechart']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

how to get x-axis line and value of the google bar chart to the top of the chart

Im using google chart for my application. I need a chart like
Expected
and i used this code to get the expected chart.
google.load("visualization", "1", {packages: ["corechart"]});
function drawVisualization() {
// Create and populate the data table.
var data = google.visualization.arrayToDataTable([
['numbers', 'Austria', 'Bulgaria'],
[2003, 1336060, 400361],
[2004, 1538156, 366849],
[2005, 1576579, 440514],
[2006, 1600652, 434552],
[2007, 1968113, 393032],
[2008, 1901067, 517206]
]);
var hAxisTick = [{v: '2003', f: "3-4"}, {v: '2004', f: "5-9"}, {v: '2005', f: "9-13"}, {v: '2006', f: "13-14"}, {v: '2007', f: "14-24"}, {v: '2008', f: "24-84"}];
var vAxisTick = [0, 1968113];
// Create and draw the visualization.
new google.visualization.BarChart(document.getElementById('chart_div')).
draw(data,
{width: 600, height: 250,
colors: ['706C6B', 'D6D3D3'],
legend: {position: 'none'},
vAxis: {ticks: hAxisTick, gridlines: {color: 'FFFFFF'}},
hAxis: {gridlines: {color: 'FFFFFF'}, ticks: vAxisTick, baselineColor: '#FFFFFF'},
enableInteractivity: false}
);
}
google.setOnLoadCallback(drawVisualization);
but,
Actual
how to get the x-axis line to the top and also i need to show the tick mark for the given points.