setting google chart multiple axes from dynamically generated data - javascript

I'm trying to replicate the following code from a working example:
series: {0: {targetAxisIndex:0},
1: {targetAxisIndex:0},
2: {targetAxisIndex:1},
This is for setting which y-axis is used to plot different columns from a dataTable on a Google chart.
However I have a variable number of columns (based on user input), therefore am collecting an array of the required axis (the axisAssignment Array in the below example).
My code is below:
var series = {};
for (i=0;i<axisAssignment.length;i++)
{
series[i] = {targetAxisIndex: axisAssignment[i]};
}
return series;
However, all of my data is only being written to the left axis, despite the debugger suggesting that the object is correct. My option code is below:
var options =
{
hAxis: {title: xTitle},
vAxes: {0: {title: y1Type},
1: {title: y2Type}
},
series: calculateSeries(),
pointSize: 1,
legend: {position: 'top', textStyle: {fontSize: 10}}
};
Any assistance would be greatly apreciated.
Thanks
Tom
edit: whole file for reference (it's a work in progress so a bit of a mess I'm afraid)
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart());
function drawChart()
{
var title = "Node: "+currentNode;
var xTitle = "Date";
var yTitle = titles[currentVariable];
if (totalData !== null)
{
var tempData = newData();
var tempData2 = totalData;
dataArray[dataCount] = tempData;
var joinMark = countArray(dataCount);
totalData = google.visualization.data.join(tempData2,tempData,'full',[[0,0]],joinMark,[1]);
dataCount = dataCount+1;
}
else
{
totalData = newData();
dataArray[dataCount] = totalData;
dataCount = 1;
}
var options =
{
hAxis: {title: xTitle},
vAxes: {0: {title: y1Type},
1: {title: y2Type}
},
series: calculateSeries(),
pointSize: 0.5,
legend: {position: 'top', textStyle: {fontSize: 10}}
};
var chart = new google.visualization.ScatterChart(document.getElementById('graph'));
console.log(calculateSeries());
chart.draw(totalData, options);
function countArray(count)
{
var arrayCount= new Array();
if (count===1)
{
arrayCount[0] = count;
}
else
{
for (var i=0;i<count;i++)
{
var temp = i+1;
arrayCount[i] = temp;
}
}
return arrayCount;
}
function calculateSeries()
{
var series = {};
for (i=0;i<axisAssignment.length;i++)
{
series[i] = {targetAxisIndex: axisAssignment[i]};
}
return series;
}
function newData()
{
var dataType = dataIn[0];
dataIn.shift();
var axis = dataSelect(dataType);
axisAssignment.push(axis);
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', "Node: "+currentNode+": "+titles[currentVariable]);
var num = (dataIn.length);
data.addRows(num/2);
var i = 0;
var j = 0;
while (i<num)
{
var d = (dataIn[i]);
if (i%2===0)
{
d = new Date(d);
data.setCell(j,0,d);
i++;
}
else
{
data.setCell(j,1,parseFloat(d));
i++;
j++;
}
}
return data;
}
function dataSelect(type)
{
var axisNumber;
if (y1Type === null || y1Type === type)
{
y1Type = type;
axisNumber = 0;
}
else if (y2Type === null || y2Type === type)
{
y2Type = type;
axisNumber = 1;
}
else
{
alert("You already have 2 axes assigned.\n\nPlease clear the graph \nor select more objects of \ntype"+y1Type+" or \ntype "+y2Type+" to continue.");
axisNumber = null;
}
return axisNumber;
}
}

Ok, it seems that it's an issue with my choice of ScatterChart,
var options =
{
hAxis: {title: xTitle},
series: calculateSeries(),
vAxes: {0: {title: y1Type },
1: {title: y2Type}
},
pointSize: 0.5,
legend: {position: 'top', textStyle: {fontSize: 10}}
};
var chart = new google.visualization.LineChart(document.getElementById('graph'));
chart.draw(totalData, options);
I've changed it to LineChart and it's working fine, by keeping the pointSize option, the appearance is almost completely unchanged. Thanks for your help juvian.

Related

JS-echart-histpgram-X axis

blue is the standard, the red is current mine
compared with these two diagrams, I do not no how to design the x-axis in the blue diagram, which is a range to describe the data.
Now, I using an array to store all value displayed, and on the y-axis, another array stores the times of each number displays. But I do not know make the X-axis to be a range.
<script>
var sheetName = null;
var sheets = null;
var ageArray = new Array();
var ageTimes = new Array();
function readExcel(file_obj){
var reader = new FileReader();
var file = file_obj.files[0];
reader.readAsBinaryString(file);
reader.onload = function (e) {
var data = e.target.result;
var wb = XLSX.read(data, {type: 'binary'});
sheetName = wb.SheetNames[0] // 获取文档中第一个sheet页签的名字
sheets = wb.Sheets[sheetName] // 获sheet名页签下的数据
var json = XLSX.utils.sheet_to_json(sheets)
// console.log(sheets); // 返回sheet对象到控制台
// console.log(json.length);
// console.log(json);
for (let i = 0; i < json.length; i++) {
ageArray.push(json[i]['Age ']);
}
// console.log(ageArray);
function unique (arr) {
return Array.from(new Set(arr))
}
ageArray = unique(ageArray);
ageArray.sort(function (a,b){
if (a>b) {
return 1
} else if (a<b){
return -1
} else return 0
});
// console.log(ageArray);
// count times
let LevelList = json.map(item => {
return item['Age '];
})
let contlist = LevelList.reduce(function(prev,next){
prev[next] = (prev[next]+1) || 1;
return prev
},{});
console.log(contlist);
for (let j = 0; j < ageArray.length; j++) {
var index = ageArray[j];
// console.log(contlist[index]);//
ageTimes.push(contlist[index]);
// console.log(ageTimes);
}
var myChart = echarts.init(document.querySelector('.box'));
var option = {
title: {
text: 'ECharts'
},
tooltip: {},
legend: {
data: ['sale']
},
xAxis: {
data: ageArray,
},
yAxis: {
},
series: [
{
name: 'sale',
type: 'bar',
data: ageTimes
}
]
};
myChart.setOption(option);
};
}
</script>
<style>
.box {
width: 1000px;
height: 400px;
background-color: pink;
}
</style>
<body>
<input type="file" onchange="readExcel(this)" />
<div class="box"></div>
</body>

How to change line color based on the value [google charts]

I have a chart to represent some temperatures of a specific place, I am using Google Chart tools (area chart), and Im trying to put a diferent color (orange) if the temperature is greater than 25 degrees
Javascript code
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Data');
data.addColumn('number', 'Temperatura ºC');
data.addColumn({ type: 'number', role: 'annotation' });
var array = JSON.parse('<%=jsonStringTemp%>');
console.log(array);
for(var i=0; i<array.length;i++){
var array2=[];
for (j = 0; j < array[i].length; j++){
if (typeof array[i][j]==='string') {
if (j !== 0) {
array[i][j]=parseInt(array[i][j], 10)
}
}
array2.push(array[i][j])
}
data.addRow(array2)
}
console.log(data)
var options = {
title: 'Temperatura',
hAxis: {title: 'Data', titleTextStyle: {color: '#333'}},
vAxis: { minValue: 0 },
series: {
0: {
color: 'green'
},
},
pointSize: 6
};
;
var chart = new google.visualization.AreaChart(document.getElementById('linechart_material'));
chart.draw(data, options);
}
output
Is it possible to do it? And How?

Google charts LineGraph switching datatables and maintaining state

I have tweaked a few examples I found across the net that allow me to remove/greyout a series when it is clicked (legend or line itself).
I then wanted to add ability to switch between datatables and have what was hidden/greyedout to transfer to the new datatable.
I took the idea from switching data from https://developers.google.com/chart/interactive/docs/animation#value-changes
(my graphs are not animating correctly like the example)
My problem is I get very weird results when clicking on the "Switch" button and switching datatables, sometimes it will keep the correct selection but when you click on a different series one will magically appear or it will deselect a different series than the one clicked. I can't figure out to get it so both datatables maintain the same selection (selection meaning greyed out/removed series).
It's worth noting that
columns.push({
calc: 'stringify',
sourceColumn: i,
type: 'string',
role: 'annotation'
});
is adding hidden columns to aide in additional logic for the series. While I am not directly using it currently I want it to remain and work properly because I think I will use it in the future. These "hidden" columns add complexity where I think the bug lives.
The code is here:
var button = document.getElementById('b1');
var current = 0;
var data = [];
var chart;
var options;
var ms2 = [{
"LOCAL_ID": "W-133",
"Class1": 29,
"Class2": 3628,
"Class3": 159,
"Class4": 24,
"Class5": 65,
"Class6": 12,
"Class7": 0,
"Class8": 12,
"Class9": 110,
"Class10": 41,
"Class11": 0,
"Class12": 0,
"Class13": 0
}, {
"LOCAL_ID": "14-6A-060",
"Class1": 19,
"Class2": 290,
"Class3": 224,
"Class4": 0,
"Class5": 0,
"Class6": 0,
"Class7": 0,
"Class8": 2,
"Class9": 0,
"Class10": 0,
"Class11": 1,
"Class12": 0,
"Class13": 0
}, {
"LOCAL_ID": "45-5-006",
"Class1": 7,
"Class2": 191,
"Class3": 165,
"Class4": 0,
"Class5": 6,
"Class6": 3,
"Class7": 0,
"Class8": 4,
"Class9": 18,
"Class10": 11,
"Class11": 0,
"Class12": 0,
"Class13": 10
}];
google.charts.load('current', {
'packages': ['line']
});
google.charts.setOnLoadCallback(init);
button.onclick = function() {
current = 1 - current;
button.disabled = true;
options.chart['subtitle'] = (current ? 'View 1' : 'View 2');
chart.draw(data[current], options);
};
function getData() {
var data = new google.visualization.DataTable();
data.addColumn('number', 'Class');
ms2.forEach(function(masterLocation, index) {
data.addColumn('number', masterLocation.LOCAL_ID);
});
for (var i = 0; i < 13; i++) {
var arr = [i];
ms2.forEach(function(masterLocation, index) {
arr.push(masterLocation['Class' + i]);
});
data.addRow(arr);
}
return data;
}
function getRandomData(base) {
var data = new google.visualization.DataTable();
data.addColumn('number', 'Class');
data.addColumn('number', ms2[0].LOCAL_ID);
data.addColumn('number', ms2[1].LOCAL_ID);
data.addColumn('number', ms2[2].LOCAL_ID);
// add random data
var y1 = base,
y2 = base,
y3 = base;
for (var i = 0; i < 13; i++) {
y1 += Math.floor(Math.random() * 5) * Math.pow(-1, Math.floor(Math.random() * 2));
y2 += Math.floor(Math.random() * 5) * Math.pow(-1, Math.floor(Math.random() * 2));
y3 += Math.floor(Math.random() * 5) * Math.pow(-1, Math.floor(Math.random() * 2));
data.addRow([i, y1, y2, y3]);
}
return data;
}
function init() {
data = [];
data[0] = getData();
data[1] = getRandomData(1000);
chart = new google.charts.Line(document.getElementById('chart_div'));
options = {
chart: {
title: 'Box Office Earnings in First Two Weeks of Opening',
subtitle: 'in millions of dollars (USD)'
},
width: 500,
height: 300,
vAxis: {
gridlines: {
color: '#ccc'
}
},
hAxis: {
gridlines: {
color: '#ccc'
}
},
animation: {
duration: 1000,
easing: 'out'
}
};
drawChart();
}
function drawChart() {
var columns = [];
var defaultSeries = [1, 2, 3];
var series = {};
for (var i = 0; i < data[current].getNumberOfColumns(); i++) {
if (i === 0 || defaultSeries.indexOf(i) > -1) {
// if the column is the domain column or in the default list, display the series
columns.push(i);
} else {
// otherwise, hide it
columns.push({
label: data.getColumnLabel(i),
type: data.getColumnType(i),
sourceColumn: i,
calc: function() {
return null;
}
});
}
if (i > 0) {
columns.push({
calc: 'stringify',
sourceColumn: i,
type: 'string',
role: 'annotation'
});
// set the default series option
series[i - 1] = {};
if (defaultSeries.indexOf(i) == -1) {
// backup the default color (if set)
if (typeof(series[i - 1].color) !== 'undefined') {
series[i - 1].backupColor = series[i - 1].color;
}
series[i - 1].color = '#CCCCCC';
}
}
}
options['series'] = series;
function showHideSeries() {
var sel = chart.getSelection();
if (sel.length < 1 || sel[0].row) {
return;
}
var col = sel[0].column;
if (typeof(columns[col]) == 'number') {
var src = columns[col];
var calcFunc = null;
if (document.getElementById("removeSeriesOnSelect").checked) {
calcFunc = function() {
return null;
};
}
columns[col] = {
label: data[current].getColumnLabel(src),
type: data[current].getColumnType(src),
sourceColumn: src,
calc: calcFunc
};
// grey out the legend entry
series[src - 1].color = '#CCCCCC';
} else {
var src = columns[col].sourceColumn;
// show the data series
columns[col] = src;
series[src - 1].color = null;
}
var view = new google.visualization.DataView(data[current]);
view.setColumns(columns);
chart.draw(view, options);
}
google.visualization.events.addListener(chart, 'select', showHideSeries);
google.visualization.events.addListener(chart, 'ready', function() {
button.disabled = false;
});
var view = new google.visualization.DataView(data[current]);
view.setColumns(columns);
chart.draw(view, options);
}
Here is the jsFiddle: https://jsfiddle.net/sp7atw1L/
Edit: I started a bounty. Given the global variables and maybe the indirect way this is doing things. I am not opposed to a direct refactor/redo that accomplishes the same thing.
Indeed the bug is related to annotation columns. After drawChart() your columns array is [0,1,{a},2,{a},3,{a}].
> when column 1 clicked, everything is ok.
> when column 2 clicked, columns[2] is {a}, which in your code is replaced by 1, so, you get another copy of column 1
> when column 3 clicked, columns[3] is 2, so, the wrong row is selected
These are consequences, but the problem lies in chart.getSelection() not taking into account annotation columns and returning wrong indexes. I am not sure why this happens, but if you draw DataView (instead of DataTable) in onclick handler like this
//chart.draw(data[current], options); <-------remove this
var view = new google.visualization.DataView(data[current]);
view.setColumns(columns);// <---make columns global
chart.draw(view, options);
it solves the issue. A related problem with annotations is e.g. here
Additionally, in getData() the line
arr.push(masterLocation['Class' + i]);
should be
arr.push(masterLocation['Class' + i+1]);

I want to multiply chart data according as array length

I used this ,to multiply doughnut chart according as array(arr) has,but it can't change to object,(data has string type).So chart doesn't appear here..,how fix it
var arr=['HTML','CSS','JS'],i,data;
data ='[';
for(i=0;i<arr.length;i++){
if(i==arr.length-1){
data+='{value:"300",color:"#fff",highlight:"#aaa",label:arr[i]}';
}
else{
data+='{value:"300",color:"#fff",highlight:"#aaa",label:arr[i]},';
}
}
data += ']';
var dat = data;
window.onload = function () {
var ctx = document.getElementById("chart-area").getContext("2d");
window.myBar = new Chart(ctx).Doughnut(dat,{
responsive: true,
});
};
//want like this
dat =[{value:"300",color:"#fff",highlight:"#aaa",label:"HTML"},
{value:"200",color:"#fff",highlight:"#aaa",label:"CSS"}];
You are creating your array as a String.
You need to create an array of objects [{},{},{}].
The method used to INSERT a new object in an array is PUSH().
Check the fiddle. Now it´s working OK (move the mouse on the screen to see the chart is there (you will only see it when mouse is over it):
window.onload = function() {
var arr = ['HTML', 'CSS', 'JS'],
i, data;
data = [];
for (i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
data.push({
value: "300",
color: "#fff",
highlight: "#aaa",
label: arr[i]
});
} else {
data.push({
value: "300",
color: "#fff",
highlight: "#aaa",
label: arr[i]
});
}
}
var dat = data;
var ctx = document.getElementById("chart-area").getContext("2d");
window.myBar = new Chart(ctx).Doughnut(dat, {
responsive: true,
});
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/nnnick/Chart.js/master/Chart.js"></script>
<canvas id="chart-area"></canvas>

Google Column Chart cropping the bars

I am trying to display data using Google's Column chart. I tried displaying bars not stacked but it would not display one bar from both ends. Then i changed the property isStacked to true, it displays all the bars but it crops the bar at the both ends.
How can i fix this issue?
I was playing around with the options but nothing seems to work.
<script type='text/javascript'>
google.load('visualization', '1', { 'packages': ['corechart'] });
google.setOnLoadCallback(drawSizeChart);
var d = 0;
function drawSizeChart() {
$.post('/metrics/SiteResourceChart', { fnsId: "#Model.FnsId", regionId: selectedValue },
function (data) {
if (Object.keys(data).length !== 0) {
var tdata = new google.visualization.DataTable();
tdata.addColumn('date', 'Date');
for (var p = 0; p < data.length; ++p) {
tdata.addColumn('number', data[p][0].PathName);
}
d = data[0].length;
for (var i = 0; i < data.length; ++i) {
for (var j = 0; j < data[i].length; ++j) {
var date = new Date(parseInt(data[i][j].CreatedAt.substr(6)));
var rCount = data[i][j].ResourceCount;
if (i === 0)
tdata.addRow([date, rCount, null]);
else
tdata.addRow([date, null, rCount]);
}
}
var options = {
title: 'Resource Count',
titleTextStyle: { fontSize: 20 },
isStacked: true,
bar: { groupWidth: '20%' },
chartArea: { left: '50' },
hAxis: { viewWindowMode: 'maximized' }
//legend: { position: 'none' }
};
var chart = new google.visualization.ColumnChart(document.getElementById('site_size_chart'));
chart.draw(tdata, options);
}
}
);
}
</script>
I guess a quick solution would be to define your first column as 'string' instead of Date and leave the hAxis.viewWindowMode as default. Otherwise, you should configure hAxis.viewWindow object (i.e., min/max values).
Same issue here. What I did is that I added dummy data with a 0 value one day before the first date and one day after the last date in order to achieve the desired result.
Using the columnchart package wasn't a solution for me because I had days without data but wanted to keep the time axis proportional.

Categories