Related
I am trying to print the bottom label of the Google gauges outside(just below the respective gauges). Also, I want to provide two different suffixes for the two gauges. I have tried giving separate formatters(formatter1, formatter2) for both and separate data(data1 and data2), but it's not even drawing the gauges(no error). In this case, the draw_data_guage will have a fourth argument.
var e = document.getElementById('draw_chart');
e.onclick = draw_data_gauge(80, 68, '%');
function draw_data_gauge(cpu_data, memory_data, suffix) {
console.log("in guage")
google.charts.load('current', {
'packages': ['gauge']
});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data1 = google.visualization.arrayToDataTable([
['Label', 'Value'],
['CPU', cpu_data],
['Memory', memory_data],
]);
var options = {
width: 500,
height: 150,
redFrom: 90,
redTo: 100,
yellowFrom: 75,
yellowTo: 90,
minorTicks: 5,
};
var formatter1 = new google.visualization.NumberFormat({
suffix: suffix,
});
formatter1.format(data1, 1);
var chart = new google.visualization.Gauge(document.getElementById('chart_div'));
chart.draw(data1, options);
}
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<input name="Button" type="button" value="Draw" id="draw_chart" />
<div id="chart_div"></div>
I want the gauge's bottom label to be displayed outside and be able to give separate suffixes for both the gauges. Consider this jsfiddle link. I want to display the percentages(bottom label) outside the gauges just below them. My jsfiddle link is here. Thanks in advance.
Your direction to separate the graphs is right. Here is how to do this:
div {
display: inline-block;
}
<script type='text/javascript' src='https://www.google.com/jsapi'></script>
<script type="text/javascript">
google.load('visualization', '1', {
packages: ['gauge']
});
google.setOnLoadCallback(drawChart);
function drawChart() {
var options = {
width: 400,
height: 120,
redFrom: 90,
redTo: 100,
yellowFrom: 75,
yellowTo: 90,
minorTicks: 5
};
var source = [{
data: ['Memory', 80],
suffix: '%'
},
{
data: ['CPU', 55],
suffix: '?'
},
{
data: ['Network', 68],
suffix: '$'
},
];
source.map((item, index) => {
var data = google.visualization.arrayToDataTable([
['Label', 'Value'],
item.data
]);
var formatter = new google.visualization.NumberFormat({
suffix: item.suffix,
fractionDigits: 0
});
formatter.format(data, 1);
document.body.innerHTML += '<div id="chart_div_' + index + '"></div>';
var chart = new google.visualization.Gauge(document.getElementById('chart_div_' + index));
chart.draw(data, options);
});
// dynamic update, randomly assign new values and redraw
//setInterval(function() {
// data.setValue(0, 1, 40 + Math.round(60 * Math.random()));
// formatter.format(data, 1);
// chart.draw(data, options);
//}, 1000);
//
//setInterval(function() {
// data.setValue(1, 1, 40 + Math.round(60 * Math.random()));
// chart.draw(data, options);
//}, 1000);
//
//setInterval(function() {
// data.setValue(2, 1, 40 + Math.round(60 * Math.random()));
// chart.draw(data, options);
//}, 1000);
}
</script>
About the text position, I think that it's impossible. You can add a div below each chart with the text.
I am trying to add some annotations to a Google Candlestick chart. I noticed someone had already asked this same question (Adding annotations to Google Candlestick chart). The user Aperçu replied with a detailed solution to extend the chart and add annotations since the chart doesn't have any such feature built in. However, when I try this solution I get an error "TypeError: document.querySelectorAll(...)[0] is undefined"
Here is my code:
chartPoints = [
['Budget', 0, 0, 9999, 9999, 'foo1'],
['Sales', 0, 0, 123, 123, 'foo2'],
['Backlog', 123, 123, 456, 456, 'foo3'],
['Hard Forecast', 456, 456, 789, 789, 'foo4'],
['Sales to Budget', 789, 789, 1000, 1000, 'foo5']
];
var data = google.visualization.arrayToDataTable(chartPoints, true);
data.setColumnProperty(5, 'role', 'annotation');
var options = {
legend: 'none',
bar: { groupWidth: '40%', width: '100%' },
candlestick: {
fallingColor: { strokeWidth: 0, fill: '#a52714' },
risingColor: { strokeWidth: 0, fill: '#0f9d58' }
}
};
var chart = new google.visualization.CandlestickChart(document.getElementById('chart_div'));
chart.draw(data, options);
// attempt to use Aperçu's solution
const bars = document.querySelectorAll('#chart_div svg > g:nth-child(5) > g')[0].lastChild.children // this triggers a TypeError
for (var i = 0 ; i < bars.length ; i++) {
const bar = bars[i]
const { top, left, width } = bar.getBoundingClientRect()
const hint = document.createElement('div')
hint.style.top = top + 'px'
hint.style.left = left + width + 5 + 'px'
hint.classList.add('hint')
hint.innerText = rawData.filter(t => t[1])[i][0]
document.getElementById('chart_div').append(hint)
}
I want the chart to show the last piece of data next to the bars (i.e. "foo1", "foo2", etc)
each candle or bar will be represented by a <rect> element
we can use the rise and fall colors to separate the bars from other <rect> elements in the chart
there will be the same number of bars as rows in the data table
once we find the first bar, we can use rowIndex of zero to pull values from the data
we need to find the value of the rise / fall, to know where to place the annotation
then use chart methods to find the location for the annotation
getChartLayoutInterface() - Returns an object containing information about the onscreen placement of the chart and its elements.
getYLocation(position, optional_axis_index) - Returns the screen y-coordinate of position relative to the chart's container.
see following working snippet
two annotations are added
one for the difference in rise and fall
and the other for the value in the column with annotation role
google.charts.load('current', {
callback: drawChart,
packages: ['corechart']
});
function drawChart() {
var chartPoints = [
['Budget', 0, 0, 9999, 9999, 'foo1'],
['Sales', 0, 0, 123, 123, 'foo2'],
['Backlog', 123, 123, 456, 456, 'foo3'],
['Hard Forecast', 456, 456, 789, 789, 'foo4'],
['Sales to Budget', 789, 789, 1000, 1000, 'foo5']
];
var data = google.visualization.arrayToDataTable(chartPoints, true);
data.setColumnProperty(5, 'role', 'annotation');
var options = {
legend: 'none',
bar: { groupWidth: '40%', width: '100%' },
candlestick: {
fallingColor: { strokeWidth: 0, fill: '#a52714' },
risingColor: { strokeWidth: 0, fill: '#0f9d58' }
}
};
var container = document.getElementById('chart_div');
var chart = new google.visualization.CandlestickChart(container);
google.visualization.events.addListener(chart, 'ready', function () {
var annotation;
var bars;
var chartLayout;
var formatNumber;
var positionY;
var positionX;
var rowBalance;
var rowBottom;
var rowIndex;
var rowTop;
var rowValue;
var rowWidth;
chartLayout = chart.getChartLayoutInterface();
rowIndex = 0;
formatNumber = new google.visualization.NumberFormat({
pattern: '#,##0'
});
bars = container.getElementsByTagName('rect');
for (var i = 0; i < bars.length; i++) {
switch (bars[i].getAttribute('fill')) {
case '#a52714':
case '#0f9d58':
rowWidth = parseFloat(bars[i].getAttribute('width'));
if (rowWidth > 2) {
rowBottom = data.getValue(rowIndex, 1);
rowTop = data.getValue(rowIndex, 3);
rowValue = rowTop - rowBottom;
rowBalance = Math.max(rowBottom, rowTop);
positionY = chartLayout.getYLocation(rowBalance) - 6;
positionX = parseFloat(bars[i].getAttribute('x'));
// row value
annotation = container.getElementsByTagName('svg')[0].appendChild(container.getElementsByTagName('text')[0].cloneNode(true));
annotation.textContent = formatNumber.formatValue(rowValue);
annotation.setAttribute('x', (positionX + (rowWidth / 2)));
annotation.setAttribute('y', positionY);
annotation.setAttribute('font-weight', 'bold');
// annotation column
annotation = container.getElementsByTagName('svg')[0].appendChild(container.getElementsByTagName('text')[0].cloneNode(true));
annotation.textContent = data.getValue(rowIndex, 5);
annotation.setAttribute('x', (positionX + (rowWidth / 2)));
annotation.setAttribute('y', positionY - 18);
annotation.setAttribute('font-weight', 'bold');
rowIndex++;
}
break;
}
}
});
chart.draw(data, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
I am not a javascript developer not even expert in ajax, just a no vice desktop developer , I would really appreciate if you can show me how can I connect MCU returning json data to a web page that uses google gauge running on client on local network at home.
So I have implemented a simple Arduino based web sever that returns data in below format:
{“arduino”:
[
{“location”:”outdoor”,”temperature”:”15.55″},
{“location”:”outdoor”,”humidity”:”15″}
]
}
I want to be able to show live temperature without having to refresh the whole page: I came across with google gauge example.
I have modified the example in the link below to display temperature and humidity separate gauge:
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['gauge']});
google.charts.setOnLoadCallback(drawGauge);
var gaugeOptions = {min: 0, max: 280, yellowFrom: 200, yellowTo: 250,
redFrom: 250, redTo: 280, minorTicks: 5};
var gauge;
function drawGauge() {
gaugeData = new google.visualization.DataTable();
gaugeData.addColumn('number', 'Temperature');
gaugeData.addColumn('number', 'Humidity');
gaugeData.addRows(2);
gaugeData.setCell(0, 0, 120);
gaugeData.setCell(0, 1, 80);
gauge = new google.visualization.Gauge(document.getElementById('gauge_div'));
gauge.draw(gaugeData, gaugeOptions);
}
function changeTemp(dir) {
gaugeData.setValue(0, 0, gaugeData.getValue(0, 0) + dir * 25);
gauge.draw(gaugeData, gaugeOptions);
}
function changeHumid(dir) {
gaugeData.setValue(0, 1, gaugeData.getValue(0, 1) + dir * 20);
gauge.draw(gaugeData, gaugeOptions);
}
</script>
</head>
<body>
<div id="gauge_div" style="width:280px; height: 140px;"></div>
<small>Change</small>
<input type="button" value="Temperature" onclick="changeTemp(1)" />
<input type="button" value="Humidity" onclick="changeHumid(1)" />
</body>
</html>
Now I want the change temperate and change Humidity functions should execute after 5 sec displaying latest data from the json returned by executing the MCU bee server URL ? How can I implement that ?
Well, I figured it out, after lots of digging, I finally have something working before I finish my vacation.
below code works and displays the latest value in my google gauge and it refreshes after every 15 seconds, same principle I can apply on json data I have put as sample in the Opening post.
<script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js'></script>
<script type='text/javascript' src='https://www.google.com/jsapi'></script>
<script type='text/javascript'>
// set your channel id here
var channel_id = 166617;
// set your channel's read api key here if necessary
var api_key = 'ZCUB611J8M8ELM9M';
// maximum value for the gauge
var max_gauge_value = 70;
// name of the gauge
var gauge_name = 'Temperature';
// global variables
var chart, charts, data;
var public_key = 'dZ4EVmE8yGCRGx5XRX1W';
// load the google gauge visualization
google.load('visualization', '1', {packages:['gauge']});
google.setOnLoadCallback(initChart);
// display the data
function displayData(point) {
data.setValue(0, 0, gauge_name);
data.setValue(0, 1, point);
chart.draw(data, options);
}
// load the data
function loadData() {
// variable for the data point
var p;
// JSONP request
var jsonData = $.ajax({
url: 'https://data.sparkfun.com/output/' + public_key + '.json',
data: {page: 1},
dataType: 'jsonp',
}).done(function (results){
// get the data last value
p = results[results.length - 1].tempf;
// if there is a data point display it
if (p) {
displayData(p);
}
});
}
// initialize the chart
function initChart() {
data = new google.visualization.DataTable();
data.addColumn('string', 'Label');
data.addColumn('number', 'Value');
data.addRows(1);
chart = new google.visualization.Gauge(document.getElementById('gauge_div'));
options = {width: 120, height: 120, greenFrom: 10, greenTo: 29, redFrom: 41, redTo: 70, yellowFrom:30, yellowTo: 40, minorTicks: 5};
loadData();
// load new data every 15 seconds
setInterval('loadData()', 15000);
}
</script>
In order to retreive temperature and humidity, you can do (using jquery):
function repeat() {
$.get( "YOUR_WEB_SERVER_JSON_URL", function( data ) {
gaugeData.setValue(0, 0, data.arduino[0].temperature);
gaugeData.setValue(0, 1, data.arduino[1].humidity);
gauge.draw(gaugeData, gaugeOptions);
setTimeout(repeat, 5000);
});
I've set up a simple example for you, check it out here.
I created a sample fiddle for you:
google.charts.load('current', {
'packages': ['gauge']
});
google.charts.setOnLoadCallback(drawGauge);
var gaugeOptions = {
min: 0,
max: 280,
yellowFrom: 200,
yellowTo: 250,
redFrom: 250,
redTo: 280,
minorTicks: 5
};
var gauge;
var gaugeData;
function drawGauge() {
gaugeData = new google.visualization.DataTable();
gaugeData.addColumn('number', 'Temperature');
gaugeData.addColumn('number', 'Humidity');
gaugeData.addRows(2);
gaugeData.setCell(0, 0, 120);
gaugeData.setCell(0, 1, 80);
gauge = new google.visualization.Gauge(document.getElementById('gauge_div'));
gauge.draw(gaugeData, gaugeOptions);
repeat();
}
function repeat() {
var dir = Math.floor((Math.random() * 10) + 1);
gaugeData.setValue(0, 0, dir * 25);
gaugeData.setValue(0, 1, dir * 20);
gauge.draw(gaugeData, gaugeOptions);
setTimeout(repeat, 5000);
}
Repeat function is going to be executed every 5 seconds. In a sample fiddle it gets some random number from 1 to 10 and updates charts with this value multiplied by 25 and 20. In your scenario, you should make a call to your web server, parse the response, get values for temperature and humidity and update the charts. Please let me know if you need help on this too.
Is there any plugin who give's the chart type = ODOMETER ?
incrideble how is so hard to find this, even highchart's that i'm using ( very good chart library ) dont have a odometer, dont know why.
i found some "speedometer", Demo but wont help-me.
anyone know any plugin or something like who work with odometer's ?
Thanks.
Google Charts
Super easy to use and well documented.
google.charts.load('current', {'packages':['gauge']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Label', 'Value'],
['Memory', 80],
['CPU', 55],
['Network', 68]
]);
var options = {
width: 400, height: 120,
redFrom: 90, redTo: 100,
yellowFrom:75, yellowTo: 90,
minorTicks: 5
};
var chart = new google.visualization.Gauge(document.getElementById('chart_div'));
chart.draw(data, options);
setInterval(function() {
data.setValue(0, 1, 40 + Math.round(60 * Math.random()));
chart.draw(data, options);
}, 13000);
setInterval(function() {
data.setValue(1, 1, 40 + Math.round(60 * Math.random()));
chart.draw(data, options);
}, 5000);
setInterval(function() {
data.setValue(2, 1, 60 + Math.round(20 * Math.random()));
chart.draw(data, options);
}, 26000);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div" style="width: 400px; height: 120px;"></div>
Let this question up-to-date. New features from highcharts, i was looking for this, and now they have available:
Highcharts gauge-speedometer
Javascript speedometer plugin is available.
https://github.com/rmanivannan/speedometer-jquery-plugin
may be this could help
Watch the CPU and memory gauges for a second. They move dynamically.
The example code shown below does not move the gauges like that (or at least when I tried it in my own project.)
How do I to get it moving dynamically like that?
(Also, will these gauges slow down my site connecting to Google? On the other hand, will it bring up my rankings?)
The example code and the actual demo are different. Try this instead:
<html>
<head>
<script type='text/javascript' src='http://www.google.com/jsapi'></script>
<script type='text/javascript'>
google.load('visualization', '1', {packages:['gauge']});
google.setOnLoadCallback(drawChart);
</script>
</head>
<body>
<div id='chart_div'></div>
<script type="text/javascript">
function Timer(){this.t={};this.tick=function(a,b){this.t[a]=[(new Date).getTime(),b]};this.tick("start")}var loadTimer=new Timer;window.jstiming={Timer:Timer,load:loadTimer};if(window.external&&window.external.pageT)window.jstiming.pt=window.external.pageT;if(window.jstiming)window.jstiming.report=function(g,d){var c="";if(window.jstiming.pt){c+="&srt="+window.jstiming.pt;delete window.jstiming.pt}if(window.external&&window.external.tran)c+="&tran="+window.external.tran;var a=g.t,h=a.start;delete a.start;var i=[],e=[];for(var b in a){if(b.indexOf("_")==0)continue;var f=a[b][1];if(f)a[f][0]&&e.push(b+"."+(a[b][0]-a[f][0]));else h&&i.push(b+"."+(a[b][0]-h[0]))}if(d)for(var j in d)c+="&"+j+"="+d[j];(new Image).src=["http://csi.gstatic.com/csi?v=3","&s=gviz&action=",g.name,e.length?"&it="+e.join(",")+c:c,"&rt=",i.join(",")].join("")};
</script>
<script type="text/javascript">
var csi_timer = new window.jstiming.Timer();
csi_timer.name = 'docs_gauge';
google.setOnLoadCallback(drawChart);
function drawChart() {
csi_timer.tick('load');
var data = new google.visualization.DataTable();
data.addColumn('string', 'Label');
data.addColumn('number', 'Value');
data.addRows(3);
data.setValue(0, 0, 'Memory');
data.setValue(0, 1, 80);
data.setValue(1, 0, 'CPU');
data.setValue(1, 1, 55);
data.setValue(2, 0, 'Network');
data.setValue(2, 1, 68);
csi_timer.tick('data');
var chart = new google.visualization.Gauge(document.getElementById('chart_div'));
csi_timer.tick('new');
var options = {width: 400, height: 120, redFrom: 90, redTo: 100,
yellowFrom:75, yellowTo: 90, minorTicks: 5};
chart.draw(data, options);
csi_timer.tick('draw');
window.jstiming.report(csi_timer);
setInterval(function() {
data.setValue(0, 1, 40 + Math.round(60 * Math.random()));
chart.draw(data, options);
}, 13000);
setInterval(function() {
data.setValue(1, 1, 40 + Math.round(60 * Math.random()));
chart.draw(data, options);
}, 5000);
setInterval(function() {
data.setValue(2, 1, 60 + Math.round(20 * Math.random()));
chart.draw(data, options);
}, 26000);
}
</script>
</body>
</html>
Their demo uses a pseudo random number generator to update the graph. It's a little misleading.
I draw the initial chart using their code and then use an ajax call to fetch the updated data as a json string - from php. Then I populate the data table and update the chart with jQuery/javascript. I haven't gotten around to making a full tutorial yet b/c it's not ready for production...
The hardest part is getting your data formatted correctly on the server-side and feeding ajax without blowing up the browser. The code appears to be really fast and when you're monitoring a webserver you kinda want the image rendering to be done somewhere else. It works but, at this point, it's still not completely browser agnostic - which is why I chose to use re-write in jQuery.
As far as I know, your page rankings are unrelated...
All of the solutions are using random generated number to animate the gauge for demo. What if you want to show a real value AND animate it at the same time?
Here is the solution:
Code it yourself on JSFiddle
function isEven(n) {
return n % 2 == 0;// true|false
}
google.charts.load('current', {'packages':['gauge']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Label', 'Value'],
['Memory', 80],
['CPU', 55],
['Network', 68]
]);
var options = {
width: 400, height: 120,
redFrom: 90, redTo: 100,
yellowFrom:75, yellowTo: 90,
minorTicks: 5
};
var chart = new google.visualization.Gauge(document.getElementById('chart_div'));
chart.draw(data, options);
// Animate Gauges: (ArrayNum(start:0), ColumnInThatArray(start:0), NewValue)
// OR in anoher words(rowIndex, columnIndex, NewValue)
setInterval(function() {
var chartValue = data.getValue(0, 1);
if (isEven(chartValue)){
data.setValue(0, 1, (chartValue + 5));
} else {
data.setValue(0, 1, (chartValue - 5));
}
chart.draw(data, options);
}, 450);// milisecond
setInterval(function() {
var chartValue = data.getValue(1, 1);
if (isEven(chartValue)){
data.setValue(1, 1, (chartValue + 1));
} else {
data.setValue(1, 1, (chartValue - 1));
}
chart.draw(data, options);
}, 600);// milisecond
setInterval(function() {
var chartValue = data.getValue(2, 1);
if (isEven(chartValue)){
data.setValue(2, 1, (chartValue + 3));
} else {
data.setValue(2, 1, (chartValue - 3));
}
chart.draw(data, options);
}, 1000);// milisecond
}