I have an Annotated Timeline that I would like to update in realtime (similar to how Google Finance does it). However, I am having trouble getting the chart to not flicker and not re-zoom when data is added.
I couldn't get the code to work in JSFiddle (I think because annotated timeline is flash based?) but here is some basic code that you can plug in to Google's Visualization Playground. You can see a saved example here but unfortunately can't modify the code, you'll have to go to the playground to do that.
function drawVisualization() {
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'My Data');
data.addRows([
[new Date(2009, 1 ,1), 30000],
[new Date(2009, 1 ,2), 14045],
[new Date(2009, 1 ,3), 55022],
[new Date(2009, 1 ,4), 75284],
[new Date(2009, 1 ,5), 41476],
[new Date(2009, 1 ,6), 33322]
]);
var annotatedtimeline = new google.visualization.AnnotatedTimeLine(
document.getElementById('visualization'));
var options = {
'allowRedraw' : true ,
'displayAnnotations' : true,
'zoomStartTime': new Date(2009, 1 ,2),
'zoomEndTime': new Date(2009, 1 ,10)
};
annotatedtimeline.draw(data, options);
// let's add some more data in 3 seconds
setTimeout(function() {
again(annotatedtimeline, data, options);
}, 3000);
}
function again(timeline, data, options) {
data.addRow([new Date(2009, 1 ,7), 30000]);
timeline.draw(data, options);
}
google.setOnLoadCallback(drawVisualization);
What's weird is that I get pretty different flicker behavior depending on how I set displayAnnotations
displayAnnotations = true : Chart flickers but does not re-zoom
displayAnnotations = false : No chart flicker but it re-zooms to the new data (try it on the playground to see)
Setting allowRedraw = false causes the chart to flicker regardless. Any idea how to get no flicker and no re-zoom?
From the docs:
allowRedraw must be true
displayAnnotations must be false (that is, you cannot show annotations)
That's your problem.
Related
I have multiple collections of data I want to display in a single google chart. Each series is a collection of CPM's with a date:
for instance:
series A[
'2016-09-01' => 2.08023,
'2016-09-04' => 2.01123
];
series B[
'2016-09-01' => 1.99324,
'2016-09-02' => 2.00112
];
Note that the dates in the two series are not the same. I want to draw these two graphs in a single google graph. How should I format the data rows (if this is possible at all).
I have made a JSFiddle with what I thought would be a way to go, but adding a null in the data table doesn't work, I get two dots for the first series where I'm expecting a line. How can I make google chart draw the line instead of the dots?
in the fiddle, the data is setup correctly
however, since there is a null value is Series A due to the different dates
need to use configuration option interpolateNulls: true
from the documentation...
interpolateNulls
Whether to guess the value of missing points. If true, it will guess the value of any missing data based on neighboring points. If false, it will leave a break in the line at the unknown point.
see following working snippet...
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('date', 'X');
data.addColumn('number', 'series a');
data.addColumn('number', 'series b')
data.addRows([
[new Date( 1472688000000 ), 2.08023, 1.99324],
[new Date( 1472774400000 ), null, 2.00112],
[new Date( 1472947200000 ), 2.01123, null]
]);
var options = {
interpolateNulls: true
};
var container = document.getElementById('chart_div');
var chart = new google.visualization.LineChart(container);
chart.draw(data, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
Using react-google-charts, I would like to specify which years should be displayed on the horizontal axis of a Google Timeline Chart. The screenshot shows an example that uses automatically generated values, based on the given time range of the rows.
The example uses the following data:
[
[ 'Washington', new Date(1789, 3, 30), new Date(1797, 2, 4) ],
[ 'Adams', new Date(1797, 2, 4), new Date(1801, 2, 4) ],
[ 'Jefferson', new Date(1801, 2, 4), new Date(1809, 2, 4) ]
]
I already tried the following options with no joy:
hAxis: {
title: 'Year',
minValue: new Date(1785, 3, 15),
maxValue: new Date(1825, 3, 15),
ticks: [
{ v: new Date(1792, 3, 15), f: '1792' },
{ v: new Date(1818, 3, 15), f: '1818' },
{ v: new Date(1824, 3, 15), f: '1824' }
]
}
I would expect to have the x-Axis labelled with "Years" and showing 1792, 1818 and 1824 instead of 1790 and 1800.
The minValue and maxValue options seem to get ignored, too.
According to the readme it should be working.
Is the problem related to the value being date-objects instead of integers?
Edit: Added a jsfiddle: http://jsfiddle.net/s4zg7mxt/
It is not using react-google-charts, but the problem remains the same: ticks (and title) options still have no effect. Interestingly, the minValue and maxValue options are taken into account though.
Is it possible at all to adapt the jsfiddle, in order to show the specified years on the horizontal axis?
i've found if the configuration option, or other feature, isn't listed on the guide for that particular chart,
the chart doesn't support it.
except for options added in more recent releases,
in which the guide for that chart hasn't been updated.
as such, the only hAxis options available on a Timeline chart are minValue and maxValue
made available with the October 2, 2015 release
Timeline:
-- Durations are now localized.
-- Now supports minValue and maxValue for the horizontal axis.
The library automatically calculates the scaling of x-axis based on the start date, end date and browser's display area.
Please paste full code, will check and update you whether it is possible to do the custom scaling of the x-axis.
The background for this question is I'm trying to access the selected cell from addListener in google visualization calendar. I could print the selected cell using JSON.stringify(chart.getSelection());. It prints as [{"date":1468195200000,"row":0}].
My problem is to access this date object. I tried to access it as
var obj=JSON.stringify(chart.getSelection());
console.log('selected value '+obj.date);
But it displays as Undefined. When I print the obj it displays as [object, object]
If you need more information please let me know. Any suggestion would be appreciated.
JSON.stringify() serializes a data object into a string. Just access the object directly.
var data = chart.getSelection()[0]; // assuming there is only ever one item in the selection array.
console.log(data.date)
Try this:
var data = [{"date":1468195200000,"row":0}]
var rw = data[0].row;
var dt = new Date(data[0].date);
console.log(rw);
console.log(dt);
careful when accessing the first array element directly when listening for the 'select' event
chart.getSelection()[0]
the 'select' event is fired, both when a selection is made, AND removed
so the above line will fail when the selection is removed
check the length before accessing...
selection = chart.getSelection();
// check selection length
if (selection.length > 0) {
console.log(selection[0].date);
} else {
console.log('selection removed');
}
see following working snippet, select a date, then select again to remove the selection...
google.charts.load('current', {
callback: function () {
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'date', id: 'Date' });
dataTable.addColumn({ type: 'number', id :'Score' });
dataTable.addRows([
[ new Date(2016, 3, 13), 101 ],
[ new Date(2016, 3, 14), 102 ],
[ new Date(2016, 3, 15), 103 ],
[ new Date(2016, 3, 16), 104 ],
[ new Date(2016, 3, 17), 105 ]
]);
var chart = new google.visualization.Calendar(document.getElementById('chart_div'));
google.visualization.events.addListener(chart, 'select', function () {
var selection = chart.getSelection();
// check selection length
if (selection.length > 0) {
console.log(selection[0].date);
} else {
console.log('selection removed');
}
});
chart.draw(dataTable);
},
packages:["calendar"]
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
This is an array of objects however there is only one object in this array (or so I think) so what you should do is console.log(obj[0].date); instead!
I have a simple Google chart:
google.setOnLoadCallback(drawVisualization);
function drawVisualization() {
var data = [
[new Date("Month"), "Shipments"],
[new Date("2015-05-01T04:00:00.000Z"), 51666],
[new Date("2014-11-01T04:00:00.000Z"), 53783],
[new Date("2015-02-01T05:00:00.000Z"), 63454],
[new Date("2014-12-01T05:00:00.000Z"), 63722],
[new Date("2015-03-01T05:00:00.000Z"), 63836],
[new Date("2015-09-01T04:00:00.000Z"), 63884],
[new Date("2015-04-01T04:00:00.000Z"), 68869],
[new Date("2015-08-01T04:00:00.000Z"), 68954],
[new Date("2015-01-01T05:00:00.000Z"), 72110],
[new Date("2015-06-01T04:00:00.000Z"), 77942],
[new Date("2015-07-01T04:00:00.000Z"), 86856],
[new Date("2014-10-01T04:00:00.000Z"), 92168]
];
// Some raw data (not necessarily accurate)
var data = google.visualization.arrayToDataTable(data);
var chart = new google.visualization.ColumnChart(
document.getElementById('chart_div')
);
chart.draw(data);
}
<script type="text/javascript" src="https://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1.1','packages':['corechart']}]}"></script>
<div id="chart_div" style="width: 900px; height: 500px;"></div>
You can also see this in action at http://codepen.io/chug187/pen/GpQzNg.
Why does it automatically sort by the dates in the data? I want to have the chart's columns appear in ascending order of the number of shipments, yet Google Charts is sorting the data by date. There doesn't appear to be any options for either the DataTable, DataView or ComboChart classes to ensure that the data appears as it exists in the data array.
Since the values on X-axis are date, it does not consider it discrete (like strings) and treat as continuous data and hence sorts them.
You can make them string, and apply sort them based on the numerical data by
[String(new Date("2015-05-01T04:00:00.000Z")), 51666],
data.sort([{column: 1}, {column: 0}]);
You can find the codepen working as per your need here
You can also refer google charts documentation here
How to create Google Histogram Chart [1] that works with dates?
I've placed sample code (with working number and non-working date examples): http://jsfiddle.net/Qquse/417/ and code below [2]
[1] https://developers.google.com/chart/interactive/docs/gallery/histogram
[2]
google.load("visualization", "1", {
packages: ["corechart"]
});
google.setOnLoadCallback(drawChart);
function str_to_utcdate(d) {
return new Date(d.substr(0, 4), d.substr(5, 2) - 1, d.substr(9, 2));
}
function drawChart() {
var data = google.visualization.arrayToDataTable([
['item', 'date'],
['a', str_to_utcdate('2001-07-01')],
['b', str_to_utcdate('2001-07-01')],
['c', str_to_utcdate('2001-07-01')], ]);
var chart = new google.visualization.Histogram(document.getElementById('chart_div1'));
chart.draw(data);
var data = google.visualization.arrayToDataTable([
['item', 'date'],
['a', 10],
['b', 20],
['c', 30], ]);
var chart = new google.visualization.Histogram(document.getElementById('chart_div2'));
chart.draw(data);
}
5 years now and Histograms still don't support dates. Since I ain't got time and I need my stuff done, I made a workaround (so ugly it hurts) but works.
First, I defined a format just to put a keyword at the start of each label. In my case, since I have only one chart in my page, I just used the keyword 'date'.
const keyword = 'date';
const options = {
// ...
hAxis: {
format: `'${keyword}'#`
},
}
If you have multiple charts in your page and you want them to behave differently, you might want to define different keyword to each one.
Now, using query selector, I selected all the label elements that are of my interest
let labels = Array.from(document.querySelectorAll('#chart svg g:nth-of-type(3) g:nth-of-type(3) g text'));
In my case, my chart was set in a DIV with id 'chart'. If you're using any other id, just replace #chart with your id;
Then I will filter only the labels which start with my keyword 'date'
labels = labels.filter(g => g.innerHTML.startsWith(keyword));
With that, I replace the innerHTML of each element to the date format I wish.
labels.forEach(g => {
const date = new Date(+g.substring(keyword.length));
// you can apply any format method you wish
// .toLocaleDateString()
g.innerHTML = date.toLocaleDateString();
// moment.js
g.innerHTML = moment(date).format('DD/MM/YYYY HH:MM');
});
Also, I'm using interactive charts, so the labels refresh on each user interaction. Therefore, I put everything inside an interval, and the final result is as follows:
const keyword = 'date';
const options = {
// ...
hAxis: {
format: `'${keyword}'#`
},
}
// ... chart setup
setInterval(() => {
let labels = Array.from(document.querySelectorAll('#chart svg g:nth-of-type(3) g:nth-of-type(3) g text'));
labels = labels.filter(g => g.innerHTML.startsWith(keyword));
labels.forEach(g => {
const date = new Date(+g.substring(keyword.length));
g.innerHTML = date.toLocaleDateString();
});
}, 100);
Use this answer with caution. Using query selectors to modify third party generated content is very unsafe because it relies on the hope that the third-party developers won't modify the way the content is generated.
Try out this column chart:
public histogramChart: GoogleChartInterface = {
chartType: 'ColumnChart',
dataTable: [
['Date', 'Number'],
[new Date(2015, 1, 1), 5],
[new Date(2015, 1, 2), 5.1],
[new Date(2015, 1, 3), 6.2],
[new Date(2015, 1, 4), 7]
];,
//opt_firstRowIsData: true,
options: {
title: 'Shooting history',
legend: { position: 'none' },
colors: ['#4285F4'],
},
};