Google charts, Column chart two different colors per column - charts

Let's say I have a datatable like this:
drivingData.addColumn('string', 'VehicleGroup');
drivingData.addColumn('number', 'TimeType');
drivingData.addColumn('number', 'TimeTarget');
drivingData.addColumn('number', 'TimeUsed');
then I add 4 rows like this:
drivingData.addRow(['Trucks-S',0, 1000, 1200])
drivingData.addRow(['Trucks-F',1, 300, 500])
drivingData.addRow(['Trailer-S',0, 1200, 1500])
drivingData.addRow(['Trailer-F',1, 100, 500])
I would like to have a 'stacked' column chart. First one shows Trucks-S with TimeType 0 with yellow and orange colors.
Second would show Trucks-F with TimeType 1 with grey and light-grey colors.
Third would then again be yellow and orange and fourth grey and light-grey and so on...
Is this possible?
Something like this:
https://imgur.com/a/oNOiP

the requested chart is only available as a Material bar chart
Material --> google.charts.Bar -- packages: ['bar']
Classic --> google.visualization.ColumnChart -- packages: ['corechart']
you can break Material bar charts into multiple stacks,
by assigning a group of series to a different y-axis
this is accomplished by using the series option
series: {
2: {
targetAxisIndex: 1
},
3: {
targetAxisIndex: 1
}
},
this will create a second axis on the right side of the chart,
which will have a different scale by default
to keep both y-axis in sync, assign a specific view window
vAxis: {
viewWindow: {
min: 0,
max: 3000
}
}
see following working snippet...
google.charts.load('current', {
packages: ['bar']
}).then(function () {
var drivingData = new google.visualization.DataTable();
drivingData.addColumn('string', 'VehicleGroup');
drivingData.addColumn('number', 'TimeTarget');
drivingData.addColumn('number', 'TimeUsed');
drivingData.addColumn('number', 'TimeTarget');
drivingData.addColumn('number', 'TimeUsed');
drivingData.addRow(['Trucks-S', 1000, 1200, 600, 800])
drivingData.addRow(['Trucks-F', 300, 500, 700, 900])
drivingData.addRow(['Trailer-S', 1200, 1500, 800, 1000])
drivingData.addRow(['Trailer-F', 100, 500, 600, 1000])
var container = document.getElementById('chart_div');
var chart = new google.charts.Bar(container);
var options = google.charts.Bar.convertOptions({
colors: ['#fbc02d', '#616161'],
height: 400,
isStacked: true,
series: {
2: {
targetAxisIndex: 1
},
3: {
targetAxisIndex: 1
}
},
vAxis: {
viewWindow: {
min: 0,
max: 3000
}
}
});
chart.draw(drivingData, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
note: just keep in mind,
there are several configuration options that are not supported by Material charts
see --> Tracking Issue for Material Chart Feature Parity
EDIT
isStacked: 'percent' is currently not support by Material charts
to work around this issue, convert the data manually, before drawing the chart
see following working snippet,
y-axis columns will be converted in groups of two...
google.charts.load('current', {
packages: ['bar']
}).then(function () {
var drivingData = new google.visualization.DataTable();
drivingData.addColumn('string', 'VehicleGroup');
drivingData.addColumn('number', 'TimeTarget');
drivingData.addColumn('number', 'TimeUsed');
drivingData.addColumn('number', 'TimeTarget');
drivingData.addColumn('number', 'TimeUsed');
drivingData.addRow(['Trucks-S', 1000, 1200, 600, 800])
drivingData.addRow(['Trucks-F', 300, 500, 700, 900])
drivingData.addRow(['Trailer-S', 1200, 1500, 800, 1000])
drivingData.addRow(['Trailer-F', 100, 500, 600, 1000])
// convert data to percent
var percentData = new google.visualization.DataTable();
for (var col = 0; col < drivingData.getNumberOfColumns(); col++) {
percentData.addColumn(drivingData.getColumnType(col), drivingData.getColumnLabel(col));
}
for (var row = 0; row < drivingData.getNumberOfRows(); row++) {
var newRow = percentData.addRow();
percentData.setValue(newRow, 0, drivingData.getValue(row, 0));
for (var col = 1; col < drivingData.getNumberOfColumns(); col++) {
if ((col % 2) !== 0) {
var rowTotal = drivingData.getValue(row, col) + drivingData.getValue(row, (col + 1));
percentData.setValue(newRow, col, (drivingData.getValue(row, col) / rowTotal));
percentData.setValue(newRow, (col + 1), (drivingData.getValue(row, (col + 1)) / rowTotal));
}
}
}
var container = document.getElementById('chart_div');
var chart = new google.charts.Bar(container);
var options = google.charts.Bar.convertOptions({
colors: ['#fbc02d', '#616161'],
height: 400,
isStacked: true,
series: {
2: {
targetAxisIndex: 1
},
3: {
targetAxisIndex: 1
}
},
vAxis: {
format: '0%',
viewWindow: {
min: 0,
max: 1
}
}
});
chart.draw(percentData, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

Related

Google Visualization SteppedAreaChart with time as axis incorrectly aligned

I'm creating a SteppedArea chart in Google Visualization to display queue length at various times of the day. My problem is that the steps in the chart don't align with the associated times. They are always one data point out. In the example below, my dataTable has 9:00 = 0, 12:00 = 3 and 14:00 = 6, but the resultant chart offsets the values, so it appears the queue between 9 and 12 is 3 when it really should be 0.
Is this a bug in the Chart rendering or am misunderstanding something ?
I guess my workaround is to offset my initial dataTable.
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('timeofday', 'Time of Day');
data.addColumn('number', 'Queue Length');
// DataTable of Time and Queue length
data.addRows([
[[9,0,0], 0],
[[12,0,0], 3],
[[14,0,0], 6],
]);
var options = {
width: 500,
height: 500,
legend: {position: 'top'},
enableInteractivity: false,
chartArea: {
width: '85%'
},
hAxis: {
viewWindow: {
min: [8,0,0],
max: [15,0,0]
},
gridlines: {
count: -1,
units: {hours: {format: ['h a']}}
},
minorGridlines: {count: 0},
}
};
var chart = new google.visualization.SteppedAreaChart(
document.getElementById('chart_div'));
chart.draw(data, options);
}
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
I've shifted the data via a view which seems to give me the right looking chart. See the example which shows before and after. Note I had to add a dummy point at the end of the dataset otherwise the last point gets missed off. I also had to assume the first point would be zero which is acceptable in my case. Unless another idea surfaces I'll go with this.
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('timeofday', 'Time of Day');
data.addColumn('number', 'Queue Length');
data.addRows([
[[9,0,0], 2],
[[11,30,0], 1],
[[12,0,0], 2],
[[13,0,0], 3],
[[14,0,0], 2],
]);
var options = {
width: 500,
height: 500,
legend: {position: 'top'},
enableInteractivity: false,
chartArea: {
width: '85%'
},
hAxis: {
viewWindow: {
min: [8,0,0],
max: [15,0,0]
},
gridlines: {
count: -1,
units: {hours: {format: ['h a']}}
},
minorGridlines: {count: 0},
}
};
var chart = new google.visualization.SteppedAreaChart(
document.getElementById('chart_div'));
chart.draw(data, options);
// need to add dummy point to end.
data.addRows([
[[23,59,0], 0]
]);
// use a view to shift the data so that it returns the value from previous row.
var data2 = new google.visualization.DataView(data);
data2.setColumns([0,
{calc: function (dt, row) {
if (row === 0) {return 0}
else {return dt.getValue(row-1,1)}
},
label: 'Queue Moved',type: 'number'}
]);
var chart2 = new google.visualization.SteppedAreaChart(
document.getElementById('chart2_div'));
chart2.draw(data2, options);
}
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<h1>Has Wrong transition times</h1>
<div id="chart_div"></div>
<h1>Looks Correct : Has transition shifted via view</h1>
<div id="chart2_div"></div>

Google Charts display options

My questions (short style)
Can you customize a y-axis labeling interval ?
Can you display the extreme values of a series as an horizontal line ?
The detailed explanations
I have a combo chart made with Google Charts : the first set of data uses an area style, and the second a line style. The second one is the one that matters here :
it represents a percentage
i don't want it from 0 to 1 (or 0 to 100 in percentage), but from its min to its max (or something near)
and i want to display those min and max values
If i modify the scale so :
PHP
$min_reject_percentage = 5 * floor($min_reject_percentage / 5);
$max_reject_percentage = 5 * ceil($max_reject_percentage / 5);
JS
var options = {
...
vAxes: {
...
1: {
format:"##%",
viewWindow: {
min: <?php echo ($min_taux_rejet / 100); ?>,
max: <?php echo ($max_taux_rejet / 100); ?>,
},
},
},
series: {
0: {
targetAxisIndex: 0,
type: 'area',
},
1: {
targetAxisIndex: 1,
type: 'line',
},
}
}
The vertical axis is limited to the nearest multiple of 5 for min and max values, but :
the interval shown on the axis is from 10 to 10, which is too big. Since i have a real max of 31.5 and a real min of 17.1, axis min is 15 is 15 and axis max is 35, but the only graduation labeled are 20 and 30.
i can't see the real min and max on the graph
you can use config option ticks, which is an array of values to be used for the labels...
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
['x', 'y0', 'y1'],
[0, 18, 0.171],
[1, 28, 0.315],
]);
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
var axisMin = 0.15;
var axisMax = 0.35;
var ticks = [];
for (var i = axisMin; i <= axisMax; i = i + 0.05) {
ticks.push(i);
}
var options = {
vAxes: {
1: {
format: '##%',
ticks: ticks,
viewWindow: {
min: axisMin,
max: axisMax,
},
},
},
series: {
0: {
targetAxisIndex: 0,
type: 'area',
},
1: {
targetAxisIndex: 1,
type: 'line',
},
}
};
chart.draw(data, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

how to get imageUri for google chart

This is my sample material bar graph and i want the image uri for the plotted graph
google.charts.load('current', {'packages':['bar']});
google.charts.setOnLoadCallback(drawStuff);
function drawStuff() {
var data = new google.visualization.arrayToDataTable([
['Galaxy', 'Distance', 'Brightness'],
['Canis Major Dwarf', 8000, 23.3],
['Sagittarius Dwarf', 24000, 4.5],
['Ursa Major II Dwarf', 30000, 14.3],
['Lg. Magellanic Cloud', 50000, 0.9],
['Bootes I', 60000, 13.1]
]);
var options = {
width: 800,
chart: {
title: 'Nearby galaxies',
subtitle: 'distance on the left, brightness on the right'
},
bars: 'vertical', // Required for Material Bar Charts.
series: {
0: { axis: 'distance' }, // Bind series 0 to an axis named 'distance'.
1: { axis: 'brightness' } // Bind series 1 to an axis named 'brightness'.
},
axes: {
x: {
distance: {label: 'parsecs'}, // Bottom x-axis.
brightness: {side: 'top', label: 'apparent magnitude'} // Top x-axis.
}
}
};
var chart = new google.charts.Bar(document.getElementById('dual_x_div'));
chart.draw(data, options);
console.log(chart.getImageURI());
};
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<div id="dual_x_div" style="width: 900px; height: 500px;"></div>
But the console giving me error like
chart.getImageURI is not a function
you can use html2canvas
you'll need the following two files from the build
<script src="html2canvas.js"></script>
<script src="html2canvas.svg.js"></script>
then on the chart's 'ready' event...
google.visualization.events.addListener(chart, 'ready', function () {
// add svg namespace to chart
$(chartContainer).find('svg').attr('xmlns', 'http://www.w3.org/2000/svg');
// get image uri
html2canvas(chartContainer, {
allowTaint: true,
taintTest: false
}).then(function(canvas) {
console.log(canvas.toDataURL('image/png'));
});
});
UPDATE
another method is to convert the svg to an image and draw it on a canvas,
then pull the uri from the canvas...
google.charts.load('current', {
packages:['bar']
}).then(function () {
var data = new google.visualization.arrayToDataTable([
['Galaxy', 'Distance', 'Brightness'],
['Canis Major Dwarf', 8000, 23.3],
['Sagittarius Dwarf', 24000, 4.5],
['Ursa Major II Dwarf', 30000, 14.3],
['Lg. Magellanic Cloud', 50000, 0.9],
['Bootes I', 60000, 13.1]
]);
var options = {
width: 800,
chart: {
title: 'Nearby galaxies',
subtitle: 'distance on the left, brightness on the right'
},
bars: 'vertical', // Required for Material Bar Charts.
series: {
0: { axis: 'distance' }, // Bind series 0 to an axis named 'distance'.
1: { axis: 'brightness' } // Bind series 1 to an axis named 'brightness'.
},
axes: {
x: {
distance: {label: 'parsecs'}, // Bottom x-axis.
brightness: {side: 'top', label: 'apparent magnitude'} // Top x-axis.
}
}
};
var chartContainer = document.getElementById('dual_x_div');
var chart = new google.charts.Bar(chartContainer);
google.visualization.events.addListener(chart, 'ready', function () {
var canvas;
var domURL;
var imageNode;
var imageURL;
var svgParent;
// add svg namespace to chart
domURL = window.URL || window.webkitURL || window;
svgParent = chartContainer.getElementsByTagName('svg')[0];
svgParent.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
imageNode = chartContainer.cloneNode(true);
imageURL = domURL.createObjectURL(new Blob([svgParent.outerHTML], {type: 'image/svg+xml'}));
image = new Image();
image.onload = function() {
canvas = document.getElementById('canvas');
canvas.setAttribute('width', parseFloat(svgParent.getAttribute('width')));
canvas.setAttribute('height', parseFloat(svgParent.getAttribute('height')));
canvas.getContext('2d').drawImage(image, 0, 0);
console.log(canvas.toDataURL('image/png'));
}
image.src = imageURL;
});
chart.draw(data, options);
});
.hidden {
display: none;
visibility: hidden;
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="dual_x_div"></div>
<canvas class="hidden" id="canvas"></canvas>
I noticed this question was posted three years ago. Google Charts probably have had quite a few updates since then. According to Google Charts though, getImageURI should work for all core charts and geocharts. The chart in question is a bar chart, which is one of the core charts of Google Charts. So, getImageURI should work. Looking at your first line of codes, you specify bar as the packages. You need to change it to say corechart. So, you will have like the following line
google.charts.load('current', {packages: ['corechart']});
And then further down, change the chart definition to var chart = new google.visualization.BarChart(document.getElementById('dual_x_div'));
After making these changes, chart.getImageURI() should return what you want. I recently did a bar chart myself and that's how I got mine to work.

Second Y axis in stacked (positive/negative) bar chart in Google Charts

I have build a stacked bar chart to illustrate positive and negative values which looks like this:
Because these values indicate opposites I want to add additional labels to a right Y axis. Is this even possible? My code so far:
var data = google.visualization.arrayToDataTable([
['Type', 'Value1', 'Value2'],
['Left-1', 0, -5],
['Left-2', 0, -3],
['Left-3', 0, 0],
['Left-4', 3, 0],
['Left-5', 5, 0]
]);
var options = {
legend: 'none',
hAxis: {
minValue: -6,
maxValue: 6
}
}
var chart = new google.visualization.BarChart(document.getElementById('chart_div'));
chart.draw(data, options);
jsfiddle: https://jsfiddle.net/cLz5nffm/
there aren't any standard options for an additional axis in this configuration
but you can add custom labels
once the 'ready' event fires
see following working snippet...
google.charts.load('current', {
callback: drawChart,
packages: ['corechart']
});
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Type', 'Value1', 'Value2'],
['Left-1', 0, -5],
['Left-2', 0, -3],
['Left-3', 0, 0],
['Left-4', 3, 0],
['Left-5', 5, 0]
]);
var options = {
legend: 'none',
hAxis: {
minValue: -6,
maxValue: 6
}
}
var chartDiv = document.getElementById('chart_div');
var chart = new google.visualization.BarChart(chartDiv);
google.visualization.events.addListener(chart, 'ready', function () {
Array.prototype.forEach.call(chartDiv.getElementsByTagName('text'), function(axisLabel) {
if (axisLabel.getAttribute('text-anchor') === 'end') {
addLabel(
axisLabel,
chart.getChartLayoutInterface().getChartAreaBoundingBox().left +
chart.getChartLayoutInterface().getChartAreaBoundingBox().width - 24 // <-- find good width
);
}
});
function addLabel(label, xOffset) {
var axisLabel = label.cloneNode(true);
axisLabel.setAttribute('x', parseFloat(label.getAttribute('x')) + xOffset);
axisLabel.innerHTML = label.innerHTML.replace('Left-', 'Right ');
chartDiv.getElementsByTagName('svg')[0].appendChild(axisLabel);
}
});
chart.draw(data, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

I need a single column column chart for Google Charts

I need a one column column-chart that has a vertical axis from 0 to 150000 and a bar that fills it (they have met their deductible completely). I thought I had what I read to do this as below, but that gives me a vertical axis of 0 to 400,000 and a bar up to 150,000.
Alternatively, I could use suggestions on how to display a single field whereas one can pay in full or in 4 payments to meet that deductible.
PLEASE help!
<script type="text/javascript">
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(barDisassembly);
function barDisassembly() {
var data = google.visualization.arrayToDataTable([
['Categories', 'Disassembly Fee'],
['N-1701', 150000]
]);
var options = {
chart: {
width: 200,
height: 400,
legend: { position: 'top', maxLines: 3 },
vAxis: {
viewWindowMode:'explicit',
viewWindow:{
max:150000,
min:0
}
}
}
};
var bar = new google.visualization.ColumnChart(document.getElementById('bar_disassembly'));
bar.draw(data, options);
}
</script>
Remove chart from the options.
The only configuration options associated with chart are subtitle and title...
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(barDisassembly);
function barDisassembly() {
var data = google.visualization.arrayToDataTable([
['Categories', 'Disassembly Fee'],
['N-1701', 150000]
]);
var options = {
width: 400,
height: 400,
legend: {
position: 'top',
maxLines: 3
},
vAxis: {
viewWindow: {
max: 150000,
min: 0
}
}
};
var bar = new google.visualization.ColumnChart(document.getElementById('bar_disassembly'));
bar.draw(data, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="bar_disassembly"></div>