How to Write Your Own Custom Legends for Google Line Chart/ Google Line Chart Legend Manipulation

How to write your own custom legends for google line chart/ Google line chart legend manipulation

Example: Build custom legend, which syncs with data and chart...

google.charts.load('44', {  callback: drawChart,  packages: ['controls', 'corechart']});
function drawChart() { // adapted from a previous example var colorPallette = ['#273746','#707B7C','#dc7633','#f1c40f','#1e8449','#2874a6','#6c3483','#922b21'];
var data = new google.visualization.DataTable(); data.addColumn('date', 'X'); data.addColumn('number', 'Y1'); data.addColumn('number', 'Y2');
data.addRow([new Date(2016, 0, 1), 1, 123]); data.addRow([new Date(2016, 1, 1), 6, 42]); data.addRow([new Date(2016, 2, 1), 4, 49]); data.addRow([new Date(2016, 3, 1), 23, 486]); data.addRow([new Date(2016, 4, 1), 89, 476]); data.addRow([new Date(2016, 5, 1), 46, 444]); data.addRow([new Date(2016, 6, 1), 178, 442]); data.addRow([new Date(2016, 7, 1), 12, 274]); data.addRow([new Date(2016, 8, 1), 123, 934]); data.addRow([new Date(2016, 9, 1), 144, 145]); data.addRow([new Date(2016, 10, 1), 135, 946]); data.addRow([new Date(2016, 11, 1), 178, 747]);
// use view to add various columns for example purposes var view = new google.visualization.DataView(data); view.setColumns([0, 1, 2, { calc: function (data, row) { return data.getValue(row, 1) + data.getValue(row, 2); }, type: 'number', label: 'Y3' }, { calc: function (data, row) { return data.getValue(row, 2) - data.getValue(row, 1); }, type: 'number', label: 'Y4' }, { calc: function (data, row) { return data.getValue(row, 1) * 2; }, type: 'number', label: 'Y5' }, { calc: function (data, row) { return data.getValue(row, 2) * 3; }, type: 'number', label: 'Y6' }, { calc: function (data, row) { return data.getValue(row, 1) * 1.5; }, type: 'number', label: 'Y7' }, { calc: function (data, row) { return data.getValue(row, 1) * 1.5; }, type: 'number', label: 'Y8' } ]);
var control = new google.visualization.ControlWrapper({ controlType: 'DateRangeFilter', containerId: 'control_div', options: { filterColumnIndex: 0 } });
var chart = new google.visualization.ChartWrapper({ chartType: 'LineChart', containerId: 'chart_div', options: { chartArea: { width: '80%' }, // add colors for legend mapping colors: colorPallette, hAxis: { format: 'MMM', slantedText: false, maxAlternation: 1 }, legend: 'none', width: 320 } });
// add legend marker function addLegendMarker(markerProps) { var legendMarker = document.getElementById('template-legend-marker').innerHTML; for (var handle in markerProps) { if (markerProps.hasOwnProperty(handle)) { legendMarker = legendMarker.replace('{{' + handle + '}}', markerProps[handle]); } } document.getElementById('legend_div').insertAdjacentHTML('beforeEnd', legendMarker); }
// chart ready event google.visualization.events.addListener(chart, 'ready', function () { var legend = document.getElementById('legend_div');
// colors from chart var colorPallette = chart.getOption('colors');
// clear previous legend legend.innerHTML = '';
// add legend marker for each Y axis column - skip X axis --> i = 1 for (var i = 1; i < chart.getDataTable().getNumberOfColumns(); i++) { var markerProps = {}; markerProps.index = i; markerProps.color = colorPallette[i - 1]; markerProps.label = chart.getDataTable().getColumnLabel(i); addLegendMarker(markerProps); }
// add click event to each legend marker var markers = legend.getElementsByTagName('DIV'); Array.prototype.forEach.call(markers, function(marker) { marker.addEventListener('click', function (e) { var marker = e.target || e.srcElement; if (marker.tagName.toUpperCase() !== 'DIV') { marker = marker.parentNode; } var columnIndex = parseInt(marker.getAttribute('data-columnIndex')); document.getElementById('message_div').innerHTML = 'legend marker clicked = ' + chart.getDataTable().getColumnLabel(columnIndex); }, false); }); });
var dash = new google.visualization.Dashboard(document.getElementById('dashboard')); dash.bind([control], [chart]); dash.draw(view);}
#legend_div {  text-align: center;  width: 320px;}
.legend-marker { display: inline-block; padding: 16px 4px 8px 4px;}
.legend-marker-color { display: inline-block; height: 12px; width: 12px;}
<script src="https://www.gstatic.com/charts/loader.js"></script><div id="dashboard">  <div id="chart_div"></div>  <div id="legend_div"></div>  <br/>  <div id="control_div"></div>  <br/>  <div id="message_div"></div></div>
<!-- template for building marker --><script id="template-legend-marker" type="text/html"> <div class="legend-marker" data-columnIndex="{{index}}"> <div class="legend-marker-color" style="background-color: {{color}}"></div> <span>{{label}}</span> </div></script>

Google charts legend manipulation

There isn't a way to manipulate the legends as we wish.
In the question of the bounty:
You can use

in two of the charts

legend : 'none'

and also use colours to guarantee that all elements have the same colour.

colors:['red','#004411']

Other than that we can't manipulate them much more unfortunately :(

Custom Legend multiple colors in Google Chart

the standard legend on a google chart will not display multiple colors.

in fact, when using the style column role,

the legend will not match the colors used in the style columns in the data table.

instead, we can build a custom legend to display the multiple colors for each series.

to build the legend, we need to add a container to hold the legend entries.

we can use a <div> element placed just below the chart.

<div id="chart_div"></div>
<div id="legend_div"></div>

we can use css to style the legend container and use the same width of the chart.

#legend_div {
font-family: Arial;
font-size: 11px;
text-align: center;
width: 920px;
}

in the following example, I extract the colors for each series from the data table.

using the values provided in the style column roles.

to create the legend content, I use the following html templates.

one for the legend entry itself...

<script id="template-legend-entry" type="text/html">
<div class="legend-entry" data-columnIndex="{{index}}">
{{colors}}
<span>{{label}}</span>
</div>
</script>

and another for each color to be displayed for that series...

<script id="template-legend-entry-color" type="text/html">
<div class="legend-entry-color" style="background-color: {{color}}"></div>
</script>

in this example, only two rows exist in the data table,

so two colors will be displayed for each legend entry.

the legend is built during the chart's 'ready' event,

so as soon as the chart is finished drawing,

the legend will be displayed.

during which, the colors are extracted from the data table and used to build the legend entries.

a click event is added for example purposes, in case there are actions you would like to take when a legend entry is clicked.

in this example, the chart series is selected to highlight which legend entry was clicked.

google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
["","0 times (never)",{"role":"style"},"1 times",{"role":"style"},"2 times",{"role":"style"},"3 times or more",{"role":"style"}],
["A class",0.581,"#b4ddfd",0.109,"#84bfef",0.21,"#559ad2",0.1,"#4277a1"],
["nationality",0.481,"#ffddba",0.209,"#ffc384",0.25,"#ffac5b",0.06,"#fa993f"]
]);

var options = {
vAxis: {
textStyle: {
fontSize: 11
},
titleTextStyle: {
italic: false
}
},
chartArea: {
width: '85%',
top: 30,
left: '13%'
},
bar: {
groupWidth: '35%'
},
legend: {
position: 'none'
},
isStacked: 'percent',
hAxis: {
ticks: [0, 1],
textStyle: {
fontSize: 13
},
minValue: 0,
maxValue: 1
},
width: 920,
height: '100%'
};

var chart = new google.visualization.BarChart(document.getElementById('chart_div'));

// chart ready event
google.visualization.events.addListener(chart, 'ready', function () {
// legend container
var legend = document.getElementById('legend_div');
legend.innerHTML = '';

// build legend from chart data
var colorPallette = [];
for (var colIndex = 0; colIndex < data.getNumberOfColumns(); colIndex++) {
// determine if style column
if (data.getColumnRole(colIndex) === 'style') {
// save colors for entire series (all rows)
var seriesColors = '';
for (var rowIndex = 0; rowIndex < data.getNumberOfRows(); rowIndex++) {
seriesColors += renderTemplate('template-legend-entry-color', {
color: data.getValue(rowIndex, colIndex)
});
}

// add legend for series (all colors)
legend.insertAdjacentHTML('beforeEnd', renderTemplate('template-legend-entry', {
colors: seriesColors,
index: colIndex - 1,
label: data.getColumnLabel(colIndex - 1)
}));
}
}

// add click event to legend entries
var legendEntries = legend.getElementsByClassName('legend-entry');
Array.prototype.forEach.call(legendEntries, function(entry) {
entry.addEventListener('click', function (e) {
// find legend entry
var entry = e.target || e.srcElement;
if (entry.className.toLowerCase() !== 'legend-entry') {
entry = entry.parentNode;
}

// get data table column index from legend entry
var columnIndex = parseInt(entry.getAttribute('data-columnIndex'));

// display legend entry that was clicked
document.getElementById('message_div').innerHTML = 'legend entry clicked = ' + data.getColumnLabel(columnIndex);

// select chart series
chart.setSelection([{row: null, column: columnIndex}]);
}, false);
});
});

// render html template
function renderTemplate(templateId, templateProps) {
var content = document.getElementById(templateId).innerHTML;
for (var handle in templateProps) {
if (templateProps.hasOwnProperty(handle)) {
content = content.replace('{{' + handle + '}}', templateProps[handle]);
}
}
return content.trim();
}

// draw chart
chart.draw(data, options);
});
#legend_div {
font-family: Arial;
font-size: 11px;
text-align: center;
width: 920px;
}

.legend-entry {
display: inline-block;
padding: 16px 4px 8px 4px;
}

.legend-entry-color {
display: inline-block;
height: 12px;
width: 12px;
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
<div id="legend_div"></div>
<div id="message_div"></div>

<script id="template-legend-entry" type="text/html">
<div class="legend-entry" data-columnIndex="{{index}}">
{{colors}}
<span>{{label}}</span>
</div>
</script>

<script id="template-legend-entry-color" type="text/html">
<div class="legend-entry-color" style="background-color: {{color}}"></div>
</script>

Fetch the legend in customized HTML in google charts

to correct the issue with the slider,

need to use filtered data table from pie chart when building markers

(see comment below //...)

to highlight slice on hover, simply use the chart's setSelection method

see following working snippet...

google.charts.load('current', {  packages: ['controls', 'corechart']}).then(function () {  var data = new google.visualization.DataTable();  data.addColumn('string', 'Name');  data.addColumn('number', 'Donuts eaten');  data.addRows([    ['Jackson' , 5],    ['Elisa', 7],    ['Robert', 3],    ['John', 2],    ['Jessica', 6],    ['Aaron', 1],    ['Margareth', 8]  ]);
var dashboard = new google.visualization.Dashboard( document.getElementById('dashboard_div') );
var donutRangeSlider = new google.visualization.ControlWrapper({ controlType: 'NumberRangeFilter', containerId: 'filter_div', options: { filterColumnLabel: 'Donuts eaten' } });
var pieChart = new google.visualization.ChartWrapper({ chartType: 'PieChart', containerId: 'chart_div', options: { width: 300, height: 300, pieSliceText: 'value', legend: 'none', colors: [ "#ee99fd", "#949ed5", "#fd6e6e", "#e6ddda", "#fdcf57", "#51b8ae", "#bada55" ], pieHole: 0.4 } });
function addLegendMarker(markerProps) { var legendMarker = document.getElementById('template-legend-marker').innerHTML; for (var handle in markerProps) { if (markerProps.hasOwnProperty(handle)) { legendMarker = legendMarker.replace('{{' + handle + '}}', markerProps[handle]); } } document.getElementById('legend_div').insertAdjacentHTML('beforeEnd', legendMarker); }
google.visualization.events.addListener(pieChart, 'ready', function () { var legend = document.getElementById('legend_div'); legend.innerHTML = ''; // use filtered data table from piechart for (var i = 0; i < pieChart.getDataTable().getNumberOfRows(); i++) { var markerProps = {}; markerProps.index = i; markerProps.color = pieChart.getOption('colors')[i]; markerProps.label = pieChart.getDataTable().getValue(i, 0); addLegendMarker(markerProps); }
// add legend hover var markers = legend.getElementsByTagName('DIV'); Array.prototype.forEach.call(markers, function(marker) { marker.addEventListener('mouseover', function (e) { var marker = e.target || e.srcElement; if (marker.className !== 'legend-marker') { marker = marker.parentNode; } var rowIndex = parseInt(marker.getAttribute('data-rowIndex')); pieChart.getChart().setSelection([{row: rowIndex}]); }, false); marker.addEventListener('mouseout', function (e) { var marker = e.target || e.srcElement; if (marker.className !== 'legend-marker') { marker = marker.parentNode; } var rowIndex = parseInt(marker.getAttribute('data-rowIndex')); var selection = pieChart.getChart().getSelection(); if (selection.length > 0) { if (selection[0].row === rowIndex) { pieChart.getChart().setSelection([]); } } }, false); }); });
dashboard.bind(donutRangeSlider, pieChart); dashboard.draw(data);});
#legend_div {  text-align: center;  width: 500px;}
.legend-marker { display: inline-block; padding: 16px 4px 8px 4px;}
.legend-marker-color { display: inline-block; height: 12px; width: 12px;}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="dashboard_div"> <div id="filter_div"></div> <div id="chart_div"></div> <div id="legend_div"></div> <div id="message_div"></div></div>
<script id="template-legend-marker" type="text/html"> <div class="legend-marker" data-rowIndex="{{index}}"> <div class="legend-marker-color" style="background-color: {{color}}"></div> <span>{{label}}</span> </div></script>

Google line chart legend display name

the column labels are initially set when using arrayToDataTable to create the data table

so, instead of using addColumn, you just need to change the existing labels

replace...

data.addColumn("number", '" + SelectedLine1 + "');
...

with...

data.setColumnLabel(1, SelectedLine1);
data.setColumnLabel(2, SelectedLine2);
data.setColumnLabel(3, SelectedLine3);

Is it possible to format the legend in Google Charts?

you can use a DataView with calculated columns,

to translate the values to the respective names

use DataView method setColumns,

see following working snippet...

google.charts.load('current', {  callback: drawChart,  packages:['table']});
function drawChart() { var data = google.visualization.arrayToDataTable([ ['ID', 'Carrier A', 'Carrier B', 'Carrier C', 'Amount'], [1, 'S', 'V', 'A', 36], [2, 'V', 'A', 'S', 15], [3, 'A', 'V', 'T', 22], [4, 'S', 'A', 'V', 48] ]);
var dataView = new google.visualization.DataView(data); dataView.setColumns([0, { calc: function (dt, row) { return getCarrierName(dt.getValue(row, 1)); }, type: 'string', label: data.getColumnLabel(1) }, { calc: function (dt, row) { return getCarrierName(dt.getValue(row, 2)); }, type: 'string', label: data.getColumnLabel(2) }, { calc: function (dt, row) { return getCarrierName(dt.getValue(row, 3)); }, type: 'string', label: data.getColumnLabel(3) }, 4]);
function getCarrierName(abbr) { var name;
switch (abbr) { case 'A': name = 'AT&T'; break;
case 'S': name = 'Sprint'; break;
case 'T': name = 'T-Mobile'; break;
case 'V': name = 'Verizon'; break;
default: name = ''; }
return name; }
var chart = new google.visualization.Table(document.getElementById('chart_div')); chart.draw(dataView);}
<script src="https://www.gstatic.com/charts/loader.js"></script><div id="chart_div"></div>

Replace a showR2 with a custom text in a Google Chart?

to change the trendline label in the legend, use option --> labelInLegend

there are no standard options to change the value in the tooltip,

but it can be changed manually using event --> onmouseover

when the legend's position is top,

you can use option --> legend.maxLines
to increase the number of lines available and prevent the arrows...

to ensure all dates are shown on the x-axis,

allow enough room by using option --> chartArea.bottom

see following working snippet for examples of each...

google.charts.load('current', {  packages: ['corechart']}).then(function () {  var data = google.visualization.arrayToDataTable([    ['x', 'y0', 'y1'],    [new Date(2017, 11, 28), 175, 10],    [new Date(2017, 11, 29), 159, 20],    [new Date(2017, 11, 30), 126, 35],    [new Date(2017, 11, 31), 129, 40],    [new Date(2018, 0, 1), 108, 60],    [new Date(2018, 0, 2), 92, 70]  ]);
var options = { chartArea: { bottom: 72 }, hAxis: { slantedText: true }, height: 400, legend: { maxLines: 2, position: 'top' }, tooltip: { isHtml: true }, trendlines: { 0: { labelInLegend: '0-Linear Trend', showR2: true, type: 'linear', visibleInLegend: true }, 1: { labelInLegend: '1-Linear Trend', showR2: true, type: 'linear', visibleInLegend: true } }, width: 400 };
var container = document.getElementById('chart_div'); var chart = new google.visualization.ColumnChart(container);
google.visualization.events.addListener(chart, 'onmouseover', function (props) { var tooltipLabels = container.getElementsByTagName('span'); for (var i = 0; i < tooltipLabels.length; i++) { if (tooltipLabels[i].innerHTML.indexOf('y =') > -1) { tooltipLabels[i].innerHTML = 'CUSTOM TEXT:'; } } });
chart.draw(data, options);});
<script src="https://www.gstatic.com/charts/loader.js"></script><div id="chart_div"></div>

Google sheets script - chart legend text labels

I believe your goal as follows.

  • You want to set the 1st row of the range as the header row, when you create a chart using Google Apps Script.

In this case, how about using setNumHeaders in Class EmbeddedTableChartBuilder? When your script is modified it becomes as follows.

Modified script:

var sheet1 = SpreadsheetApp.getActiveSheet();
var chart = sheet1.newChart()
.setChartType(Charts.ChartType.LINE)
.addRange(sheet2.getRange('A1:D12'))
.setPosition(5, 5, 0, 0)
.setNumHeaders(1) // <--- Added
.build();

sheet1.insertChart(chart);
  • By adding setNumHeaders(1) as above modification, "Use row 1 as headers" is checked.

Reference:

  • setNumHeaders(headers)


Related Topics



Leave a reply



Submit