I can't figure out why, I've triple checked that I'm passing in the right values. When I hover over any of the bars it displays the right data, but every single one of them displays at 10x scale on the graph and I can't figure out why. Here's my code if it helps:
var dashboard2 = new google.visualization.Dashboard(
document.getElementById('dashboard'));
var control2 = new google.visualization.ControlWrapper({
'controlType': 'ChartRangeFilter',
'containerId': 'control2',
'options': {
// Filter by the date axis.
'filterColumnIndex': 0,
'ui': {
'chartType': 'LineChart',
'chartOptions': {
'chartArea': {'width': '80%'},
'hAxis': {'baselineColor': 'none'}
},
// Display a single series that shows the closing value of the stock.
// Thus, this view has two columns: the date (axis) and the stock value (line series).
'chartView': {
'columns': [0, 1, 14]
},
// 1 day in milliseconds = 24 * 60 * 60 * 1000 = 86,400,000
'minRangeSize': 259200000
}
},
// Initial range: 2012-02-09 to 2012-03-20.
'state': {'range': {'start': new Date(2012, 11, 7), 'end': new Date()}}
});
var chart2 = new google.visualization.ChartWrapper({
'chartType': 'ComboChart',
'containerId': 'chart2',
'options': {
// Use the same chart area width as the control for axis alignment.
'chartArea': {'height': '80%', 'width': '80%'},
'hAxis': {'slantedText': false},
'vAxis': {'viewWindow': {'min': 0, 'max': 400}},
'title': 'Sales Made by Affiliate Name',
'seriesType': "bars",
'series': {0: {type: "line"}, 13: {type: "line"}},
'isStacked': true
},
// Convert the first column from 'date' to 'string'.
'view': {
'columns': [
{
'calc': function(dataTable, rowIndex) {
return dataTable.getFormattedValue(rowIndex, 0);
},
'type': 'string'
}, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
}
});
var jsonData2 = $.ajax({
url: "getData.php",
dataType:"json",
async: false
}).responseText;
// Create our data table out of JSON data loaded from server
var data2 = new google.visualization.DataTable(jsonData2);
dashboard2.bind(control2, chart2);
dashboard2.draw(data2);
Edit: Here's a small bit of the data at the very beginning, because I don't want to give out our data, but I suppose it might be necessary to get an idea for what is being passed in. I cut out the starting bracket for readability:
"cols":[ {"id":"","label":"Date","pattern":"","type":"date"}, {"id":"","label":"Total","pattern":"","type":"number"}, {"id":"","label":"andersce99","pattern":"","type":"number"}, {"id":"","label":"sojourn","pattern":"","type":"number"}, {"id":"","label":"warriorplus","pattern":"","type":"number"}, {"id":"","label":"potpie queen","pattern":"","type":"number"}, {"id":"","label":"60minuteaffiliate","pattern":"","type":"number"}, {"id":"","label":"bob voges","pattern":"","type":"number"}, {"id":"","label":"Grayth","pattern":"","type":"number"}, {"id":"","label":"TiffanyDow","pattern":"","type":"number"}, {"id":"","label":"AmandaT","pattern":"","type":"number"}, {"id":"","label":"Gaz Cooper","pattern":"","type":"number"}, {"id":"","label":"Sam England","pattern":"","type":"number"}, {"id":"","label":"Matthew Olson","pattern":"","type":"number"}, {"id":"","label":"Average Per Day Over Time","pattern":"","type":"number"} ],
"rows": [ {"c":[{"v":"Date(2012,11,7)","f":null},{"v":"387","f":null},{"v":"19","f":null},{"v":"275","f":null},{"v":"8","f":null},{"v":"0","f":null},{"v":"35","f":null},{"v":"3","f":null},{"v":"21","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"11","f":null},{"v":"6","f":null},{"v":"387","f":null}]},
{"c":[{"v":"Date(2012,11,8)","f":null},{"v":"98","f":null},{"v":"11","f":null},{"v":"39","f":null},{"v":"1","f":null},{"v":"0","f":null},{"v":"15","f":null},{"v":"0","f":null},{"v":"7","f":null},{"v":"9","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"3","f":null},{"v":"6","f":null},{"v":"242.5","f":null}]},
{"c":[{"v":"Date(2012,11,9)","f":null},{"v":"58","f":null},{"v":"7","f":null},{"v":"16","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"4","f":null},{"v":"0","f":null},{"v":"3","f":null},{"v":"10","f":null},{"v":"2","f":null},{"v":"9","f":null},{"v":"0","f":null},{"v":"2","f":null},{"v":"181","f":null}]},
{"c":[{"v":"Date(2012,11,10)","f":null},{"v":"196","f":null},{"v":"5","f":null},{"v":"8","f":null},{"v":"126","f":null},{"v":"0","f":null},{"v":"2","f":null},{"v":"35","f":null},{"v":"0","f":null},{"v":"7","f":null},{"v":"4","f":null},{"v":"3","f":null},{"v":"1","f":null},{"v":"0","f":null},{"v":"184.75","f":null}]},
{"c":[{"v":"Date(2012,11,11)","f":null},{"v":"76","f":null},{"v":"7","f":null},{"v":"5","f":null},{"v":"17","f":null},{"v":"30","f":null},{"v":"7","f":null},{"v":"1","f":null},{"v":"1","f":null},{"v":"2","f":null},{"v":"1","f":null},{"v":"4","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"163","f":null}]},
{"c":[{"v":"Date(2012,11,12)","f":null},{"v":"48","f":null},{"v":"4","f":null},{"v":"5","f":null},{"v":"9","f":null},{"v":"20","f":null},{"v":"7","f":null},{"v":"1","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"143.833333333","f":null}]},
{"c":[{"v":"Date(2012,11,13)","f":null},{"v":"21","f":null},{"v":"3","f":null},{"v":"2","f":null},{"v":"5","f":null},{"v":"4","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"1","f":null},{"v":"2","f":null},{"v":"0","f":null},{"v":"1","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"126.285714286","f":null}]},
{"c":[{"v":"Date(2012,11,14)","f":null},{"v":"12","f":null},{"v":"1","f":null},{"v":"1","f":null},{"v":"2","f":null},{"v":"4","f":null},{"v":"2","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"112","f":null}]},
{"c":[{"v":"Date(2012,11,15)","f":null},{"v":"8","f":null},{"v":"3","f":null},{"v":"0","f":null},{"v":"1","f":null},{"v":"2","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"1","f":null},{"v":"0","f":null},{"v":"1","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"0","f":null},{"v":"100.444444444","f":null}]}
Your data is formatted incorrectly: numbers need to be stored as numbers in the JSON, not as strings. As an example, this:
{"v":"387","f":null}
should be like this:
{"v":387,"f":null}
If you are using PHP's json_encode function to build the JSON, you can add JSON_NUMERIC_CHECK as an argument to the function call to output the numbers properly:
json_encode($myData, JSON_NUMERIC_CHECK);
Related
I have been having a lot of issues with coloring individual elements of a google visualization timeline object. I have tried ordering my colors[] object different ways, but it seems the current google visualization library processes the colors based on a horizontal-first approach to parsing the dates, but as I never know exactly how the dates will get arranged in the timeline, I cannot predict the color ordering.
I found a decent example of this in a previous post on Stack Overflow 23268616. The JSFiddle referenced on that page doesn't actually work for me (using Chrome 49.0.2623.87) with the current Google Visualization package. I also tried Firefox and get the same incorrect results.
Fiddle replicated here for reference:
function drawChart() {
var container = document.getElementById('example4.2');
var chart = new google.visualization.Timeline(container);
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'string', id: 'Group' });
dataTable.addColumn({ type: 'string', id: 'Category' });
dataTable.addColumn({ type: 'string', id: 'ID' });
dataTable.addColumn({ type: 'date', id: 'Start' });
dataTable.addColumn({ type: 'date', id: 'End' });
dataTable.addRows([
[ 'GROUP #1', 'CategoryA', 'C00001', new Date(2014, 0, 1), new Date(2014, 0, 31) ],
[ 'GROUP #1', 'CategoryA', 'C00002', new Date(2014, 1, 1), new Date(2014, 1, 28) ],
[ 'GROUP #1', 'CategoryA', 'C00003', new Date(2014, 3, 1), new Date(2014, 3, 15) ],
[ 'GROUP #1', 'CategoryB', 'C00003', new Date(2014, 0, 21), new Date(2014, 2, 19) ],
[ 'GROUP #1', 'CategoryA', 'C00004', new Date(2014, 0, 1), new Date(2014, 0, 15) ],
[ 'GROUP #2', 'CategoryC', 'C00005', new Date(2014, 2, 8), new Date(2014, 2, 15) ],
[ 'GROUP #3', 'CategoryC', 'C00006', new Date(2014, 5, 1), new Date(2014, 5, 15) ],
[ 'GROUP #4', 'CategoryA', 'C00007', new Date(2014, 1, 15), new Date(2014, 1, 25) ]
]);
var colors = [];
var colorMap = {
// should contain a map of category -> color for every category
CategoryA: '#e63b6f',
CategoryB: '#19c362',
CategoryC: '#592df7'
}
for (var i = 0; i < dataTable.getNumberOfRows(); i++) {
colors.push(colorMap[dataTable.getValue(i, 1)]);
}
var rowHeight = 41;
var chartHeight = (dataTable.getNumberOfRows() + 1) * rowHeight;
var options = {
timeline: {
groupByRowLabel: true,
rowLabelStyle: {
fontName: 'Roboto Condensed',
fontSize: 14,
color: '#333333'
},
barLabelStyle: {
fontName: 'Roboto Condensed',
fontSize: 14
}
},
avoidOverlappingGridLines: true,
height: chartHeight,
width: '100%',
colors: colors
};
// use a DataView to hide the category column from the Timeline
var view = new google.visualization.DataView(dataTable);
view.setColumns([0, 2, 3, 4]);
chart.draw(view, options);
}
google.load('visualization', '1', {packages:['timeline'], callback: drawChart});
<script src="http://www.google.com/jsapi?.js"></script>
<div id='example4.2'></div>
For example, in this code, according to the colormap, line C00004 is supposed to be category A, but in my browser it is colored like category B! C0007 is supposed to be category A as well, but is category C In color! I cannot even figure out the pattern which is coloring the objects the way it is. Re-arranging the addRows([]) list leads to more crazy results... is this feature of Google Visualization just plain broken?
I have also tried referencing the library via https://www.gstatic.com/charts.loader.js but get the same results.
The following works fine (see jsfiddle) except when the table is filtered via one of the control wrappers. It seems that currentRow and rowIndex always have the same number e.g. google.visualization.DataView#getTableRowIndex(currentRow) doesn't do any translation; it simply spits out the same number that's passed in. How must the row index be properly translated so that one can obtain the desired row from the underlying google.visualization.DataTable?
function drawChart()
{
var dataTable = new google.visualization.DataTable();
dataTable.addColumn('date', 'Request Date');
dataTable.addColumn('string', 'To Do');
dataTable.addColumn('date', 'Target Complete Date');
dataTable.addColumn('number', 'Duration');
dataTable.addColumn('date', 'Date Completed');
dataTable.addColumn('number', 'ID');
dataTable.addRow([
new Date(2014, 1, 24),
'To do item 1',
new Date(2014, 1, 27),
3.5,
new Date(2014, 1, 26),
1000
]);
dataTable.addRow([
new Date(2014, 2, 24),
'To do item 2',
new Date(2014, 2, 27),
1.5,
new Date(2014, 2, 26),
1001
]);
dataTable.addRow([
new Date(2014, 3, 24),
'To do item 3',
new Date(2014, 3, 27),
7.5,
new Date(2014, 3, 26),
1002
]);
dataTable.addRow([
new Date(2014, 4, 24),
'To do item 4',
new Date(2014, 4, 27),
4.5,
new Date(2014, 4, 26),
1003
]);
dataTable.addRow([
new Date(2014, 5, 24),
'To do item 5',
new Date(2014, 5, 27),
2.5,
new Date(2014, 5, 26),
1004
]);
// Format the duration column so that it shows two decimal places.
var durationFormatter = new google.visualization.NumberFormat({ 'fractionDigits': 2 });
durationFormatter.format(dataTable, 3); // Apply formatter to duration column
// Table chart
var cssClassNames = {
'headerRow': 'dataHeaderRow',
'tableRow': 'dataTableRow',
'oddTableRow': 'dataOddTableRow',
'selectedTableRow': 'dataSelectedTableRow',
'hoverTableRow': 'dataHoverTableRow',
'headerCell': 'dataHeaderCell',
'tableCell': 'dataTableCell',
'rowNumberCell': 'dataRowNumberCell'
};
var tableChartOptions = {
'cssClassNames': cssClassNames,
'alternatingRowStyle': true,
'page': 'enable',
'pageSize': 10,
'pagingSymbols': {
prev: '<span class="fa fa-arrow-left"></span>',
next: '<span class="fa fa-arrow-right"></span>'
},
'pagingButtonsConfiguration': 'auto',
'sort': 'enable',
'sortAscending': true,
'sortColumn': 0, // <-- Initially sort by column 0: date column.
'title': 'Completed To Do List',
'width': '100%'
};
// Prevent the database ID (column 5 in underlying data table) from being
// displayed via a data view.
var rawDataView_NoID = new google.visualization.DataView(dataTable);
rawDataView_NoID.setColumns([0, 1, 2, 3, 4]);
var chartWrapper = new google.visualization.ChartWrapper({
'chartType': 'Table', // <-- google.visualization.Table
'containerId': 'loggedInCompletedToDoChart_div',
'options': tableChartOptions
} );
// The chart must be ready before the select listener can be created.
google.visualization.events.addListener(
chartWrapper,
'ready',
function () {
var visualization_table = chartWrapper.getChart(); // <-- google.visualization.Table
google.visualization.events.addListener(
visualization_table,
'select',
function () {
// Chart wrapper in this case is configured to allow only
// a single row selection. Hence, an array of length 1.
var selection = visualization_table.getSelection()[0];
var currentRow, rowIndex, duration, entryId;
if (selection !== undefined) {
currentRow = selection.row;
rowIndex = chartWrapper.getDataTable().getTableRowIndex(currentRow);
duration = dataTable.getFormattedValue(rowIndex, 3);
// entryId is available in underlying data table -- not in data view.
entryId = dataTable.getFormattedValue(rowIndex, 5);
alert(entryId); // Only correct when no filtering takes place.
}
}
);});
// Define Filter controls
var toDoFilter = new google.visualization.ControlWrapper({
'controlType': 'StringFilter',
'containerId': 'loggedInCompletedToDo_ToDo_SearchInputElement_div',
'options': {
'filterColumnLabel': 'To Do',
'matchType': 'any'
}});
var durationFilter = new google.visualization.ControlWrapper({
'controlType': 'NumberRangeFilter',
'containerId': 'loggedInCompletedToDo_Duration_SearchInputElement_div',
'options': {
'filterColumnLabel': 'Duration',
'ui': {
'format': { 'fractionDigits': 2 },
'step': 0.25
}
} } );
// Create the dashboard.
var dashboard = new google.visualization.Dashboard(
document.getElementById('loggedInCompletedToDoDashboard_div')
).
// Configure the filters to affect the chart content
bind([ toDoFilter, durationFilter ], chartWrapper).
// Draw the dashboard
draw(rawDataView_NoID);
}
google.load('visualization', '1.0', {packages: ['table', 'controls']});
google.setOnLoadCallback(drawChart);
EDIT:
I've noticed that the problem only occurs with the first control wrapper passed to the bind function. In other words with the following configuration the row selection stops working correctly if the To Do filter is used:
bind([ toDoFilter, durationFilter ], chartWrapper).
and if I swap the order of the filters then the row selection stops working correctly if the Duration filter is used:
bind([ durationFilter, toDoFilter ], chartWrapper).
If I chain the method invocations as follows the first control wrapper object in the chain is the one that causes row selection to not work properly (just as the first control wrapper object in the array, above, did) and, worse, doing it this way causes the select handler to be invoked 14 times in a row with a single click of the mouse:
bind(durationFilter, chartWrapper).
bind(toDoFilter, chartWrapper).
According to the API reference:
bind(controls, charts)
Binds one or more Controls to one or more other dashboard participants (either charts or other controls), so that all of the latter are redrawn whenever any of the former collects a programmatic or user interaction that affects the data managed by the dashboard. Returns the dashboard instance itself for chaining multiple bind() calls together.
controls - Either a single one or an array of google.visualization.ControlWrapper instances defining the controls to bind.
charts - Either a single one or an array of google.visualization.ChartWrapper instances defining the charts the that will be driven the by the controls.
You can avoid this by just referencing the data passed to the ChartWrapper instead of trying to translate back to the original DataTable. Change this:
currentRow = selection.row;
rowIndex = chartWrapper.getDataTable().getTableRowIndex(currentRow);
duration = dataTable.getFormattedValue(rowIndex, 3);
to this:
duration = chartWrapper.getDataTable().getFormattedValue(selection.row, 3);
Also, ChartWrappers now support the "select" event natively, so you don't need to wrap them with a "ready" event:
google.visualization.events.addListener(chartWrapper, 'select', function () {
// selection handling
});
I'm trying to create a Google chart that looks like the following:
http://chart.googleapis.com/chart?cht=bvs&chs=200x125&chd=t2:10,50,60,80,40%7C50,60,100,40,20%7C30,70,90,95,45&chco=4d89f900,c6d9fd&chbh=20&chds=0,160&chm=H,336699,2,-1,1:22
Basically, I just want to represent the max, min, and average all on one chart, but I can't seem to figure out how to do this. I know it's possible using markers with the old URL-based charts, but they're being deprecated and it doesn't look like the new API supports markers yet.
I tried using candlesticks, but the only way I got it working was with a skinny line and a horizontal line in the middle, so it looked like a bunch of plus signs rather than floating columns with line markers. I know I could also technically stack a column chart with a stepped area chart, but then the line is continuous across all entries, which I don't want.
Thanks.
EDIT: Using jmac's method and intervals, I came up with this:
function drawVisualization() {
// Create and populate the data table.
var data = new google.visualization.DataTable();
data.addColumn('string', 'label');
data.addColumn('number', 'filler');
data.addColumn('number', 'range');
data.addColumn({type:'number', role:'interval'});
data.addRows([
['A', 3, 4, 2],
['B', 2, 5, 4],
['C', 4, 4, 1],
['D', 5, 2, 1],
['E', 1, 8, 4],
]);
// Create and draw the visualization.
var ac = new google.visualization.ColumnChart(document.getElementById('visualization'));
ac.draw(data, {
width: 600,
isStacked: true,
series: [{color:'transparent'},{color:'silver'},{color:'silver'}],
vAxis: {gridlines: {color: 'transparent'}, textPosition: 'none'},
focusTarget: 'category',
intervals: { 'style': 'bars', 'barWidth': 1.3, 'lineWidth': 2 },
});
}
I don't have enough reputation to post an image of what it looks like yet, but if you paste it in here you can see it: https://code.google.com/apis/ajax/playground/?type=visualization#column_chart
Also, since it still highlights the filler area when you mouse over it, I found a css hack to hide the highlighting on mouse over:
#chart-div {
svg g g g g rect {
stroke-width:0px;
}
}
You can use "box" style intervals to accomplish what you want:
function drawChart () {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Category');
data.addColumn('number', 'Min');
data.addColumn('number', 'Average');
data.addColumn('number', 'Max');
data.addRows([
['Foo', 3, 5, 7],
['Bar', 5, 8, 10],
['Baz', 0, 2, 6],
['Bat', 1, 2, 4]
]);
var view = new google.visualization.DataView(data);
// duplicate 1 column as a dummy data series, and add intervals to it
view.setColumns([0, 1, {
id: 'min',
type: 'number',
role: 'interval',
calc: function (dt, row) {
return dt.getValue(row, 1);
}
}, {
id: 'avg',
type: 'number',
role: 'interval',
calc: function (dt, row) {
return dt.getValue(row, 2);
}
}, {
id: 'max',
type: 'number',
role: 'interval',
calc: function (dt, row) {
return dt.getValue(row, 3);
}
}, 1, 2, 3]);
var chart = new google.visualization.LineChart(document.querySelector('#chart_div'));
chart.draw(view, {
height: 400,
width: 600,
lineWidth: 0,
intervals: {
style: 'boxes'
},
legend: {
position: 'none'
},
series: {
0: {
// dummy data series, controls color of intervals
visibleInLegend: false,
color: 'blue',
enableInteractivity: false
},
1: {
// min series options
},
2: {
// average series options
},
3: {
// max series options
}
}
});
}
google.load('visualization', '1', {packages:['corechart'], callback: drawChart});
See working example: http://jsfiddle.net/asgallant/pvJpx/
If all you care about is how it looks visually, you can recreate this with a bit of finagling to have it look like this:
This is the code:
function drawVisualization() {
// Create and populate the data table.
var data = google.visualization.arrayToDataTable([
['label', 'filler', 'bot half', 'top half'],
['A', 3, 2, 2],
['B', 2, 4, 1],
['C', 4, 1, 3],
['D', 5, 1, 1],
['E', 1, 4, 4],
]);
// Create and draw the visualization.
var ac = new google.visualization.ColumnChart(document.getElementById('visualization'));
ac.draw(data, {
width: 600,
isStacked: true,
series: [{color:'transparent'},{color:'silver'},{color:'silver'}],
vAxis: {gridlines: {color: 'transparent'}, textPosition: 'none'},
focusTarget: 'category',
});
}
This is a dumb workaround, but here are the steps given a min value, a max value, and an avg value:
Create a dummy (transparent) series equal to min
Create a second series for the bottom half of the bar equal to avg - min
Create a third series for the top half of the bar equal to max - avg
Although it looks right, the issue is that interaction with the chart will be real funky, in the sense that it won't show you what you would expect from the chart (you would have separate values that aren't showing min, max, and average, but only two values for the size of points 2) and 3) above). You can get around this with creative use of focusTarget, but that will still get you odd stuff like this:
Now you could theoretically rename your series, and use the {v:, f:} trick to make it look nicer, and that may be a good workaround, but it is very kludgy depending on your application. If you finagle it all nice and right, you would get something like this:
This is done with the following code:
function drawVisualization() {
// Create and populate the data table.
var data = new google.visualization.DataTable();
data.addColumn('string', 'Series Name');
data.addColumn('number', 'Average');
data.addColumn('number', 'Minimum');
data.addColumn('number', 'Maximum');
data.addRows([
['A', {v:3, f:'5'}, {v:2, f:'3'}, {v:2, f:'7'}],
['B', {v:2, f:'6'}, {v:4, f:'2'}, {v:1, f:'7'}],
['C', {v:4, f:'5'}, {v:1, f:'4'}, {v:3, f:'8'}],
['D', {v:5, f:'6'}, {v:1, f:'5'}, {v:1, f:'8'}],
['E', {v:1, f:'5'}, {v:4, f:'1'}, {v:4, f:'9'}],
]);
// Create and draw the visualization.
var ac = new google.visualization.ColumnChart(document.getElementById('visualization'));
ac.draw(data, {
width: 600,
isStacked: true,
series: [{color:'transparent'},{color:'silver'},{color:'silver'}],
vAxis: {gridlines: {color: 'transparent'}, textPosition: 'none'},
focusTarget: 'category',
});
}
Again, this is kludgy and not perfect (see the grey box around the filler series, that can't be helped), but it will display the info, and it can be automated using some fancy javascript and/or formatters with dataviews depending on how often the charts need to be changed and what format you get your data in.
I have a bunch of products which I use ColumnChart to show the product name on the x-axis and then two different values that the products have on my y-axis. Since there are a bunch of products it gets pretty messy if I show all of them at once on the ColumnChart therefore I use the ChartRangeFilter Control to be able to have a window of products.
Now my problem is that ChartRangeFilter can't use strings on the axises. But I don't want to display the product id on the x-axis, so is it possible to change the lable when it is displayd?
Hope you can understand what I mean. Below is some code to test in the google code playground
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>
Google Visualization API Sample
</title>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load('visualization', '1.1', {packages: ['corechart', 'controls']});
</script>
<script type="text/javascript">
function drawVisualization() {
var dashboard = new google.visualization.Dashboard(
document.getElementById('dashboard'));
var control = new google.visualization.ControlWrapper({
'controlType': 'ChartRangeFilter',
'containerId': 'control',
'options': {
// Filter by the date axis.
'filterColumnIndex': 0,
'ui': {
'chartType': 'LineChart',
'chartOptions': {
'chartArea': {'width': '90%'},
'hAxis': {'baselineColor': 'none'}
},
'chartView': {
'columns': [0, 1, 2]
},
'minRangeSize': 1
}
},
// Initial range: 1 to 4.
'state': {'range': {'start': 1, 'end': 4}}
});
var chart = new google.visualization.ChartWrapper({
'chartType': 'ColumnChart',
'containerId': 'chart',
'options': {
// Use the same chart area width as the control for axis alignment.
'chartArea': {'height': '80%', 'width': '90%'},
'hAxis': {'slantedText': false},
'vAxis': {'viewWindow': {'min': 0, 'max': 20}},
'legend': {'position': 'none'}
}
});
var data = new google.visualization.DataTable();
data.addColumn('number', 'Product ID');
data.addColumn('number', 'value1');
data.addColumn('number', 'valu2');
data.addRow([1, 11, 12]);
data.addRow([2, 15, 12]);
data.addRow([3, 10, 11]);
data.addRow([4, 11, 9]);
data.addRow([5, 8, 12]);
data.addRow([6, 4, 9]);
data.addRow([7, 8, 15]);
data.addRow([8, 8, 11]);
data.addRow([9, 8, 9]);
dashboard.bind(control, chart);
dashboard.draw(data);
}
google.setOnLoadCallback(drawVisualization);
</script>
</head>
<body>
<div id="dashboard">
<div id="chart" style='width: 915px; height: 300px;'></div>
<div id="control" style='width: 915px; height: 50px;'></div>
</div>
</body>
</html>
Thanks in advance!
You can use a DataView to get around this problem. In the ControlWrapper, set the view.columns parameter like this:
var control = new google.visualization.ControlWrapper({
'controlType': 'ChartRangeFilter',
'containerId': 'control',
'options': {
// Filter by the date axis.
'filterColumnIndex': 0,
'ui': {
'chartType': 'LineChart',
'chartOptions': {
'chartArea': {'width': '90%'},
'hAxis': {'baselineColor': 'none'}
},
'chartView': {
'columns': [0, 1, 2]
},
'minRangeSize': 1
}
},
// Initial range: 1 to 4.
'state': {'range': {'start': 1, 'end': 4}},
view: {
columns: [{
type: 'number',
calc: function (dt, row) {
return {v: row, f: dt.getFormattedValue(row, 0)};
}
}, 1, 2]
}
});
then reverse the process in the ChartWrapper's view.columns:
var chart = new google.visualization.ChartWrapper({
'chartType': 'ColumnChart',
'containerId': 'chart',
'options': {
// Use the same chart area width as the control for axis alignment.
'chartArea': {'height': '80%', 'width': '90%'},
'hAxis': {'slantedText': false},
'vAxis': {'viewWindow': {'min': 0, 'max': 20}},
'legend': {'position': 'none'}
},
view: {
columns: [{
type: 'string',
label: data.getColumnLabel(0),
calc: function (dt, row) {
return dt.getFormattedValue(row, 0);
}
}, 1, 2]
}
});
That should get you what you want.
This code assumes you have a DataTable with 3 columns: a string (product name) and two number columns (value1 and value2). Here is a demo: http://jsfiddle.net/asgallant/55agF/
change the color of the text as of background
hAxis: {textStyle: {color: 'white'}},
How do you change the color of an annotation text in Google Chart Tools LineChart ?
Here is an example
google.load('visualization', '1', {packages: ['corechart']});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Sales');
data.addColumn({id: 'title', label: 'Title', type: 'string', role: 'annotation'});
data.addRows([
[new Date(2012, 3, 5), 80, null],
[new Date(2012, 3, 12), 120, 'New Product'],
[new Date(2012, 3, 19), 80, null],
[new Date(2012, 3, 26), 65, null],
[new Date(2012, 4, 2), 70, null],
]);
var options = {
title: 'Sales by Week',
displayAnnotations: true,
hAxis: {title: 'Date',
titleTextStyle: {color: 'grey'}},
colors: ['#f07f09']
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
I want the line to be orange and the annotation text in grey. Currently the annotation text is orange.
No need for extra style data column and plumbing code to fill it for every row with ugly (and even incomplete above) formatting string. Only resort to separate styling column if you want to have different annotation color for the different data points.
There's a global setting, search for annotations.textStyle in https://developers.google.com/chart/interactive/docs/gallery/linechart
var options = {
annotations: {
textStyle: {
fontName: 'Times-Roman',
fontSize: 18,
bold: true,
italic: true,
// The color of the text.
color: '#871b47',
// The color of the text outline.
auraColor: '#d799ae',
// The transparency of the text.
opacity: 0.8
}
}
};
Here is a concept code for your case (notice different initialization google.charts, very important):
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
google.charts.load('current', { 'packages': ['corechart', 'line', 'bar'] });
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Sales');
data.addColumn({id: 'title', label: 'Title', type: 'string', role: 'annotation'});
data.addRows([
[new Date(2012, 3, 5), 80, null],
[new Date(2012, 3, 12), 120, 'New Product'],
[new Date(2012, 3, 19), 80, null],
[new Date(2012, 3, 26), 65, null],
[new Date(2012, 4, 2), 70, null],
]);
var options = {
chart: {
title: 'Sales by Week'
},
hAxis: {
title: 'Date',
titleTextStyle: {color: 'grey'}
},
annotations: {
textStyle: {
color: 'grey',
}
}
colors: ['#f07f09']
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
You can also change other text formatting of the annotation, like bold, italic, font type, etc. Here is an example where most of the text is configured to be bold:
var options = {
chart: {
title: title
},
hAxis: {
textStyle: {
bold: true
}
},
vAxis: {
format: 'decimal',
textStyle: {
bold: true
}
},
legendTextStyle: {
bold: true
},
titleTextStyle: {
bold: true
},
width: chart_width,
//theme: 'material', // material theme decreases the color contrast and sets the black color items (all text) to 171,171,171 grey -> washed out
annotations: {
alwaysOutside: true,
highContrast: true, // default is true, but be sure
textStyle: {
bold: true
}
}
};
More examples with source repo link: https://mrcsabatoth.github.io/GoogleChartsTalk/
Actually you can. Color of the annotations is the same as line color. Just put a dot in the place you want to make an annotation and set a dot's color to the desirable annotation color.
data.addColumn({type: 'string', role: 'style'});
data.addColumn({type:'string', role:'annotation'});
and then when you add data
'point { size: 14; shape-type: circle; fill-color: #63A74A','Your annotation'
See example at
http://www.marketvolume.com/stocks/stochasticsmomentumindex.asp?s=SPY&t=spdr-s-p-500
If your annotations are not "touching", ie. the points you'd like to annotate are not next to each other, you could add a second line and add the annotations to that line.
In the JSON example below I have a date and a "total balance", as well as an "Ann" line.
"cols":[
{
"id":"date",
"label":"date",
"type":"date",
"p":{
"role":"domain"
}
},
{
"id":"total-balance",
"label":"Total balance",
"type":"number",
"p":{
"role":"data"
}
},
{
"id":"ann",
"label":"Ann",
"type":"number",
"p":{
"role":"data"
}
},
{
"type":"string",
"p":{
"role":"annotation"
}
},
{
"type":"string",
"p":{
"role":"annotationText"
}
}
],
The annotation comes after the "Ann" column so it'll be added to the "Ann" data points.
In my JSON, the date and "total-balance" are always filled in. "Ann" and the annotations are usually empty:
"rows":[
{
"c":[
{
"v":"Date(2013, 0, 1)"
},
{
"v":1000
},
{
"v":null
},
{
"v":null
},
{
"v":null
}
]
},
{
"c":[
{
"v":"Date(2013, 0, 8)"
},
{
"v":1001
},
{
"v":null
},
{
"v":null
},
{
"v":null
}
]
},
When I need an annotation, the "Ann" cell gets the same value as the total balance, and the annotation is added:
{
"c":[
{
"v":"Date(2013, 1, 26)"
},
{
"v":2000
},
{
"v":2000
},
{
"v":"Something!"
},
{
"v":"Something happened here!"
}
]
},
In your GChart's configuration, you can now set two colours. One for the normal line, and one for the "Ann".
colors: ['black','red']
If you have no annotations "touching", GCharts will not draw a line between them and the points will remain "invisible", while the annotations show up at exactly the right place.
Short answer: no, you can't change the text color through standard options (you could write something to find that text in the SVG and change its color with javascript, but that is beyond my level).
You can see an answer from ASGallant on Google Groups here, and his example here.
// code borrowed from Google visualization API playground, slightly modified here
google.load('visualization', '1', {packages: ['corechart']});
google.setOnLoadCallback(drawVisualization);
function drawVisualization() {
// Create and populate the data table.
var data = new google.visualization.DataTable();
data.addColumn('string', 'x');
data.addColumn({type: 'string', role: 'annotation'});
data.addColumn({type: 'string', role: 'annotationText'});
data.addColumn('number', 'Cats');
data.addColumn('number', 'Blanket 1');
data.addColumn('number', 'Blanket 2');
data.addRow(["A", null, null, 1, 1, 0.5]);
data.addRow(["B", null, null, 2, 0.5, 1]);
data.addRow(["C", null, null, 4, 1, 0.5]);
data.addRow(["D", null, null, 8, 0.5, 1]);
data.addRow(["E", 'foo', 'foo text', 7, 1, 0.5]);
data.addRow(["F", null, null, 7, 0.5, 1]);
data.addRow(["G", null, null, 8, 1, 0.5]);
data.addRow(["H", null, null, 4, 0.5, 1]);
data.addRow(["I", null, null, 2, 1, 0.5]);
data.addRow(["J", null, null, 3.5, 0.5, 1]);
data.addRow(["K", null, null, 3, 1, 0.5]);
data.addRow(["L", null, null, 3.5, 0.5, 1]);
data.addRow(["M", null, null, 1, 1, 0.5]);
data.addRow(["N", null, null, 1, 0.5, 1]);
// Create and draw the visualization.
var chart = new google.visualization.LineChart(document.getElementById('visualization'));
chart.draw(data, {
annotation: {
1: {
style: 'line'
}
},
curveType: "function",
width: 500,
height: 400,
vAxis: {
maxValue: 10
}
});
}
The best you can do is to change the style of the line, but it doesn't look like you can currently change the color of the line.
Has this been updated using the 'style' option where one could add a new column {"type":"string","role":"style"} and in each row we would have {"v":"point {size: 4; fill-color: #3366cc;}"}? This allows the annotation to have the same color as the point/marker (which could be changed for each point) but does not allow it to be bold. One example of the data to try would be,
var data =new google.visualization.DataTable(
{
"cols":[
{"label":"Log GDP Per-Capita ","type":"number"},
{"label":"New Chart",
"type":"number"},
{"type":"string","role":"annotation"},
{"type":"string","role":"style"}
],
"rows":[
{"c":[{"v":10.21932},{"v":12.3199676},{"v":"ABW"},{"v":"point {size: 4; fill-color: #3366cc;}"}]},
{"c":[{"v":10.68416},{"v":8.4347518},{"v":"ARE"},{"v":"point {size: 4; fill-color: #3366cc;}"}]},
{"c":[{"v":9.634226},{"v":12.0774068},{"v":"ATG"},{"v":"point {size: 4; fill-color: #3366cc;}"}]},
{"c":[{"v":10.83869},{"v":1.8545959},{"v":"AUS"},{"v":"point {size: 4; fill-color: #3366cc;}"}]},
{"c":[{"v":10.7687},{"v":7.4919999},{"v":"AUT"},{"v":"point {size: 4; fill-color: #3366cc;}"}]}
]
}
);