google chart discrete axis show line? - google-visualization

I'm using google charts with discrete values and can't seem to get the vAxis line to be drawn (in black).
It appears when graphic in Continuous values but I don't want the chart to be spaced out that way.
here are the 2 types of graphs.
http://jsfiddle.net/cFHJY/
google.load("visualization", "1", {packages: ["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var discreteData = new google.visualization.DataTable();
discreteData.addColumn('string', 'Number');
discreteData.addColumn('number', 'Value');
discreteData.addRows([
['1.492', 10],
['30.701', 17],
['127.469', 6],
['749.382', 11]
]);
var discreteChart = new google.visualization.ColumnChart(document.getElementById('discrete_chart_div'));
discreteChart.draw(discreteData, {
title: 'Discrete Axis Line Chart'
});
var continuousData = new google.visualization.DataTable();
continuousData.addColumn('number', 'Number');
continuousData.addColumn('number', 'Value');
continuousData.addRows([
[1.492, 10],
[30.701, 17],
[127.469, 6],
[749.382, 11]
]);
var continuousChart = new google.visualization.ColumnChart(document.getElementById('continuous_chart_div'));
continuousChart.draw(continuousData, {
title: 'Continuous Axis Line Chart'
});
}
How do I get the vAxis line to be drawn?

The "vAxis line" is actually the hAxis baseline, which is only available to continuous axes. With a bit of hackery, you can put your data on a continuous axis while appearing to keep its discrete nature. Use a DataView to convert your data to a "number" type (using the row index for the value and the string value as the formatted value) and build the hAxis.ticks option from the value/formatted value pairs in the view:
function drawChart() {
var discreteData = new google.visualization.DataTable();
discreteData.addColumn('string', 'Number');
discreteData.addColumn('number', 'Value');
discreteData.addRows([
['1.492', 10],
['30.701', 17],
['127.469', 6],
['749.382', 11]
]);
var view = new google.visualization.DataView(discreteData);
view.setColumns([{
type: 'number',
label: discreteData.getColumnLabel(0),
calc: function (dt, row) {
return {v: row + 1, f: dt.getFormattedValue(row, 0)};
}
}, 1]);
var ticks = [];
for (var i = 0; i < view.getNumberOfRows(); i++) {
ticks.push({v: view.getValue(i, 0), f: view.getFormattedValue(i, 0)});
}
var range = view.getColumnRange(0);
var offset = 0.5; // change this to move the left/right margins of the chart
var discreteChart = new google.visualization.ColumnChart(document.getElementById('discrete_chart_div'));
discreteChart.draw(view, {
title: 'Discrete Axis Line Chart',
hAxis: {
ticks: ticks,
viewWindow: {
min: range.min - offset,
max: range.max + offset
},
// set gridlines.color to "transparent" to hide the vertical gridlines
/*
gridlines: {
color: 'transparent'
}
*/
}
});
}
google.load('visualization', '1', {packages:['corechart'], callback: drawChart});
Ex: http://jsfiddle.net/asgallant/h4Kfd/

Related

Google column charts X-axis label different from value

I'd like to create column chart with X axis numeric values 1, 2, 3, 4 ... N and Y value of course different on every column.
I can't find out how to change labels on X line under bars, to string. For example - 1 could be marked as Elephant, 2 as Horse etc.
I could use string as X values, but then there is no way to get zoom working. At least, I didn't find any way to get it working.
simple example with strings, I'd like to achieve same appearance as this one, but with numeric values on X axis.
google.charts.load('current', {packages: ['corechart', 'bar']});
google.charts.setOnLoadCallback(drawBasic);
function drawBasic() {
var data = new google.visualization.DataTable();
data.addColumn('number', 'animal');
data.addColumn('number', 'count');
data.addRows([
['Elephant', 5],
['Horse', 2],
['Dog', 7],
['Cat', 4],
]);
var options = {
explorer: {
axis: 'horizontal',
keepInBounds: true,
},
title: 'Testing',
hAxis: {
title: 'Animal',
},
vAxis: {
title: 'number'
}
};
var chart = new google.visualization.ColumnChart(
document.getElementById('chart_div'));
chart.draw(data, options);
}
Chart should look like this, but with working zoom:
Chart example
to use string labels on a continuous axis,
you will need to provide your own ticks
using object notation, provide the value (v:) and formatted value (f:)
{v: 1, f: 'Elephant'}
see following working snippet...
google.charts.load('current', {
callback: drawBasic,
packages: ['corechart']
});
function drawBasic() {
var data = new google.visualization.DataTable();
data.addColumn('number', 'animal');
data.addColumn('number', 'count');
data.addRows([
[1, 5],
[2, 2],
[3, 7],
[4, 4]
]);
var options = {
explorer: {
axis: 'horizontal'
},
title: 'Testing',
hAxis: {
ticks: [
{v: 1, f: 'Elephant'},
{v: 2, f: 'Horse'},
{v: 3, f: 'Dog'},
{v: 4, f: 'Cat'}
],
title: 'Animal',
},
vAxis: {
title: 'number'
}
};
var chart = new google.visualization.ColumnChart(
document.getElementById('chart_div')
);
chart.draw(data, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

number of labels on the horizontal axis in Google Chartwrapper

In Google Charts, the 'hAxis': {'gridlines': {'count': 3} } statement seems to work, but when I'm using chartWrapper as part of an interactive plot, it does not. I don't really care about vertical gridlines, but I want to control how many labels are on the X axis. I think labels are usually attached to gridlines - one label per gridline.
I have an example from the Google Charts website, where the only thing I changed was to put try and put in 3 gridlines:
https://jsfiddle.net/emorris/gLcq1h2j/
chart option ticks is only supported by a continuous axis
in the fiddle you shared, the view placed on the chart,
converts the first column from type 'date' to 'string',
which results in a discrete axis
// 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]
}
to control how many labels are on the X axis, remove the view
to build the ticks dynamically here, use the state of the range filter,
to know the date range currently displayed on the chart
the chart will need to be redrawn when the control's 'statechange' event fires
see following working snippet, an axis label is created for every 5 days...
google.charts.load('current', {
callback: drawChartRangeFilter,
packages: ['corechart', 'controls']
});
function drawChartRangeFilter() {
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Stock low');
data.addColumn('number', 'Stock open');
data.addColumn('number', 'Stock close');
data.addColumn('number', 'Stock high');
var open, close = 300;
var low, high;
for (var day = 1; day < 121; ++day) {
var change = (Math.sin(day / 2.5 + Math.PI) + Math.sin(day / 3) - Math.cos(day * 0.7)) * 150;
change = change >= 0 ? change + 10 : change - 10;
open = close;
close = Math.max(50, open + change);
low = Math.min(open, close) - (Math.cos(day * 1.7) + 1) * 15;
low = Math.max(0, low);
high = Math.max(open, close) + (Math.cos(day * 1.3) + 1) * 15;
var date = new Date(2012, 0, day);
data.addRow([date, Math.round(low), Math.round(open), Math.round(close), Math.round(high)]);
}
var dashboard = new google.visualization.Dashboard(
document.getElementById('dashboard')
);
var control = new google.visualization.ControlWrapper({
controlType: 'ChartRangeFilter',
containerId: 'control',
options: {
filterColumnIndex: 0,
ui: {
chartType: 'LineChart',
chartOptions: {
chartArea: {
width: '92%'
},
hAxis: {
baselineColor: 'none'
},
height: 72
},
chartView: {
columns: [0, 3]
},
minRangeSize: 86400000
}
},
state: {
range: {
start: new Date(2012, 1, 9),
end: new Date(2012, 2, 20)
}
}
});
var chart = new google.visualization.ChartWrapper({
chartType: 'CandlestickChart',
containerId: 'chart',
options: {
chartArea: {
height: '100%',
width: '100%',
top: 12,
left: 48,
bottom: 48,
right: 48
},
vAxis: {
viewWindow: {
min: 0,
max: 2000
}
},
legend: {
position: 'none'
}
}
});
google.visualization.events.addListener(control, 'statechange', setAxisTicks);
function setAxisTicks() {
var oneDay = (1000 * 60 * 60 * 24);
var dateRange = control.getState().range;
var ticksAxisH = [];
for (var i = dateRange.start.getTime(); i <= dateRange.end.getTime(); i = i + (oneDay * 5)) {
ticksAxisH.push(new Date(i));
}
if (ticksAxisH.length > 0) {
ticksAxisH.push(new Date(ticksAxisH[ticksAxisH.length - 1].getTime() + (oneDay * 5)));
}
chart.setOption('hAxis.ticks', ticksAxisH);
if (chart.getDataTable() !== null) {
chart.draw();
}
}
setAxisTicks();
dashboard.bind(control, chart);
drawDashboard();
$(window).resize(drawDashboard);
function drawDashboard() {
dashboard.draw(data);
}
}
<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="dashboard">
<div id="chart"></div>
<div id="control"></div>
</div>

Legend and axis tooltip comes with black box with google chart (Firefox

I am currently working on Google Charts with below Version.
google.charts.load('upcoming', {packages: ['corechart']);
When i enter a mouse on axis and legend tooltip comes with black box as per attached image.
I also tried "Current" and "42" version but still getting a same issue as in attached image. I am facing this issue with Firefox.
Google Line Chart- Tooltip with balck box in Firefox
Is it a bug in Google Chart API or anything else?
tooltip seems to work fine here
any code / css / chart options you can share?
see following working snippet...
google.charts.load('current', {
callback: drawChart,
packages: ['corechart']
});
function drawChart() {
var dataTable = new google.visualization.DataTable({
cols: [
{id: 'x', label: 'Date', type: 'date'},
{id: 'y', label: 'Fn', type: 'number'},
{id: 'z', label: 'Shade', type: 'number'}
]
});
var formatDate = new google.visualization.DateFormat({
pattern: 'MMM-dd-yyyy'
});
var oneDay = (1000 * 60 * 60 * 24);
var startDate = new Date(2016, 10, 27);
var endDate = new Date();
var ticksAxisH = [];
var dateRanges = [
{start: new Date(2017, 0, 1), end: new Date(2017, 0, 20)},
{start: new Date(2017, 1, 5), end: new Date(2017, 1, 10)}
];
var maxShade = 200;
for (var i = startDate.getTime(); i < endDate.getTime(); i = i + oneDay) {
// x = date
var rowDate = new Date(i);
var xValue = {
v: rowDate,
f: formatDate.formatValue(rowDate)
};
// y = 2x + 8
var yValue = (2 * ((i - startDate.getTime()) / oneDay) + 8);
// z = null or max shade
var zValue = null;
dateRanges.forEach(function (range) {
if ((rowDate.getTime() >= range.start.getTime()) &&
(rowDate.getTime() <= range.end.getTime())) {
zValue = maxShade;
}
});
// add data row
dataTable.addRow([
xValue,
yValue,
zValue
]);
// add tick every 7 days
if (((i - startDate.getTime()) % 7) === 0) {
ticksAxisH.push(xValue);
}
}
var container = document.getElementById('chart_div');
var chart = new google.visualization.ChartWrapper({
chartType: 'ComboChart',
dataTable: dataTable,
options: {
chartArea: {
bottom: 64,
top: 48
},
hAxis: {
slantedText: true,
ticks: ticksAxisH
},
legend: {
position: 'top'
},
lineWidth: 4,
series: {
// line
0: {
color: '#00acc1'
},
// area
1: {
areaOpacity: 0.6,
color: '#ffe0b2',
type: 'area',
visibleInLegend: false
},
},
seriesType: 'line'
}
});
chart.draw(container);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

Google halfdonut pie chart: is it possible to set total percentage?

I made half a donut chart with Google charts and I have a problem that the sum of visible percentage is equal to 50%. Is there any possible solution ?
Image of my chart
you can override the text displayed on the slice by using the following config option...
pieSliceText: 'value'
then in the data, set the formatted value of the cells to the correct percentage...
var data = [
['Task', 'Hours'],
// use formatted values
['A', {v: 19.2, f: '38.4%'}],
['B', {v: 30.8, f: '61.6%'}],
[null, 50]
];
the following working snippet uses the same approach,
but calculates the correct percentages,
rather than hard-coding...
google.charts.load('current', {
callback: function () {
var data = [
['Task', 'Hours'],
['A', 19.2],
['B', 30.8],
[null, 50.0]
];
var total = 0;
for (var i = 1; i < data.length; i++) {
if (data[i][0] !== null) {
total += data[i][1];
}
}
var numberFormat = new google.visualization.NumberFormat({
pattern: '#,##0.0',
suffix: '%'
});
var dataTable = google.visualization.arrayToDataTable(data);
for (var i = 0; i < dataTable.getNumberOfRows(); i++) {
if (dataTable.getValue(i, 0) !== null) {
dataTable.setFormattedValue(i, 1, numberFormat.formatValue(((dataTable.getValue(i, 1) / total) * 100)));
}
}
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
var options = {
height: 400,
chartArea: {
top: 24
},
colors: ['#8BC34A', '#64B5F6'],
legend: 'none',
pieHole: 0.4,
pieStartAngle: 270,
pieSliceText: 'value',
slices: {
2: {
color: 'transparent'
}
},
theme: 'maximized',
width: 400
};
chart.draw(dataTable, options);
},
packages: ['corechart']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

Google charts floating min / max / average column chart

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.