As said in the title, I'm trying to create a Javascript library from scratch which has to adjust the output of a chart created with Google Chart.
To explain better, Instead of doing this:
var options = {
title: 'Top Consuming Nations - Thousand barrels daily',
hAxis: {title: 'Year'},
width: 1050, height : 400,
vAxes: [
{title: 'Top Countries', titleTextStyle: {color: '#FF0000'}, maxValue: max}, // Left axis maxValue: 60000
{title: 'Total World', titleTextStyle: {color: '#FF0000'}, maxValue: tot} // Right
],
series:{
6: {targetAxisIndex: 1}
},
legend: { position: 'top', alignment: 'start' },
};
var chart = new google.visualization.LineChart(document.getElementById(chartDiv));
chart.draw(data, options);
I want to do something like this with a library created by me (skewedChart):
var options = {
title: 'Top Consuming Nations - Thousand barrels daily',
hAxis: {title: 'Year'},
width: 1050, height : 400,
vAxes: [
{title: 'Top Countries', titleTextStyle: {color: '#FF0000'}, maxValue: max}, // Left axis maxValue: 60000
{title: 'Total World', titleTextStyle: {color: '#FF0000'}, maxValue: tot} // Right
],
series:{
6: {targetAxisIndex: 1}
},
legend: { position: 'top', alignment: 'start' },
skew: 1
};
var chart = skewedChart.visualization.LineChart(document.getElementById(chartDiv));
chart.draw(data, options);
This is the code of my library, contained in the file skewedChart.js:
var skewedChart = {};
skewedChart.visualization = {};
skewedChart.visualization.LineChart = function(location) {
this.chart = new google.visualization.LineChart(location) ;
this.draw = function(data,option) {
option.height = this.skewHeight(option.width, option.skew) ;
option.vAxes[0].maxValue = this.skewMax(option.vAxes[0],option.skew) ;
this.chart.draw(data,option);
}
this.skewHeight= function(width,skewFactor) {
}
this.skewMax= function(series, skewFactor) {
}
};
The problem is that the chart returns "undefined", why? How can I do it better?
If you do not return anything from a function call it returns undefined which is what you are seeing. You need to add return this; at the end of your function.
Related
I've been trying to add annotations to google bar chart. I've seen related questions about this, but can't solve it. There are 2 bar in charts and i want to show numbers on bars. I added 2 annotation column to my datatable. Chart draw works without annotations and there is no error at console. So i need some help. Here is my code:
var options = {
chart: {
title: 'xxxx',
subtitle: 'xxxx',
focusTarget:'category'
},
annotations: {
textStyle: {
color: 'black',
fontSize: 11,
},
alwaysOutside: true
},
height:300,
vAxis: {format: 'short'},
colors: ['#17807E', '#4285F4']
};
function drawAudits(Data) //data comes from another function with ajax call
{
var dataTbl = new google.visualization.DataTable();
dataTbl.addColumn('string', 'Months');
dataTbl.addColumn('number', 'Scheduled');
dataTbl.addColumn('number', 'Done');
dataTbl.addColumn({ type:'number' , role: 'annotation' });
dataTbl.addColumn({ type:'number' , role: 'annotation' });
for (var i = 0; i < Data.length; i++)
{
dataTbl.addRow([Data[i].month, Data[i].AllAudits, Data[i].DoneAudits, Data[i].AllAudits, Data[i].DoneAudits]);
} //last 2 column for annotations
var chart = new google.charts.Bar(document.getElementById('columnChartDiv'));
chart.draw(dataTbl,options);
}
thanks in advance.
annotations.* are not supported by Material charts, along with several other options...
see --> Tracking Issue for Material Chart Feature Parity #2143
the following option will style Core charts, similar to Material...
theme: 'material'
note: the annotation column should directly follow the series it represents...
see following working snippet...
google.charts.load('current', {
callback: function () {
var options = {
annotations: {
textStyle: {
color: 'black',
fontSize: 11,
},
alwaysOutside: true
},
chartArea: {
left: 36,
width: '100%'
},
colors: ['#17807E', '#4285F4'],
focusTarget:'category',
height:300,
legend: {
position: 'bottom'
},
theme: 'material',
title: 'xxxx',
vAxis: {
format: 'short',
viewWindow: {
max: 12
}
},
};
drawAudits();
window.addEventListener('resize', drawAudits, false);
function drawAudits(Data) {
var dataTbl = new google.visualization.DataTable();
dataTbl.addColumn('string', 'Months');
dataTbl.addColumn('number', 'Scheduled');
dataTbl.addColumn({ type:'number' , role: 'annotation' });
dataTbl.addColumn('number', 'Done');
dataTbl.addColumn({ type:'number' , role: 'annotation' });
Data = [
{month: 'Jan', AllAudits: 10, DoneAudits: 5},
{month: 'Feb', AllAudits: 10, DoneAudits: 6}
];
for (var i = 0; i < Data.length; i++) {
dataTbl.addRow([Data[i].month, Data[i].AllAudits, Data[i].AllAudits, Data[i].DoneAudits, Data[i].DoneAudits]);
}
var chart = new google.visualization.ColumnChart(document.getElementById('columnChartDiv'));
chart.draw(dataTbl,options);
}
},
packages: ['corechart']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="columnChartDiv"></div>
I am using google charts and showing 3 tooltips by default when chart is loaded for that i have used
tooltip: { trigger: 'selection' },
aggregationTarget: 'none',
selectionMode: 'multiple'
Every thing is working fine but when the points get very close to each other like (1,1) and (1,1.5) the tool tips comes over each other please see this image. Is there any option or a way to overcome this.
google.charts.load('current', {
packages: ['corechart']
}).then(drawScatterChart);
function drawScatterChart() {
var data = new google.visualization.DataTable();
data.addColumn('number', 'brand');
data.addColumn('number', 'store');
data.addColumn({
type: 'string',
role: 'tooltip'
});
data.addColumn({
type: 'string',
role: 'style'
});
var datarows = "";
var json = JSON.parse('[{"store":4.73977695167286,"brand":4.95353159851301,"empty":false,"tooltip":true,"tooltiptext":"Alpha Bravo"},{"store":0.362526138475839,"brand":0.835487337360595,"empty":false,"tooltip":true,"tooltiptext":"Avg. For Age"},{"store":0.598803222730479,"brand":1.14256989262171,"empty":false,"tooltip":true,"tooltiptext":"Franchisee Avg."},{"store":0.0929368029739777,"brand":0.288104089219331,"empty":false,"tooltip":true,"tooltiptext":"Andrew Richardson"},{"store":4.64684014869888,"brand":7.00743494423792,"empty":false,"tooltip":true,"tooltiptext":"April Singer"},{"store":4.64684014869888,"brand":7.00743494423792,"empty":false,"tooltip":true,"tooltiptext":"April Singer"}]');
$.each(json, function(ind, ele) {
//Every row given must be either null or an array.
var arr = [];
//'point {stroke-color: #A3A3A3; stroke-width: 0; fill-color: none;');/
if (ele.empty == true) {
arr.push(ele.brand, ele.store, "", 'point {stroke-color: #A3A3A3; stroke-width: 0; fill-color: none;'); //" Franchise Avg. ");fill-color: #a52714;
} else {
if (ele.tooltip == true) {
datarows += ind + ",";
}
arr.push(ele.brand, ele.store, ele.tooltiptext, 'point {stroke-color: #A3A3A3; stroke-width: 1'); //" Franchise Avg. ");fill-color: #a52714;
}
data.addRows([arr]);
});
var container = document.getElementById('chart_div');
var chart = new google.visualization.ScatterChart(container);
var options = {
width: 500,
height: 440,
legend: 'none',
hAxis: {
title: 'Brand Engagement',
gridlines: {
count: 11
}
}, //, minValue: 0
vAxis: {
title: 'Performance',
gridlines: {
count: 11
}
}, //, minValue: 0
backgroundColor: 'none',
colors: ['#fff'],
chartArea: {
left: 50,
top: 20,
width: "80%",
height: "87%"
},
tooltip: {
isHtml: true,
trigger: 'selection'
},
aggregationTarget: 'none',
pointSize: 5,
selectionMode: 'multiple',
};
google.visualization.events.addListener(chart, 'ready', setChartSelection);
function setChartSelection() {
var arrRows = datarows.split(",");
chart.setSelection([{
row: arrRows[0],
column: 1
},
{
row: arrRows[1],
column: 1
},
{
row: arrRows[2],
column: 1
}
]);
}
chart.draw(data, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="chart_div" style="float: left;">
</div>
there are no options you can set to avoid overlap...
a possible solution would be to use the explorer option to pan and zoom
explorer: {
actions: ['dragToZoom', 'rightClickToReset']
}
see following working snippet, when the chart loads,
use the mouse to draw a square around the two points on the lower left,
once zoomed, both tooltips are displayed fully...
google.charts.load('current', {
packages: ['corechart']
}).then(drawScatterChart);
function drawScatterChart() {
var data = new google.visualization.DataTable();
data.addColumn('number', 'brand');
data.addColumn('number', 'store');
data.addColumn({
type: 'string',
role: 'tooltip'
});
data.addColumn({
type: 'string',
role: 'style'
});
var datarows = "";
var json = JSON.parse('[{"store":4.73977695167286,"brand":4.95353159851301,"empty":false,"tooltip":true,"tooltiptext":"Alpha Bravo"},{"store":0.362526138475839,"brand":0.835487337360595,"empty":false,"tooltip":true,"tooltiptext":"Avg. For Age"},{"store":0.598803222730479,"brand":1.14256989262171,"empty":false,"tooltip":true,"tooltiptext":"Franchisee Avg."},{"store":0.0929368029739777,"brand":0.288104089219331,"empty":false,"tooltip":true,"tooltiptext":"Andrew Richardson"},{"store":4.64684014869888,"brand":7.00743494423792,"empty":false,"tooltip":true,"tooltiptext":"April Singer"},{"store":4.64684014869888,"brand":7.00743494423792,"empty":false,"tooltip":true,"tooltiptext":"April Singer"}]');
$.each(json, function(ind, ele) {
//Every row given must be either null or an array.
var arr = [];
//'point {stroke-color: #A3A3A3; stroke-width: 0; fill-color: none;');/
if (ele.empty == true) {
arr.push(ele.brand, ele.store, "", 'point {stroke-color: #A3A3A3; stroke-width: 0; fill-color: none;'); //" Franchise Avg. ");fill-color: #a52714;
} else {
if (ele.tooltip == true) {
datarows += ind + ",";
}
arr.push(ele.brand, ele.store, ele.tooltiptext, 'point {stroke-color: #A3A3A3; stroke-width: 1'); //" Franchise Avg. ");fill-color: #a52714;
}
data.addRows([arr]);
});
var container = document.getElementById('chart_div');
var chart = new google.visualization.ScatterChart(container);
var options = {
width: 500,
height: 440,
legend: 'none',
hAxis: {
title: 'Brand Engagement',
gridlines: {
count: 11
}
}, //, minValue: 0
vAxis: {
title: 'Performance',
gridlines: {
count: 11
}
}, //, minValue: 0
backgroundColor: 'none',
colors: ['#fff'],
chartArea: {
left: 50,
top: 20,
width: "80%",
height: "87%"
},
tooltip: {
isHtml: true,
trigger: 'selection'
},
aggregationTarget: 'none',
pointSize: 5,
selectionMode: 'multiple',
explorer: {
actions: ['dragToZoom', 'rightClickToReset']
}
};
google.visualization.events.addListener(chart, 'ready', setChartSelection);
function setChartSelection() {
var arrRows = datarows.split(",");
chart.setSelection([{
row: arrRows[0],
column: 1
},
{
row: arrRows[1],
column: 1
},
{
row: arrRows[2],
column: 1
}
]);
}
chart.draw(data, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="chart_div" style="float: left;">
</div>
I have a google visualisation linechart. I am having issues formatting the labels on the h-axis. I would like to have them rounded off to integers so it looks neater. I have looked at the documentation but could not find a solution. Here is my code:
HTML
<div id="myChart2" name="myChart2" width="500" height="280"></div>
jQuery
$(document).ready(function(){
var chartData = new google.visualization.DataTable();
chartData.addColumn('number', 'SPS');
chartData.addColumn('number', 'WGT');
var chartdatax = ["47", "47", "38", "35", "35"];
var chartdatay = ["1500", "2300", "2300", "1950", "1500"];
for (var i = 0; i < chartdatax.length; i++) {
chartData.addRow([parseFloat(chartdatax[i]), parseFloat(chartdatay[i])]);
};
options2 = {
height: 500,
hAxis: {
title: 'SPS',
gridlines: {
count: 15
}
},
vAxis: {
title: 'WGT',
gridlines: {
count: 15
}
},
chartArea: {
top: 40,
width: "70%",
height: "75%"
},
legend: {
position: 'none'
},
pointSize: 5
};
myLineChart = new google.visualization.LineChart(document.getElementById('myChart2'));
myLineChart.draw(chartData, options2);
});
JSFiddle: https://jsfiddle.net/rdawkins/w83mdx3y/2/
You can add format:'#,###' to your hAxis object:
hAxis: {
format:'#,###',
title: 'SPS',
gridlines: {
count: 15
}
},
Here's an updated version of your fiddle: https://jsfiddle.net/w83mdx3y/3/
See customizing axes in the charts documentation for more information on how this works.
I want to visualize some timeseries data in the browser with jqplot. My problem is, that the x-axis values overlay and aren't readable.
Therefore, the zoom function would be very useful. But it doesn't work.
Please have a look at the fiddle, it doesn't run on firefox, just on google chrome:
http://jsbin.com/onufih/9/edit
Here's my code:
function getTicks() {
var ticks = [];
for (var i = 0; i < data.length; i++) {
var item = data[i];
var dateStr = item[0];
ticks.push(dateStr);
}
return ticks;
}
var overviewChart = $.jqplot('overviewChart', [data], {
title: 'Rotated Axis Text',
axes: {
xaxis: {
renderer: $.jqplot.DateAxisRenderer,
rendererOptions: {
tickRenderer: $.jqplot.CanvasAxisTickRenderer
},
ticks: getTicks(),
tickOptions: {
formatString: '%#m/%#d/%y - %#H h - %#M m - %#S s',
fontSize: '10pt',
fontFamily: 'Tahoma',
angle: -40
}
},
yaxis: {
rendererOptions: {
tickRenderer: $.jqplot.CanvasAxisTickRenderer
},
tickOptions: {
fontSize: '10pt',
fontFamily: 'Tahoma',
angle: 30
}
}
},
series: [{
lineWidth: 4,
markerOptions: {
style: 'square'
}
}],
cursor: {
zoom: true,
looseZoom: true
}
});
}
You need to add show: true to your cursor, as in this example.
It's not working because you have specified the "ticks" option. I'm having the same issue. Seems to me this should work as expected even when I set the ticks (as an initial "un-zoomed" value).
I have a Highchart that is receiving JSON data via AJAX and jQuery. But my chart doesn't show the points until I hover the mouse over the chart. Even then the points are all at the very top of the chart. I don't think I'm adding my points to the series correctly. Please tell me what I'm doing wrong in the jsonpcallback function.
Thanks!
<script type="text/javascript">
<!-- Begin Chart options-->
// define the options
var options = {
chart: {renderTo: 'container'},
title: {text: 'Brewery'},
subtitle: {text: ' '},
xAxis: {text: 'Time',type: 'datetime'},
yAxis: [{ // left y axis
title: {text: 'Temperature (℉)'},
labels: {align: 'left', x: 3, y: 16,
formatter: function() {
return Highcharts.numberFormat(this.value, 0);}
},
showFirstLabel: false},
{ // right y axis
linkedTo: 0, gridLineWidth: 0, opposite: true,
title: {text: 'Temperature (℉)'},
labels: {align: 'right', x: -3, y: 16,
formatter: function() {
return Highcharts.numberFormat(this.value, 0);}
},
showFirstLabel: false
}],
legend: {align: 'left', verticalAlign: 'top', y: 20,
floating: true, borderWidth: 0},
tooltip: {shared: true, crosshairs: true},
plotOptions: { series: {cursor: 'pointer',
point: {events: {
click: function() {
hs.htmlExpand(null, {
pageOrigin: {
x: this.pageX,
y: this.pageY
},
headingText: this.series.name,
maincontentText: Highcharts.dateFormat('%A, %b %e, %Y', this.x) +':<br/> '+
this.y +'(℉)',
width: 200});
}}},
marker: {lineWidth: 1}}},
series: [ {name: 'Hot Liqour Tank'},
{name: 'MashTun'},
{name: 'Brew Kettle'},
{name: 'Post Chiller'},
{name: 'Control Box'}
]
};
<!-- End Chart Options -->
var chart;
//after DOM is loaded setup timeout to call the ajax method
$(document).ready(function() {
//call function to render the chart and setup the options
renderChart();
});
//this function requests the data
function reqData(){
$.ajax({
url: "http://192.168.0.11/"+Math.random(),
dataType: "jsonp",
jsonp: "callback",
jsonpCallback: "jsonpcallback"
});
}
function jsonpcallback(rtndata) {
for(var i = 0; i < rtndata.length; i++){
if(rtndata[i].sensor=="hlt")
{
chart.series[0].addPoint([rtndata[i].time, rtndata[i].temp]);
}
else if(rtndata[i].sensor=="mt")
{
chart.series[1].addPoint([rtndata[i].time, rtndata[i].temp]);
}
else if(rtndata[i].sensor=="bk")
{
chart.series[2].addPoint([rtndata[i].time, rtndata[i].temp]);
}
else if(rtndata[i].sensor=="pc")
{
chart.series[3].addPoint([rtndata[i].time, rtndata[i].temp]);
}
else if(rtndata[i].sensor=="box")
{
chart.series[4].addPoint([rtndata[i].time, rtndata[i].temp]);
}
}
}
function renderChart(){
chart = new Highcharts.Chart(options);
}
//continually poll for data
setInterval(reqData, 5000);
</script>
I think you are nearly there; the only piece i believe you are missing is an initial call to your regData function from the chart's load event.
So to your second line after define the options, change this line:
chart: {renderTo: 'container'},
to this:
chart: {renderTo: 'container', events: {load: regData}},
Try converting the time strings to Javascript datetime objects. Highcharts will then read the datetimes correctly. For example, if the JSON date is in the format 'YYYY-MM-DD' you can use this code:
var dates = [];
$.each(jsondata[0], function(itemNo, item) {
year = parseInt(item.split('-')[0], 10);
month = parseInt(item.split('-')[1], 10);
day = parseInt(item.split('-')[2], 10);
dt = Date.UTC(parseInt(year), parseInt(month), parseInt(day));
series[0].data.push([dt, parseInt(jsondata[2][itemNo], 10)]);
series[1].data.push([dt, parseInt(jsondata[1][itemNo], 10)]);
dates.push(dt);
});
options.series = series;