I am using Google Charts to display some data related to the performance of a web page (bounce rate, volume, etc). When I make changes to the page (for example changing the color of a button), I keep track of that using small notes (for example: 'week 15 2014: button is now green').
I'd like to display these notes (with a hover-over function to display the text) IN the chart. So vertically they should be at the right location (right week). Horizontally it doesn't matter where they're placed, on top or bottom would be most logical. What would be the best approach to succeed in doing so?
JSFiddle of my current chart: http://jsfiddle.net/9qukjbhg/
google.load("visualization", "1", {
packages: ["corechart"]
});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Interval', 'Bounce Rate', 'Call to Action Succeed', 'Total Volume'],
['week 36', 0.3283, 0.4328, 67],
['week 37', 0.2857, 0.4167, 84],
['week 38', 0.1562, 0.5417, 96],
['week 39', 0.275, 0.4125, 80],
['week 40', 0.2615, 0.4154, 65],
['week 41', 0.2213, 0.3588, 131],
['week 42', 0.2232, 0.5, 112],
['week 43', 0.3476, 0.3898, 118],
['week 44', 0.3025, 0.4118, 119],
['week 45', 0.294, 0.3897, 136],
['week 46', 0.2043, 0.4286, 49]
]);
var formatter = new google.visualization.NumberFormat({
pattern: '#,###%'
});
formatter.format(data, 1);
formatter.format(data, 2);
var options = {
vAxes: {
0: {
format: '#,###%'
},
gridlines: {
color: 'transparent'
}
},
1: {
gridlines: {
color: 'transparent'
}
},
series: {
0: {
targetAxisIndex: 0,
type: 'bars'
},
1: {
targetAxisIndex: 0,
type: 'bars'
},
2: {
targetAxisIndex: 1
}
},
title: 'Page performance per week'
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
What I try to do (something like this, see the note on the right top of the image):
Who can point me in the right direction? Many thanks in advance!
Related
I'm working on a small HTML application for my website that does some simulations and plots it to a graph (using Google Charts). All of the data will originate in the JavaScript code on the page (i.e. I'm not trying to pull in data from a database or anything like that). For this reason, I would like to have access to the data table from other functions so the data can be updated when a new simulation is run.
What I'm running into is that if I build a data table (and data view) inside of the drawChart() function, everything works fine. See this jsfiddle or the following code:
//Google charts stuff
google.charts.load('current', { 'packages': ['line', 'corechart'] });
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var forceChartDiv = document.getElementById('force_chart_div');
var sim_data = new google.visualization.DataTable();
sim_data.addColumn('number', 'Elapsed Time (sec)');
sim_data.addColumn('number', "Total Force");
sim_data.addColumn('number', "M1 Force(Each)");
sim_data.addRows([
[0.0, -.5, 5.7],
[0.1, .4, 8.7],
[0.2, .5, 12]
]);
var forceDataView = new google.visualization.DataView(sim_data);
forceDataView.setColumns([0, 1, 2]);
var forceChartOptions = {
chart: {title: 'Simulation Results: Force'},
width: 900,
height: 500,
series: {
// Gives each series an axis name that matches the Y-axis below.
0: { axis: 'Total' },
1: { axis: 'Individual' }
},
axes: {
// Adds labels to each axis; they don't have to match the axis names.
y: {
Total: { label: 'Total Force (Newtons)'},
Individual: { label: 'Per-Motor Force (Newtons)'}
}
}
};
var forceChart = new google.charts.Line(forceChartDiv);
forceChart.draw(forceDataView, google.charts.Line.convertOptions(forceChartOptions));
}
But if I move the code for the creation of the data table and data view outside of the function scope, it doesn't work. See this jsfiddle or the following code:
var sim_data;
var forceDataView;
//Google charts stuff
google.charts.load('current', { 'packages': ['line', 'corechart'] });
sim_data = new google.visualization.DataTable();
sim_data.addColumn('number', 'Elapsed Time (sec)');
sim_data.addColumn('number', "Total Force");
sim_data.addColumn('number', "M1 Force(Each)");
sim_data.addRows([
[0.0, -0.5, 5.7],
[0.1, 0.4, 8.7],
[0.2, 0.5, 12]
]);
forceDataView = new google.visualization.DataView(sim_data);
forceDataView.setColumns([0, 1, 2]);
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var forceChartDiv = document.getElementById('force_chart_div');
var forceChartOptions = {
chart: {title: 'Simulation Results: Force'},
width: 900,
height: 500,
series: {
// Gives each series an axis name that matches the Y-axis below.
0: { axis: 'Total' },
1: { axis: 'Individual' }
},
axes: {
// Adds labels to each axis; they don't have to match the axis names.
y: {
Total: { label: 'Total Force (Newtons)'},
Individual: { label: 'Per-Motor Force (Newtons)'}
}
}
};
var forceChart = new google.charts.Line(forceChartDiv);
forceChart.draw(forceDataView, google.charts.Line.convertOptions(forceChartOptions));
}
Both of these examples use the following HTML:
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<div id="force_chart_div"></div>
I thought it might have something to do with the execution order of the callback function. But putting it in different spots in the code doesn't seem to change anything. In my full project, I went so far as to add a button that called the drawChart() function just to check, but that didn't help either.
Depending on where I put the callback function call, I'll get a red "Data Table is not Defined" alert showing up where the chart is supposed to be on the webpage. That pretty much tells me what I already suspected, but I don't know how to fix it. Any help would be appreciated. I'm a huge JS noob, by the way, so go easy on me.
your instinct was correct, you must wait on the callback to finish,
before using the google.visualization or google.charts namespaces.
it has to do more with timing, than placement of the code.
instead of using the callback statement, we can use the promise that the load statement returns.
as in the following snippet...
var sim_data;
var forceDataView;
//Google charts stuff
google.charts.load('current', {
packages: ['line', 'corechart']
}).then(function () {
sim_data = new google.visualization.DataTable();
sim_data.addColumn('number', 'Elapsed Time (sec)');
sim_data.addColumn('number', "Total Force");
sim_data.addColumn('number', "M1 Force(Each)");
sim_data.addRows([
[0.0, -0.5, 5.7],
[0.1, 0.4, 8.7],
[0.2, 0.5, 12]
]);
forceDataView = new google.visualization.DataView(sim_data);
forceDataView.setColumns([0, 1, 2]);
});
function drawChart() {
var forceChartDiv = document.getElementById('force_chart_div');
var forceChartOptions = {
chart: {title: 'Simulation Results: Force'},
width: 900,
height: 500,
series: {
// Gives each series an axis name that matches the Y-axis below.
0: { axis: 'Total' },
1: { axis: 'Individual' }
},
axes: {
// Adds labels to each axis; they don't have to match the axis names.
y: {
Total: { label: 'Total Force (Newtons)'},
Individual: { label: 'Per-Motor Force (Newtons)'}
}
}
};
var forceChart = new google.charts.Line(forceChartDiv);
forceChart.draw(forceDataView, google.charts.Line.convertOptions(forceChartOptions));
}
I wanted to make a google chart which shows the dual y axis , but both should represents the same bar.
See this fiddle
google.charts.load('current', {'packages':['bar']});
google.charts.setOnLoadCallback(drawStuff);
function drawStuff() {
var data = new google.visualization.arrayToDataTable([
['Car', 'Distance travelled'],
["mercedes", 44],
["lamborgh", 31],
["porsche", 12],
["aston martin", 10]
]);
var options = {
title: 'Car distance',
width: 500,
legend: { position: 'none' },
chart: { subtitle: 'money spent in distance travelled' },
axes: {
x: {
0: { side: 'top', label: 'Car stats'} // Top x-axis.
}
},
bar: { groupWidth: "20%" }
};
var chart = new google.charts.Bar(document.getElementById('top_x_div'));
// Convert the Classic options to Material options.
chart.draw(data, google.charts.Bar.convertOptions(options));
};
I have shown the Cars distance traveled , thats actually in kms, now i wanted to show the cars money spent in fuel
like a car traveled 1km and it spends $2 in fuel
now looking at the fiddle suppose we have mercedes car traveled 44km then it costs around $88 which should be depicted by the 2nd y-axis
How it can be done?
each series (y-value) in the chart represents a column in the data
"series 0" = column 1 in the data
"series 1" = column 2 in the data
then use the options to map each series to an axis...
series: {
0: { axis: 'distance' },
1: { axis: 'fuel' }
},
axes: {
y: {
distance: {label: 'Distance'},
fuel: {side: 'right', label: 'Fuel'}
}
}
see following working snippet...
google.charts.load('current', {
callback: drawChart,
packages:['bar']
});
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Car', 'Distance travelled', 'Fuel'],
['mercedes', 44, 88],
['lamborgh', 31, 62],
['porsche', 12, 24],
['aston martin', 10, 20]
]);
var options = {
title: 'Car distance',
height: 500,
legend: { position: 'none' },
chart: { subtitle: 'money spent in distance travelled' },
bar: { groupWidth: "20%" },
series: {
0: { axis: 'distance' },
1: { axis: 'fuel' }
},
axes: {
x: {
0: { side: 'top', label: 'Car stats'} // Top x-axis.
},
y: {
distance: {label: 'Distance'},
fuel: {side: 'right', label: 'Fuel'}
}
}
};
var chart = new google.charts.Bar(document.getElementById('chart_div'));
chart.draw(data, options);
};
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
EDIT
to remove the second bar but keep the axis requires a bit of manipulation
and use of options not available to material charts
see following working snippet using a core chart...
google.charts.load('current', {
callback: drawChart,
packages:['bar', 'corechart']
});
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Car', 'Distance travelled'],
['mercedes', 44],
['lamborgh', 31],
['porsche', 12],
['aston martin', 10]
]);
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, {
label: 'Fuel',
type: 'number',
calc: function () {
return null;
}
}]);
var options = {
title: 'Car distance',
height: 500,
legend: { position: 'none' },
chart: { subtitle: 'money spent in distance travelled' },
bar: { groupWidth: "20%" },
// center bar with x-axis label
isStacked: true,
// material chart theme
theme: 'material',
// y-axis settings
vAxes: {
0: {
ticks: [0, 10, 20, 30, 40, 50],
title: 'Distance'
},
1: {
ticks: [0, 20, 40, 60, 80, 100],
title: 'Fuel'
}
},
// map series
series: {
0: {
targetAxisIndex: 0
},
1: {
targetAxisIndex: 1
}
}
};
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
chart.draw(view, options);
};
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
note
material charts --> packages:['bar'] -- google.charts.Bar
core charts --> packages:['corechart'] -- google.visualization.ColumnChart
I have a plot with multiple y axes and a legend on right side.
I want only to show the y axis when the graph is selected on the legend.
I can hide the graphs when i click on the legend , but the axis are all visible.
How can i dynamically hide the y axes?
var trace1 = {
x: [1, 2, 3],
y: [40, 50, 60],
name: 'yaxis data',
type: 'scatter'
};
var trace2 = {
x: [2, 3, 4],
y: [4, 5, 6],
name: 'yaxis2 data',
yaxis: 'y2',
type: 'scatter'
};
var data = [trace1, trace2];
var layout = {
title: 'Double Y Axis Example',
yaxis: {title: 'yaxis title'},
yaxis2: {
title: 'yaxis2 title',
titlefont: {color: 'rgb(148, 103, 189)'},
tickfont: {color: 'rgb(148, 103, 189)'},
overlaying: 'y',
side: 'right'
}
};
Plotly.newPlot('myDiv', data, layout);
You can listen to the plot_restyle event and then depending how flexible (and complex) you want your code to be, you can then somehow make the axis you want to hide hidden by changing the axis' visible property to false through
Plotly.relayout('myDiv', { 'yaxis2.visible': false });
// and to undo...
Plotly.relayout('myDiv', { 'yaxis2.visible': true });
For a fully dynamic example checkout https://jsfiddle.net/bytesnz/t2y3yaa3/. Note that all the yaxis have anchor: 'free'
now i can answer my question myself.
Plotly.relayout('myDiv', 'yaxis2', null);
that deletes the 'yaxis2' from the layout.
If you want to delete the traces belong to this axis , then delete the traces first.
Plotly.deleteTraces('myDiv',[x]); // 0 delete first trace, 1 second 2 third...
Plotly.relayout('myDiv', 'yaxis2', null);
I'm looking at further improving a combo chart I created here by making it first a dual y axis combo chart then a multiple axis combo chart.
As seen here I've figured out how to create a basic combo chart using the tutorial.
google.load("visualization", "1", {
packages: [ "corechart", "bar" ]
});
google.setOnLoadCallback(drawVisualization);
function drawVisualization() {
// Some raw data (not necessarily accurate)
var data = google.visualization.arrayToDataTable([
[ 'Month', 'Col1', 'Col2', 'Col3', 'Col4', 'Col5', 'Col6' ],
[ 'Set 1', 165, 938, 522, 998, 450, 614.6 ],
[ 'Set 2', 135, 1120, 599, 1268, 288, 682 ],
[ 'Set 3', 157, 1167, 587, 807, 397, 623 ],
[ 'Set 4', 139, 1110, 615, 968, 215, 609.4 ],
[ 'Set 5', 136, 691, 629, 1026, 366, 569.6 ]
]);
var options = {
title: 'Chart title',
width: 1001,
height: 500,
vAxis: {
title: "VAxis title"
},
hAxis: {
title: "HAxis title"
},
seriesType: "bars",
series: {
5: {
type: "line"
}
}
};
var chart = new google.visualization.ComboChart(document.getElementById('number_format_chart'));
chart.draw(data, options);
}
.chartwrapper {
margin: 20px 0 12px 0;
}
#number_format_chart {
width: 100%
}
<script src="https://www.google.com/jsapi"></script>
<div class="chartwrapper">
<!--Div that will hold the bar charts -->
<div id="number_format_chart"></div>
</div>
Now moving on to changing the plain combo chart to a dual y version this is what I'm trying to achieve.
I thought adding the code below would help but no luck as the 2nd y axis isn't displayed
series: {
0: { axis: 'Col1' }, // Bind series 0 to an axis named 'distance'.
1: { axis: 'Col2' } // Bind series 1 to an axis named 'brightness'.
},
axes: {
y: {
Col1: {
label: 'leftyaxis'
}, // Left y-axis.
Col2: {
side: 'right',
label: 'rightyaxis'
} // Right y-axis.
}
}
Any help is appreciated
You're close. The way I've done it uses indexes so the axes part looks like this
vAxes: {
0: {
title: 'leftyaxis'
},
1: {
title: 'rightyaxis'
}
}
And you add something like targetAxisIndex: 0 to your series.
Fiddle
I am using the following code and while the chart loads fine, the annotations don't appear and furthermore there is no error returned.
Here is the same example in a jsfiddle. Beating my brains out over here. Thank you in advance if you can see what I cannot.
What gives?
// Load the Visualization API and the corechart package.
google.load("visualization", "1", {packages:["corechart"]});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('number', 'GIP'); // Implicit domain label col.
data.addColumn('number', 'Production Curve Percentage'); // Implicit series 1 data col.
data.addColumn({type:'string', role:'annotation'}); // annotation role col.
data.addRows([
[2.7334,0.94, 'note 1-1', ],
[1.7899,0.653, 'note 2-2', ],
[1.444,0.94, 'note 3-3', ],
[1.7704,0.789, 'note 4', ],
[1.7773,1.083, 'note 5', ],
[2.7703,1.308, 'note 6', ],
[1.7173,1.026, 'note 7', ],
]);
var options = {
title: 'GIP2 vs. performance',
annotations: {
textStyle: {
fontName: 'Times-Roman',
fontSize: 18,
bold: true,
italic: true,
color: '#871b47', // The color of the text.
auraColor: '#d799ae', // The color of the text outline.
opacity: 0.8 // The transparency of the text.
}
},
pointShape: 'circle',
pointSize: '4',
vAxis: {
title: 'Performance',
},
hAxis: {
title: "GIP",
//logScale: 'true',
//format: "####",
},
seriesType: "line",
trendlines: {
0: {
type: 'linear',
visibleInLegend: true,
visibleInLegend: true,
showR2: true,
}
}
}
var chart = new google.visualization.ScatterChart(document.getElementById('chart_GIPvsPCP'));
chart.draw(data, options);
};
Apparently Scattercharts don't support annotations yet. The easy workaround is to change:
var chart = new google.visualization.ScatterChart(document.getElementById('chart_GIPvsPCP'));
to
var chart = new google.visualization.LineChart(document.getElementById('chart_GIPvsPCP'));
and then specify:
lineWidth: 0,
to get the same effect.
Thanks Samuel Cook. Official response from Google here: https://code.google.com/p/google-visualization-api-issues/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Stars%20Modified%20Type%20Status%20Priority%20Milestone%20Owner%20Summary&groupby=&sort=&id=1817