I found the following code online and would like to adapt it to my existing code.
Here's the code to show/hide data series on click I found:
http://jsfiddle.net/asgallant/6gz2Q/
Here's my Adaptation so far:
function drawChart() {
var data = new google.visualization.arrayToDataTable([
['Draw', '1997', '1998'],
['1', 1236777, 1408007],
['2', 834427, 572882],
['3', 2164890, 1614181],
['4', 1893574, 3897171],
['5', 2851881, 673906],
['6', 359504, 630853]
]);
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
// create columns array
var columns = [];
// display these data series by default
var defaultSeries = [1];
var series = {};
for (var i = 0; i < data.getNumberOfColumns(); i++) {
if (i == 0 || defaultSeries.indexOf(i) > -1) {
// if the column is the domain column or in the default list, display the series
columns.push(i);
}
else {
// otherwise, hide it
columns[i] = {
label: data.getColumnLabel(i),
type: data.getColumnType(i),
calc: function () {
return null;
}
};
}
if (i > 0) {
// set the default series option
series[i - 1] = {};
if (defaultSeries.indexOf(i) == -1) {
// backup the default color (if set)
if (typeof(series[i - 1].color) !== 'undefined') {
series[i - 1].backupColor = series[i - 1].color;
}
series[i - 1].color = '#CCCCCC';
}
}
}
// Options customize what goes inside our chart.
var options = {
fontName: 'verdana',
fontSize: 12,
// Curve the series line.
curveType: "function",
title: 'Title of Chart',
// disables tooltip on hover data points
enableInteractivity: true,
// Enable/Disable tooltip. selection or none.
tooltip: { trigger: 'none' },
// Select multiple Data points.
selectionMode: 'multiple',
// Customize vAxis ---------------------------------------------------------
vAxis: {
gridlines: {color: 'black', count: 5},
title: 'Title of vAxis',
// Affects only the Title. eg. Not title.
titleTextStyle: {fontName: 'verdana', fontSize: 10, color: 'black', bold: false, italic: false},
// Range of data for vAxis eg. min: 0, max:9
viewWindow: {min: 0, max: 5006386},
// Affects only the Range. eg. Not title.
textStyle: {fontName: 'verdana', fontSize: 12, color: 'black', bold: false, italic: false}
},
// Customize hAxis ---------------------------------------------------------
hAxis: {
title: 'Title of hAxis',
// Affects only the Title. eg. Not title.
titleTextStyle: {fontName: 'verdana', fontSize: 10, color: 'black', bold: false, italic: false},
// Affects only the Range. eg. Not title.
textStyle: {fontName: 'verdana', fontSize: 10, color: 'black', bold: false, italic: false}
},
// Customize Series ---------------------------------------------------------
series: {
0: {lineWidth: 1, pointSize: 4},
1: {lineWidth: 1, pointSize: 4},
2: {lineWidth: 1, pointSize: 4}
},
// Customize Annotations ---------------------------------------------------------
annotations: {
textStyle: {fontName: 'verdana', fontSize: 10, color: 'black', bold: false, italic: false, auraColor: 'none'}
},
// Custome Legends ---------------------------------------------------------
legend: {
// Position top, right, bottom, left.
position: 'top',
// Align at the star, center or end.
alignment: 'start',
// Affects only the Range. eg. Not title.
textStyle: {fontName: 'verdana', fontSize: 10, color: 'black', bold: false, italic: false}
}
}; // End Options
function showHideSeries () {
var sel = chart.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 (columns[col] == col) {
// hide the data series
columns[col] = {
label: data.getColumnLabel(col),
type: data.getColumnType(col),
calc: function () {
return null;
}
};
// grey out the legend entry
series[col - 1].color = '#CCCCCC';
}
else {
// show the data series
columns[col] = col;
series[col - 1].color = null;
}
var view = new google.visualization.DataView(data);
view.setColumns(columns);
chart.draw(view, options);
}
}
}
google.visualization.events.addListener(chart, 'select', showHideSeries);
// create a view with the default columns
var view = new google.visualization.DataView(data);
view.setColumns(columns);
chart.draw(view, options);
}
google.load('visualization', '1', {packages: ['corechart']});
google.setOnLoadCallback(drawChart);
...And here is what I really wanted to figure how to incorporate into this code. I can't seem to figure it out. It's driving me nuts!
// Declare our Columns and set types, roles, etc.
view.setColumns([
0,
1, { calc: "stringify", sourceColumn: 1, type: "string", role: "annotation" },
2, { calc: "stringify", sourceColumn: 2, type: "string", role: "annotation" },
3, { calc: "stringify", sourceColumn: 3, type: "string", role: "annotation" }
]);
Try replacing this section:
if (i == 0 || defaultSeries.indexOf(i) > -1) {
// if the column is the domain column or in the default list, display the series
columns.push(i);
}
with this:
if (i == 0 || defaultSeries.indexOf(i) > -1) {
// if the column is the domain column or in the default list, display the series
columns.push(i);
if (i > 0) {
columns.push({
calc: "stringify",
sourceColumn: i,
type: "string",
role: "annotation"
});
}
}
Here is asgallant solution which worked as desired.
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('number', 'x');
data.addColumn('number', 'y1');
data.addColumn('number', 'y2');
data.addColumn('number', 'y3');
// add random data
var y1 = 50, y2 = 50, y3 = 50;
for (var i = 0; i < 100; i++) {
y1 += Math.floor(Math.random() * 5) * Math.pow(-1, Math.floor(Math.random() * 2));
y2 += Math.floor(Math.random() * 5) * Math.pow(-1, Math.floor(Math.random() * 2));
y3 += Math.floor(Math.random() * 5) * Math.pow(-1, Math.floor(Math.random() * 2));
data.addRow([i, y1, y2, y3]);
}
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
// create columns array
var columns = [];
// display these data series by default
var defaultSeries = [1, 3];
var series = {};
for (var i = 0; i < data.getNumberOfColumns(); i++) {
if (i == 0 || defaultSeries.indexOf(i) > -1) {
// if the column is the domain column or in the default list, display the series
columns.push(i);
}
else {
// otherwise, hide it
columns.push({
label: data.getColumnLabel(i),
type: data.getColumnType(i),
sourceColumn: i,
calc: function () {
return null;
}
});
}
if (i > 0) {
columns.push({
calc: 'stringify',
sourceColumn: i,
type: 'string',
role: 'annotation'
});
// set the default series option
series[i - 1] = {};
if (defaultSeries.indexOf(i) == -1) {
// backup the default color (if set)
if (typeof(series[i - 1].color) !== 'undefined') {
series[i - 1].backupColor = series[i - 1].color;
}
series[i - 1].color = '#CCCCCC';
}
}
}
var options = {
width: 600,
height: 400,
series: series
}
function showHideSeries () {
var sel = chart.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[src - 1].color = '#CCCCCC';
}
else {
var src = columns[col].sourceColumn;
// show the data series
columns[col] = src;
series[src - 1].color = null;
}
var view = new google.visualization.DataView(data);
view.setColumns(columns);
chart.draw(view, options);
}
}
}
google.visualization.events.addListener(chart, 'select', showHideSeries);
// create a view with the default columns
var view = new google.visualization.DataView(data);
view.setColumns(columns);
chart.draw(view, options);
}
google.load('visualization', '1', {packages: ['corechart']});
google.setOnLoadCallback(drawChart);
Related
I'm creating a column chart in Google Charts, and I want to also create a table chart showing summary data based on the column values, viz. average, minimum, maximum, total.
I've declared these as global variables (initialised as 0) outside the drawchart function, and I've assigned values within the drawchart function (without var):
function drawPower() {
$.get("costs_daily.csv", function(csvString) {
// transform the CSV string into a 2-dimensional array
var arrayData = $.csv.toArrays(csvString, {onParseValue: $.csv.hooks.castToScalar});
// this new DataTable object holds all the data
var data = new google.visualization.arrayToDataTable(arrayData);
/// get min, max cost
var range = data.getColumnRange(3);
var n_rows = data.getNumberOfRows();
function getSum(data, row) {
var total = 0;
for (i = 0; i < n_rows; i++)
total = total + data.getValue(i, row);
return total;
}
totCost = getSum(data, 3);
aveCost = totCost / n_rows;
minCost = range.min;
maxCost = range.max;
var options = {
title: 'Costs for last 30 days',
titleTextStyle: {color: 'grey', fontSize: 16},
hAxis: {title: 'Date', titleTextStyle: {bold: false, italic: false, color: 'grey'}, slantedTextAngle: 90, textStyle: {fontSize: 12}},
legend: {position: 'top'},
vAxes: {
0: {title: 'Cost (p)', titleTextStyle: {bold: false, italic: false, color: 'grey'}},
},
focusTarget: 'category',
intervals: {color:'#000000',
textStyle: { color: 'none'}},
series: {
0: {color: '#44AA99', type: 'bars'},
1: {color: '#DDCC77', type: 'bars'},
2: {
color: 'transparent',
type: 'line',
lineWidth: 0,
pointSize: 0,
enableInteractivity: false,
visibleInLegend: false
}
},
interpolateNulls: true,
bar: { groupWidth: '75%' },
isStacked: true,
};
var formatter = new google.visualization.NumberFormat(
{prefix: '£', fractionDigits: 2}
);
formatter.format(data,1);
formatter.format(data,2);
formatter.format(data,3);
var chart = new google.visualization.ComboChart(document.getElementById('power_div'));
chart.draw(data, options);
},'text');
}
I've then created a separate function to draw a table with these values:
function drawTable() {
statsData = [
['Stat', 'Cost'],
['Average', aveCost],
['Minimum', minCost],
['Maximum', maxCost],
['Total', totCost]
];
var stats = new google.visualization.arrayToDataTable(statsData);
var options = {
showRowNumber: false,
width: '100%',
height: '100%'
};
var formatter = new google.visualization.NumberFormat(
{prefix: '£', fractionDigits: 2}
);
formatter.format(stats,1);
var table = new google.visualization.Table(document.getElementById('table_div'));
table.draw(stats, options);
}
but the values remain at their initialised values (zero). Is there a way to pass the calculated values from the chart function to the table function?
not sure where drawTable is called from now,
but yes, you can pass the values from the chart function to the table function.
create the statsData in the chart function,
then pass it to the table function.
and remove where ever the table function is currently being called.
totCost = getSum(data, 3);
aveCost = totCost / n_rows;
minCost = range.min;
maxCost = range.max;
statsData = [
['Stat', 'Cost'],
['Average', aveCost],
['Minimum', minCost],
['Maximum', maxCost],
['Total', totCost]
];
drawTable(statsData);
...
function drawTable(statsData) {
...
see following snippet...
function drawPower() {
$.get("costs_daily.csv", function(csvString) {
// transform the CSV string into a 2-dimensional array
var arrayData = $.csv.toArrays(csvString, {onParseValue: $.csv.hooks.castToScalar});
// this new DataTable object holds all the data
var data = new google.visualization.arrayToDataTable(arrayData);
/// get min, max cost
var range = data.getColumnRange(3);
var n_rows = data.getNumberOfRows();
function getSum(data, row) {
var total = 0;
for (i = 0; i < n_rows; i++)
total = total + data.getValue(i, row);
return total;
}
totCost = getSum(data, 3);
aveCost = totCost / n_rows;
minCost = range.min;
maxCost = range.max;
statsData = [
['Stat', 'Cost'],
['Average', aveCost],
['Minimum', minCost],
['Maximum', maxCost],
['Total', totCost]
];
drawTable(statsData);
var options = {
title: 'Costs for last 30 days',
titleTextStyle: {color: 'grey', fontSize: 16},
hAxis: {title: 'Date', titleTextStyle: {bold: false, italic: false, color: 'grey'}, slantedTextAngle: 90, textStyle: {fontSize: 12}},
legend: {position: 'top'},
vAxes: {
0: {title: 'Cost (p)', titleTextStyle: {bold: false, italic: false, color: 'grey'}},
},
focusTarget: 'category',
intervals: {color:'#000000',
textStyle: { color: 'none'}},
series: {
0: {color: '#44AA99', type: 'bars'},
1: {color: '#DDCC77', type: 'bars'},
2: {
color: 'transparent',
type: 'line',
lineWidth: 0,
pointSize: 0,
enableInteractivity: false,
visibleInLegend: false
}
},
interpolateNulls: true,
bar: { groupWidth: '75%' },
isStacked: true,
};
var formatter = new google.visualization.NumberFormat(
{prefix: '£', fractionDigits: 2}
);
formatter.format(data,1);
formatter.format(data,2);
formatter.format(data,3);
var chart = new google.visualization.ComboChart(document.getElementById('power_div'));
chart.draw(data, options);
},'text');
}
function drawTable(statsData) {
var stats = new google.visualization.arrayToDataTable(statsData);
var options = {
showRowNumber: false,
width: '100%',
height: '100%'
};
var formatter = new google.visualization.NumberFormat(
{prefix: '£', fractionDigits: 2}
);
formatter.format(stats,1);
var table = new google.visualization.Table(document.getElementById('table_div'));
table.draw(stats, options);
}
I am using Google Charts (Google Visualization), it was working fine . But now, I am facing a weird problem in animation. It is a stacked bar chart. First two columns (bars) is animating flawlessly but third column (bar) is coming at once, animation is not working for the last bar (third column).
I have tried with total 2 bars and now 2nd bar's animation is not working (came at once). It is clear that problem is in last bar. Is it a flaw in stacked bar chart from Google Chart's end?
Here is my code:
var data = google.visualization.arrayToDataTable([
['Status', awating, not_interested, interested, { role: 'annotation' }],
['SANDRA COOMBS', 2, 4, 2, ''],
['VINCENT ODA', 2, 2, 2, ''],
]);
arTotal = niTotal = iTotal = 0;
for (var i = 0; i < data.getNumberOfRows(); i++) {
if (data.getValue(i, 1) != null) {
arTotal += data.getValue(i, 1);
}
if (data.getValue(i, 2) != null) {
niTotal += data.getValue(i, 2);
}
if (data.getValue(i, 3) != null) {
iTotal += data.getValue(i, 3);
}
}
var view = new google.visualization.DataView(data);
view.setColumns([0, 1,
{
calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation"
},
2, {
calc: "stringify",
sourceColumn: 2,
type: "string",
role: "annotation"
},
3, {
calc: "stringify",
sourceColumn: 3,
type: "string",
role: "annotation"
}]);
var options = {
legend: {
position: 'none'
},
chartArea: { width: width, height: height, right: right },
isStacked: true,
orientation: orientation.orientation,
colors: ['#008FBE', '#BE1E2D', '#00BD90'],
fontSize: '12',
fontName: 'OpenSans-Regular',
hAxis: {
viewWindowMode: 'maximized',
},
vAxis: {
viewWindowMode: 'maximized',
},
animation: {
startup: true,
duration: 1500,
easing: 'out',
},
};
var chart = new google.visualization.ColumnChart(document.getElementById("currentStatusChart"));
google.visualization.events.addListener(chart, 'ready', readyHandler);
chart.draw(view, options);
i've encountered various bugs when using animation on startup,
specifically when a DataView is used to draw the chart
a workaround is to convert the DataView into a DataTable before drawing the chart,
you can use method --> toDataTable()
view.toDataTable()
which does seem to help in this situation,
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
['Status', 'awating', 'not_interested', 'interested', { role: 'annotation' }],
['SANDRA COOMBS', 2, 4, 2, ''],
['VINCENT ODA', 2, 2, 2, ''],
]);
arTotal = niTotal = iTotal = 0;
for (var i = 0; i < data.getNumberOfRows(); i++) {
if (data.getValue(i, 1) != null) {
arTotal += data.getValue(i, 1);
}
if (data.getValue(i, 2) != null) {
niTotal += data.getValue(i, 2);
}
if (data.getValue(i, 3) != null) {
iTotal += data.getValue(i, 3);
}
}
var view = new google.visualization.DataView(data);
view.setColumns([0, 1,
{
calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation"
},
2, {
calc: "stringify",
sourceColumn: 2,
type: "string",
role: "annotation"
},
3, {
calc: "stringify",
sourceColumn: 3,
type: "string",
role: "annotation"
}]);
var options = {
legend: {
position: 'none'
},
//chartArea: { width: width, height: height, right: right },
isStacked: true,
//orientation: orientation.orientation,
colors: ['#008FBE', '#BE1E2D', '#00BD90'],
fontSize: '12',
fontName: 'OpenSans-Regular',
hAxis: {
viewWindowMode: 'maximized',
},
vAxis: {
viewWindowMode: 'maximized',
},
animation: {
startup: true,
duration: 1500,
easing: 'out',
},
};
var chart = new google.visualization.ColumnChart(document.getElementById("currentStatusChart"));
chart.draw(view.toDataTable(), options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="currentStatusChart"></div>
how can I highlight a single grid line? I would like to set an optical temperature limit at 35 ° C.
Thanks! I have now added it to my code, but it does not work .... do you see my mistake? Or did I not understand something in your explanation?
Here is the edited version :
//Google Chart
google.charts.load('current', {
callback: function drawChart(peanut) {
const div = document.createElement('div');
div.id = peanut.color + peanut.mac.split(':').join('');
$('#charts').appendChild(div);
peanut.data = new google.visualization.DataTable();
peanut.data.addColumn('datetime', 'Time');
peanut.data.addColumn('number', '🥜 ' + peanut.label);
for (var i = 0, len = localStorage.length; i < len; i++) {
let dateTime = new Date(parseInt(localStorage.key(i)));
let item = JSON.parse(localStorage.getItem(localStorage.key(i)));
if (item.peanutMac === peanut.mac) {
if (item.temperatureCelsius) {
let temperature = parseFloat(item.temperatureCelsius);
peanut.data.addRows([ [dateTime, temperature] ]);
} else if (item.alert) {
let data = parseInt(item.alert);
peanut.data.addRows([ [dateTime, data] ]);
}
}
}
if (peanut.type == 'thermo') {
peanut.chart = new google.visualization.LineChart($('#' + div.id));
peanut.chartOptions = {
interpolateNulls: true,
fontName: 'Roboto',
curveType: 'function',
colors: [peanut.rgbColor],
width: document.body.clientWidth,
height: (window.innerHeight - 224) / 2,
legend: 'none',
lineWidth: 3,
vAxis: {
format: '#.## °C',
ticks: [15.00, 20.00, 25.00, 30.00, 35.00, 40.00]
},
hAxis: {
gridlines: {
color: '#fff'
}
}
};
peanut.viewColumns = [];
$.each(new Array(data.getNumberOfColumns()), function (colIndex) {
peanut.viewColumns.push(colIndex);
});
peanut.viewColumns.push({
calc: function () {
return 35;
},
label: 'optical temperature limit',
type: 'number'
});
}
peanut.view = new google.visualiation.DataView(data);
peanut.view.setColumns(viewColumns);
if (peanut.data.getNumberOfRows()) {
peanut.chart.draw(peanut.view, peanut.chartOptions);
}
}
packages:['corechart', 'table']
});
add another series with the value set to 35 for all rows
here, a data view is used to add a calculated column for the optical temperature limit
google.charts.load('current', {
callback: function () {
var data = new google.visualization.DataTable();
data.addColumn('number', 'x');
data.addColumn('number', 'y0');
data.addColumn('number', 'y1');
data.addColumn('number', 'y2');
data.addRows([
[1, 32.8, 20.8, 21.8],
[2, 30.9, 29.5, 32.4],
[3, 25.4, 27, 25.7],
[4, 21.7, 28.8, 20.5],
[5, 21.9, 27.6, 20.4]
]);
var options = {
interpolateNulls: true,
fontName: 'Roboto',
curveType: 'function',
legend: 'none',
lineWidth: 3,
vAxis: {
format: '#.## °C',
ticks: [20.00, 25.00, 30.00, 35.00, 40.00]
},
hAxis: {
gridlines: {
color: '#fff'
}
}
};
var viewColumns = [];
$.each(new Array(data.getNumberOfColumns()), function (colIndex) {
viewColumns.push(colIndex);
});
viewColumns.push({
calc: function () {
return 35;
},
label: 'optical temperature limit',
type: 'number'
});
var view = new google.visualization.DataView(data);
view.setColumns(viewColumns);
var chart = new google.visualization.LineChart($('#chart').get(0));
chart.draw(view, options);
},
packages:['corechart', 'table']
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart"></div>
Its not the best and safest way but I didnt find something on the google documentation:
You could use Jquery for it Ive tried it on the example from google docs and it works click
var line = $("svg g line")[4]
$(line).attr('stroke','red');
A simple way is to set the vAxis baseline to the value you want, say 35, and change the baselineColor. There is no option to change the width of this line, however, so if you need that, you should follow the suggestion above to add a series just to draw this line, and set its lineWidth.
I have a Google combo chart that has one value as bars and one value for a line, I also wanted a line to show the average of the value of the bars, so I found code that would do that, however, when implemented my other line disappeared.
This is what my chart looked like prior.
And this is after I implemented the average line, my other line disappeared.
I don't know how to do to make them both show?
This line seems to have things to do with all of it, changing dv back to data will show how my chart looked like on the first picture, but I guess there is something more I need to change to make it all work?
chart.draw(dv, options);
Here is the code.
<script>
google.charts.load('current', {
'packages': ['corechart']
});
google.charts.setOnLoadCallback(drawVisualization);
function drawVisualization() {
var data = google.visualization.arrayToDataTable([
['Day', 'Repetitions', 'Sets'],
#foreach (var c in db.Query(Query, inputDate, endDate, baselift))
{
var totAvg = c.avg;
var allReps = c.reps;
var realAvg = (totAvg / allReps) * 100;
//Writes out the data that will be shown in the chart.
<text>['#c.date', #c.reps, #c.sets],</text>
}
]);
// Create a DataView that adds another column which is all the same (empty-string) to be able to aggregate on.
var viewWithKey = new google.visualization.DataView(data);
viewWithKey.setColumns([0, 1, {
type: 'string',
label: '',
calc: function (d, r) {
return ''
}
}])
// Aggregate the previous view to calculate the average. This table should be a single table that looks like:
// [['', AVERAGE]], so you can get the Average with .getValue(0,1)
var group = google.visualization.data.group(viewWithKey, [2], [{
column: 1,
id: 'avg',
label: 'Average',
aggregation: google.visualization.data.avg,
'type': 'number'
}]);
// Create a DataView where the third column is the average.
var dv = new google.visualization.DataView(data);
dv.setColumns([0, 1, {
type: 'number',
label: 'Average',
calc: function (dt, row) {
return group.getValue(0, 1);
}
}]);
var options = {
title: 'Daily Repetition Statistics',
backgroundColor: { fill: 'transparent' },
explorer: { axis: 'horizontal' },
vAxes: {
0: { logScale: false, viewWindow: { min: 0 } },
1: { logScale: false, maxValue: 2 }
},
hAxis: { title: 'Day' },
seriesType: 'bars',
curveType: 'function',
series: {
0: {
targetAxisIndex: 0,
color: 'orange'
},
1: { targetAxisIndex: 1 },
1: { targetAxisIndex: 1, type: "line" },
2: { targetAxisIndex: 1, type: "line" }
}
};
var chart = new google.visualization.ComboChart(document.getElementById('chart_div'));
chart.draw(dv, options);
}
</script>
the column index for 'sets' is not provided to setColumns
change this...
var dv = new google.visualization.DataView(data);
dv.setColumns([0, 1, {
type: 'number',
label: 'Average',
calc: function (dt, row) {
return group.getValue(0, 1);
}
}]);
to..
var dv = new google.visualization.DataView(data);
dv.setColumns([0, 1, 2, { // <-- add 'sets' column index 2
type: 'number',
label: 'Average',
calc: function (dt, row) {
return group.getValue(0, 1);
}
}]);
i'm trying to use Google Chart API for building an Waterfall chart. I noticed that Candlestick/Waterfall charts are not supporting the annotations.
See this jsfiddle sample
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Category');
data.addColumn('number', 'MinimumLevel');
data.addColumn('number', 'MinimumLevel1');
data.addColumn('number', 'MaximumLevel');
data.addColumn('number', 'MaximumLevel1');
data.addColumn({type: 'number', role: 'tooltip'});
data.addColumn({type: 'string', role: 'style'});
data.addColumn({type: 'number', role: 'annotation'});
data.addRow(['Category 1', 0 , 0, 5, 5, 5,'gray',5]);
data.addRow(['Category 2', 5 , 5, 10, 10, 10,'red',10]);
data.addRow(['Category 3', 10 , 10, 15, 15, 15,'blue',15]);
data.addRow(['Category 4', 15 , 15, 10, 10, 10,'yellow',10]);
data.addRow(['Category 5', 10 , 10, 5, 5, 5,'gray',5]);
var options = {
legend: 'none',
bar: { groupWidth: '60%' } // Remove space between bars.
};
var chart = new google.visualization.CandlestickChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
I would like to put the value of the 5th column at the top of every candlestick.
It should look like this :
Is there a way to do this?
Thanks
I add annotations to candlestick charts by adding annotations to a hidden scatter plot. You can set exactly where you want the annotations to sit by changing the plot.
google.charts.load('current', { 'packages': ['corechart'] });
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Low');
data.addColumn('number', 'Open');
data.addColumn('number', 'Close');
data.addColumn('number', 'High');
data.addColumn('number'); //scatter plot for annotations
data.addColumn({ type: 'string', role: 'annotation' }); // annotation role col.
data.addColumn({ type: 'string', role: 'annotationText' }); // annotationText col.
var high, low, open, close = 160;
for (var i = 0; i < 10; i++) {
open = close;
close += ~~(Math.random() * 10) * Math.pow(-1, ~~(Math.random() * 2));
high = Math.max(open, close) + ~~(Math.random() * 10);
low = Math.min(open, close) - ~~(Math.random() * 10);
annotation = '$' + close;
annotation_text = 'Close price: $' + close;
data.addRow([new Date(2014, 0, i + 1), low, open, close, high, high, annotation, annotation_text]);
}
var view = new google.visualization.DataView(data);
var chart = new google.visualization.ComboChart(document.querySelector('#chart_div'));
chart.draw(view, {
height: 400,
width: 600,
explorer: {},
chartArea: {
left: '7%',
width: '70%'
},
series: {
0: {
color: 'black',
type: 'candlesticks',
},
1: {
type: 'scatter',
pointSize: 0,
targetAxisIndex: 0,
},
},
candlestick: {
color: '#a52714',
fallingColor: { strokeWidth: 0, fill: '#a52714' }, // red
risingColor: { strokeWidth: 0, fill: '#0f9d58' } // green
},
});
}
<script type="text/javascript"src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div" style="width: 900px; height: 500px;"></div>
just so happens, i ran into the same problem this week
so I added my own annotations, during the 'animationfinish' event
see following working snippet...
google.charts.load('current', {
callback: drawChart,
packages:['corechart']
});
function drawChart() {
var dataChart = new google.visualization.DataTable({"cols":[{"label":"Category","type":"string"},{"label":"Bottom 1","type":"number"},{"label":"Bottom 2","type":"number"},{"label":"Top 1","type":"number"},{"label":"Top 2","type":"number"},{"role":"style","type":"string","p":{"role":"style"}}],"rows":[{"c":[{"v":"Budget"},{"v":0},{"v":0},{"v":22707893.613},{"v":22707893.613},{"v":"#007fff"}]},{"c":[{"v":"Contract Labor"},{"v":22707893.613},{"v":22707893.613},{"v":22534350.429},{"v":22534350.429},{"v":"#1e8449"}]},{"c":[{"v":"Contract Non Labor"},{"v":22534350.429},{"v":22534350.429},{"v":22930956.493},{"v":22930956.493},{"v":"#922b21"}]},{"c":[{"v":"Materials and Equipment"},{"v":22930956.493},{"v":22930956.493},{"v":22800059.612},{"v":22800059.612},{"v":"#1e8449"}]},{"c":[{"v":"Other"},{"v":22800059.612},{"v":22800059.612},{"v":21993391.103},{"v":21993391.103},{"v":"#1e8449"}]},{"c":[{"v":"Labor"},{"v":21993391.103},{"v":21993391.103},{"v":21546003.177999996},{"v":21546003.177999996},{"v":"#1e8449"}]},{"c":[{"v":"Travel"},{"v":21546003.177999996},{"v":21546003.177999996},{"v":21533258.930999994},{"v":21533258.930999994},{"v":"#1e8449"}]},{"c":[{"v":"Training"},{"v":21533258.930999994},{"v":21533258.930999994},{"v":21550964.529999994},{"v":21550964.529999994},{"v":"#922b21"}]},{"c":[{"v":"Actual"},{"v":0},{"v":0},{"v":21550964.52999999},{"v":21550964.52999999},{"v":"#007fff"}]}]});
var waterFallChart = new google.visualization.ChartWrapper({
chartType: 'CandlestickChart',
containerId: 'chart_div',
dataTable: dataChart,
options: {
animation: {
duration: 1500,
easing: 'inAndOut',
startup: true
},
backgroundColor: 'transparent',
bar: {
groupWidth: '85%'
},
chartArea: {
backgroundColor: 'transparent',
height: 210,
left: 60,
top: 24,
width: '100%'
},
hAxis: {
slantedText: false,
textStyle: {
color: '#616161',
fontSize: 9
}
},
height: 272,
legend: 'none',
tooltip: {
isHtml: true,
trigger: 'both'
},
vAxis: {
format: 'short',
gridlines: {
count: -1
},
textStyle: {
color: '#616161'
},
viewWindow: {
max: 24000000,
min: 16000000
}
},
width: '100%'
}
});
google.visualization.events.addOneTimeListener(waterFallChart, 'ready', function () {
google.visualization.events.addListener(waterFallChart.getChart(), 'animationfinish', function () {
var annotation;
var chartLayout;
var container;
var numberFormatShort;
var positionY;
var positionX;
var rowBalance;
var rowBottom;
var rowFormattedValue;
var rowIndex;
var rowTop;
var rowValue;
var rowWidth;
container = document.getElementById(waterFallChart.getContainerId());
chartLayout = waterFallChart.getChart().getChartLayoutInterface();
numberFormatShort = new google.visualization.NumberFormat({
pattern: 'short'
});
rowIndex = 0;
Array.prototype.forEach.call(container.getElementsByTagName('rect'), function(rect) {
switch (rect.getAttribute('fill')) {
// use colors to identify bars
case '#922b21':
case '#1e8449':
case '#007fff':
rowWidth = parseFloat(rect.getAttribute('width'));
if (rowWidth > 2) {
rowBottom = waterFallChart.getDataTable().getValue(rowIndex, 1);
rowTop = waterFallChart.getDataTable().getValue(rowIndex, 3);
rowValue = rowTop - rowBottom;
rowBalance = Math.max(rowBottom, rowTop);
positionY = chartLayout.getYLocation(rowBalance) - 6;
positionX = parseFloat(rect.getAttribute('x'));
rowFormattedValue = numberFormatShort.formatValue(rowValue);
if (rowValue < 0) {
rowFormattedValue = rowFormattedValue.replace('-', '');
rowFormattedValue = '(' + rowFormattedValue + ')';
}
annotation = container.getElementsByTagName('svg')[0].appendChild(container.getElementsByTagName('text')[0].cloneNode(true));
$(annotation).text(rowFormattedValue);
annotation.setAttribute('x', (positionX + (rowWidth / 2)));
annotation.setAttribute('y', positionY);
annotation.setAttribute('font-weight', 'bold');
rowIndex++;
}
break;
}
});
});
});
$(window).resize(function() {
waterFallChart.draw();
});
waterFallChart.draw();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>