Adding a new line to Google chart without shifting the others - javascript

I'm having trouble using google charts stacked graphs to display a 'dynamic' graph, by dynamic I mean that every time I draw the graph, I add a new row of data.
The problem is that when I add the new row, the entire graph proportion changes.
Link to JSFiddle.
HTML:
<div id="chartdiv"></div>
<button onclick='DrawChart();'>Draw Chart</button>
CSS:
#chartdiv{
height: 400px;
overflow-x: hidden;
overflow-y: scroll;
border: solid;
}
JS:
google.load("visualization", "1", { packages: ["corechart"] });
// create legend
var legend = ['School', 'A', 'B', 'C', 'D', 'E', 'F', 'G'];
// create table
var dataTable = [legend];
// create line
var line = ['line', 0.05, 0.10, 0.25, 0.33, 0 , 0.12, 0.15];
function DrawChart() {
dataTable.push(line);
var data = google.visualization.arrayToDataTable(dataTable);
var view = new google.visualization.DataView(data);
var options_fullStacked = {
isStacked: 'percent',
legend: { position: 'top', maxLines: 3 },
height: data.getNumberOfRows() * 110,
width: 615,
bar: { groupWidth: 50 },
hAxis: {
minValue: 0,
ticks: [0, .25, .5, .75, 1]
},
};
var chart = new google.visualization.BarChart(document.getElementById("chartdiv"));
chart.draw(view, options_fullStacked);
}
I saw a somewhat similar question here, which I tried to learn from and make the changes accordingly, but it didn't help.
The best way to understand what I need help with is to enter the JSFiddle link and click the draw chart button a few times, each time you click it a new row will be added to the chart. So just try clicking it a few times and you'll see that things are starting to get messy after a while.
Ideally what I'm trying to achieve is that after the 2nd, 3rd (and so on) click I won't notice that the entire graph we loaded, I will only notice that a new row was added.
I would really appreciate help on this issue.

I was able to fix it. After playing with the graph for a while I found a way to overcome most of the bugs I had.
The main issues were the changing height and width, and that after a few runs the graph was starting to lose its structure.
The changes I made include:
Setting a fixed width.
Setting a min height and also making some adjustments to the size value.
Setting a fixed font size - that's what caused the graph to lose its shape.
I've included the updated code below. (looks much better in JSFiddle)
google.load("visualization", "1", {
packages: ["corechart"]
});
// create legend
var legend = ['School', 'A', 'B', 'C', 'D', 'E', 'F', 'G'];
// create table
var dataTable = [legend];
// create line
var lines = [
['line', 0.05, 0.10, 0.25, 0.33, 0, 0.12, 0.15],
['line', 0.1, 0.3, 0.25, 0, 0, 0.12, 0.23]
];
var i = 0;
function DrawChart() {
dataTable.push(lines[(i++) % 2]);
var data = google.visualization.arrayToDataTable(dataTable);
var view = new google.visualization.DataView(data);
var height = Math.max(180, data.getNumberOfRows() * 85);
var options_fullStacked = {
isStacked: 'percent',
legend: {
position: 'top',
maxLines: 3
},
height: height,
width: 720,
bar: {
groupWidth: 50
},
hAxis: {
minValue: 0,
ticks: [0, .25, .5, .75, 1],
title: "p"
},
chartArea: {
left: 100,
top: 30,
width: 600
},
fontSize: 14
};
var chart = new google.visualization.BarChart(document.getElementById("chartdiv"));
chart.draw(view, options_fullStacked);
}
#chartdiv {
height: 400px;
overflow-x: hidden;
overflow-y: scroll;
border: solid;
}
<script src="https://www.google.com/jsapi"></script>
<div id="chartdiv"></div>
<button onclick='DrawChart();'>Draw Chart</button>

Related

Google visualization dual Y axis chart align line with specific bar

I have attached snippet for a dual Y axis chart.
The orange dot for Ontime% Goal corresponds with the blue bar for Ontime %. Both have been assigned to targetAxisIndex: 0
Can I shift/move the dot to align above the blue bar? (see attached picture for desired position).
Thank you as always to the experts out there!
google.charts.load('current', {'packages':['corechart', 'bar']});
google.charts.setOnLoadCallback(drawStuff);
function drawStuff() {
var button = document.getElementById('change-chart');
var chartDiv = document.getElementById('chart_div');
var data = google.visualization.arrayToDataTable([
['Type', 'Ontime%', 'Count', 'Ontime% Goal'],
['AE', 90, 500, 100]
]);
var classicOptions = {
width: 900,
series: {
0: {targetAxisIndex: 0, type: 'bars'},
1: {targetAxisIndex: 1, type: 'bars'},
2: {targetAxisIndex: 0, type: 'line', pointSize: 8, pointShape: { type: 'circle' } },
},
title: 'Ontime % on the left, Count on the right',
bar:{
width: "60%"
},
vAxis: {
minValue: 0
},
vAxes: {
// Adds titles to each axis.
0: {title: 'Ontime %'},
1: {title: 'Count'}
}
};
function drawClassicChart() {
var classicChart = new google.visualization.ColumnChart(chartDiv);
classicChart.draw(data, classicOptions);
button.innerText = 'Change to Material';
button.onclick = drawMaterialChart;
}
drawClassicChart();
};
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<br><br>
<div id="chart_div" style="width: 800px; height: 500px;"></div>
nothing out of the box will allow you to adjust the position of the point.
you can move it manually, on the chart's ready event.
but the chart will move it back when the user hovers the point.
you can use a MutationObserver to move the point when the chart moves it back,
but this will just cause it to blink from one spot to the other while it is being hovered.
not much you can do, unless you disable tooltips.
see following working snippet,
hover the point to see it move...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
//var button = document.getElementById('change-chart');
var chartDiv = document.getElementById('chart_div');
var data = google.visualization.arrayToDataTable([
['Type', 'Ontime%', 'Count', 'Ontime% Goal'],
['AE', 90, 500, 100]
]);
var classicOptions = {
width: 900,
series: {
0: {targetAxisIndex: 0, type: 'bars'},
1: {targetAxisIndex: 1, type: 'bars'},
2: {
targetAxisIndex: 0,
type: 'line',
pointSize: 8,
pointShape: {type: 'circle'},
},
},
title: 'Ontime % on the left, Count on the right',
bar:{
width: "60%"
},
vAxis: {
minValue: 0
},
vAxes: {
0: {title: 'Ontime %'},
1: {title: 'Count'}
}
};
function drawClassicChart() {
var classicChart = new google.visualization.ColumnChart(chartDiv);
google.visualization.events.addListener(classicChart, 'ready', function () {
var chartLayout = classicChart.getChartLayoutInterface();
var bounds = chartLayout.getBoundingBox('bar#0#0');
var observer = new MutationObserver(function () {
var circles = chartDiv.getElementsByTagName('circle');
if (circles.length > 1) {
circles[1].setAttribute('cx', (bounds.left + (bounds.width / 2)));
}
});
observer.observe(chartDiv, {
childList: true,
subtree: true
});
});
classicChart.draw(data, classicOptions);
//button.innerText = 'Change to Material';
//button.onclick = drawMaterialChart;
}
drawClassicChart();
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
best case, you could disable the chart's tooltips,
then add your own custom tooltips,
for both the point and columns, etc...
the chart does provide mouseover and mouseout events,
not sure its worth the effort...

Google Charts - Can you align columns in a column chart to the center of the chart?

Is there a way using the column chart provided by the Google charts javascript api to center columns in the middle of the chart rather than having large amounts of space between each column? I can accomplish this by grouping the values together but I lose the label under the column.
Here's a pic of what I'm trying to accomplish:
Here's what I have so far:
google.charts.load('current', { packages: ['corechart', 'bar'] })
google.charts.setOnLoadCallback(drawColColors)
function drawColColors() {
const data = google.visualization.arrayToDataTable([
['Number', 'Price'],
['1', 1900000],
['2', 1800000],
['3', 1500000]
])
const options = {
width: '100%',
height: 400,
colors: ['red'],
vAxis: { minValue: 0, format: '$###,###,###' },
enableInteractivity: false,
bar: { groupWidth: 45 },
legend: { position: 'none' }
}
const chart = new google.visualization.ColumnChart(document.getElementById('chart'))
chart.draw(data, options)
}
Codesandbox: https://codepen.io/anon/pen/GworqG
bar.groupWidth is the only config option that will specifically address column alignment
(in this manner)
however, instead of a number...
bar: {groupWidth: 45},
you can also use a percentage.
This won't necessarily move the columns, but it will make them larger, bringing them closer together.
bar: {groupWidth: '90%'},
see following working snippet for an example...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
['Number', 'Price'],
['1', 1900000],
['2', 1800000],
['3', 1500000]
])
var options = {
width: '100%',
height: 400,
colors: ['red'],
vAxis: {minValue: 0, format: '$###,###,###'},
enableInteractivity: false,
bar: {groupWidth: '90%'},
legend: { position: 'none' }
}
var chart = new google.visualization.ColumnChart(document.getElementById('chart'))
chart.draw(data, options)
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart"></div>
another option would be to use actual numbers (1), rather than strings ('1'), on the x-axis.
this enables additional config options you can use to push the columns closer to the center.
for instance, setting the viewWindow will allow you to add space between the visible columns and the edges.
hAxis: {
viewWindow: {
min: -2,
max: 6
}
}
by default, a continuous axis (numbers) will display grid lines,
whereas a discrete axis (strings) will not.
these can be removed, or hidden, with the following options.
baselineColor: 'transparent',
gridlines: {
color: 'transparent'
},
see following working snippet for another example...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
['Number', 'Price'],
[1, 1900000],
[2, 1800000],
[3, 1500000]
])
var options = {
width: '100%',
height: 400,
colors: ['red'],
vAxis: {minValue: 0, format: '$###,###,###'},
enableInteractivity: false,
legend: {position: 'none'},
hAxis: {
baselineColor: 'transparent',
gridlines: {
color: 'transparent'
},
ticks: data.getDistinctValues(0),
viewWindow: {
min: -2,
max: 6
}
}
}
var chart = new google.visualization.ColumnChart(document.getElementById('chart'))
chart.draw(data, options)
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart"></div>

How to set Google Chart height based on number of rows?

I have a Google stacked bar chart that pulls data from a database and draws charts based on said data. I was able to search around and find a way to dynamically set the height based on the number of rows - but for one of my search filters, the charts look way off.
The code is below and works for 4 out of 5 of my filters, but in the 5th filter the number of rows becomes much larger (around 40-50).
Code:
var paddingHeight = 40;
var rowHeight = data.getNumberOfRows() * 50;
var chartHeight = rowHeight + paddingHeight;
var options = {
titlePosition: 'none',
width: 1400,
height: chartHeight,
legend: { position: 'top', maxLines: 3 },
bar: { groupWidth: '50%' },
isStacked: true,
hAxis: {
title: 'Business Hours (excluding weekends & holidays)'
},
colors: ['#0066ff', '#33cc33', '#ffcc00', '#ff0000'],
annotations: {
alwaysOutside: true,
textStyle: {
color: '#000000'
}
}
}
Produces the following results. This first image is what 4 of my 5 filters looks like.
The second image is the one in question that shows I'm clearly doing something wrong.
What is the cause of this and how can I resolve it?
Edit: I suspect my issue is one of the following:
Either my data rows are not being counted correctly as I refresh the page with the latest search parameters or I have a problem with how my divs are set up and interacting with each other. I've tried adjusting the math behind the chartHeight and removing the padding and it seems to have the same effect either way. Am I on the right track or is there something else I'm missing?
need to set options for both height and chartArea.height
here, recommend using rowHeight for chartArea.height
var paddingHeight = 40;
var rowHeight = data.getNumberOfRows() * 50;
var chartHeight = rowHeight + paddingHeight;
var options = {
titlePosition: 'none',
width: 1400,
height: chartHeight,
chartArea: {
height: rowHeight,
},
legend: { position: 'top', maxLines: 3 },
bar: { groupWidth: '50%' },
isStacked: true,
hAxis: {
title: 'Business Hours (excluding weekends & holidays)'
},
colors: ['#0066ff', '#33cc33', '#ffcc00', '#ff0000'],
annotations: {
alwaysOutside: true,
textStyle: {
color: '#000000'
}
}
}
you'll want to leave some room for the legend, y-axis, etc...
chartArea has the following properties
top
left
height
width
you'll want to set top to 20 or something if legend is on top

Google Pie chart, can't set different values for 2 different graphs

I am trying to re-use a google pie chart function to draw a chart in 2 different divs.
My html :
<div class="piechart" style="height: 220px;" data-completeness="35"></div>
<div class="piechart" style="height: 220px;" data-completeness="80"></div>
My javascript:
function drawChart()
{
{#var completeness = 30;#} //this is working and setting same value to the two different charts
var completeness = $(this).attr('data-completeness'); //this is not working and charts are rendered very small
console.log(completeness); //this is dumping the right values in both cases, either the same, or two different ones as I expect
var data = google.visualization.arrayToDataTable([
['Nom', 'Valeur'],
["Profil rempli à ", completeness],
['Manque', 100 - completeness]
]);
var options = {
backgroundColor: { fill:'transparent'},
pieSliceBorderColor : 'transparent',
pieHole: 0.8,
legend: {position: 'top'},
width: 220,
height: 220,
tooltip: {trigger: 'none'},
pieStartAngle: -90,
pieSliceTextStyle :{fontsize : 16, color: 'transparent'},
slices: {
0: { color: '#09b4ff'},
1: { color: '#444'}
},
chartArea : {width: '90%', height: '90%'}
};
var chart = new google.visualization.PieChart(this);
chart.draw(data, options);
}
google.load('visualization', '1', {packages:['corechart']});
google.setOnLoadCallback(function(){
$('.piechart').each(drawChart);
});
So when I set a single value, I have the following good looking graph:
When I set two different values, the result in weird:
Info : I have a
1:1 XMLHttpRequest cannot load
https://www.google.com/uds/api/visualization/1.0/dca88b1ff7033fac80178eb526cb263e/ui+en.css.
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://foodmeup.dev' is therefore not allowed
access.
error in both cases, but it's diplaying well in the first case so I'm not sure it's the issue here.
.attr('data-completeness') return the string "35" and "80" so you can use parseInt to get the actual numbers or you can use .data("completeness") like this
var completeness = $(this).data('completeness');
// or parseInt($(this).attr('data-completeness'));
full code
function drawChart(){
var completeness = $(this).data('completeness');
// or parseInt($(this).attr('data-completeness'))
var data = google.visualization.arrayToDataTable([
['Nom', 'Valeur'],
["Profil rempli à ", completeness],
['Manque', 100 - completeness]
]);
var options = {
backgroundColor: { fill:'transparent'},
pieSliceBorderColor : 'transparent',
pieHole: 0.8,
legend: {position: 'top'},
width: 220,
height: 220,
tooltip: {trigger: 'none'},
pieStartAngle: -90,
pieSliceTextStyle :{fontsize : 16, color: 'transparent'},
slices: {
0: { color: '#09b4ff'},
1: { color: '#444'}
},
chartArea : {width: '90%', height: '90%'}
};
var chart = new google.visualization.PieChart(this);
chart.draw(data, options);
}
google.load('visualization', '1', {packages:['corechart']});
google.setOnLoadCallback(function(){
$('.piechart').each(drawChart);
});
https://jsfiddle.net/sjsaa2xf/
enter image description here
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>

Google Annotation Chart background color [duplicate]

I'm styling a google chart using the javascript api. I want to change the background of the area where the data is plotted. For some reason when I set background options like so:
chart.draw(data, { backgroundColor: { fill: "#F4F4F4" } })
It changes the the background of the whole chart and not the area where the data is plotted. Any ideas on how to only change the background of the plotted area?
Thanks
pass the options like this
var options = {
title: 'title',
width: 310,
height: 260,
backgroundColor: '#E4E4E4',
is3D: true
};
add this to your options:
'chartArea': {
'backgroundColor': {
'fill': '#F4F4F4',
'opacity': 100
},
}
The proper answer is that it depends if it is classic Google Charts or Material Google Charts. If you use classic version of the Google Charts, multiple of the above suggestion work. However if you use newer Material type Google charts then you have to specify the options differently, or convert them (see google.charts.Bar.convertOptions(options) below). On top of that in case of material charts if you specify an opacity for the whole chart, the opacity (only) won't apply for the chart area. So you need to explicitly specify color with the opacity for the chart area as well even for the same color combination.
In general: material version of Google Charts lack some of the features what the Classic has (slanted axis labels, trend lines, custom column coloring, Combo charts to name a few), and vica versa: the number formating and the dual (triple, quadruple, ...) axes are only supported with the Material version.
In case a feature is supported by both the Material chart sometimes requires different format for the options.
<body>
<div id="classic_div"></div>
<div id="material_div"></div>
</body>
JS:
google.charts.load('current', { 'packages': ['corechart', 'bar'] });
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Year', 'Sales', 'Expenses'],
['2004', 1000, 400],
['2005', 1170, 460],
['2006', 660, 1120],
['2007', 1030, 540],
['2009', 1120, 580],
['2010', 1200, 500],
['2011', 1250, 490],
]);
var options = {
width: 1000,
height: 600,
chart: {
title: 'Company Performance',
subtitle: 'Sales, Expenses, and Profit: 2014-2017'
},
// Accepts also 'rgb(255, 0, 0)' format but not rgba(255, 0, 0, 0.2),
// for that use fillOpacity versions
// Colors only the chart area, simple version
// chartArea: {
// backgroundColor: '#FF0000'
// },
// Colors only the chart area, with opacity
chartArea: {
backgroundColor: {
fill: '#FF0000',
fillOpacity: 0.1
},
},
// Colors the entire chart area, simple version
// backgroundColor: '#FF0000',
// Colors the entire chart area, with opacity
backgroundColor: {
fill: '#FF0000',
fillOpacity: 0.8
},
}
var classicChart = new google.visualization.BarChart(document.getElementById('classic_div'));
classicChart.draw(data, options);
var materialChart = new google.charts.Bar(document.getElementById('material_div'));
materialChart.draw(data, google.charts.Bar.convertOptions(options));
}
Fiddle demo: https://jsfiddle.net/csabatoth/v3h9ycd4/2/
It is easier using the options.
drawChart() {
// Standard google charts functionality is available as GoogleCharts.api after load
const data = GoogleCharts.api.visualization.arrayToDataTable([
['Chart thing', 'Chart amount'],
['Na Meta', 50],
['Abaixo da Meta', 22],
['Acima da Meta', 10],
['Refugos', 15]
]);
let options = {
backgroundColor: {
gradient: {
// Start color for gradient.
color1: '#fbf6a7',
// Finish color for gradient.
color2: '#33b679',
// Where on the boundary to start and
// end the color1/color2 gradient,
// relative to the upper left corner
// of the boundary.
x1: '0%', y1: '0%',
x2: '100%', y2: '100%',
// If true, the boundary for x1,
// y1, x2, and y2 is the box. If
// false, it's the entire chart.
useObjectBoundingBoxUnits: true
},
},
};
const chart = new GoogleCharts.api.visualization.ColumnChart(this.$.chart1);
chart.draw(data, options);
}
I'm using polymer that's why i'm using this.$.cart1, but you can use selectedbyid, no problem.
Have you tried using backgroundcolor.stroke and backgroundcolor.strokewidth?
See Google Charts documentation.
If you want to do like this then it will help. I use stepped area chart in the combo chart from the Google library...
where the values for each stepped area is the value for ticks.
Here is the link for jsfiddle code
Simply add background option
backgroundColor: {
fill:'red'
},
here is the fiddle link https://jsfiddle.net/amitjain/q3tazo7t/
You can do it just with CSS:
#salesChart svg > rect { /*#salesChart is ID of your google chart*/
fill: #F4F4F4;
}

Categories