Google Charts (Pie) Showing Only Slivers when given dynamic data - javascript

I'm trying to include a Google Pie Chart in my Rails app, and I've run into what I think is a particularly weird error.
The problem is, when I input numbers, the chart displays perfectly (showing my two input numbers as the two components of a pie equal to their sum), but when I try to feed it dynamic data, it seems to PICK UP the data but NOT USE it correctly -- instead displaying the two numbers as slivers in an otherwise blank chart. Code examples:
This works perfectly, turning into a pretty pie chart with the correct values (sold and left, below):
<div id="chart_div"></div>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var sold = 406;
var left = 38;
var data = google.visualization.arrayToDataTable([
['Pounds', 'Sold/Left'],
['Pounds Sold', sold],
['Left', left]
]);
var options = {
};
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
This, however, produces a chart with a hover showing (in this case) the exact same numbers (406, and 38), but the two chart sections are extremely small, accounting for about 1% of the chart's volume (as opposed to the ideal 100%). The remaining 99ish% of the chart is blank:
<div id="chart_div" data-sold=<%= #animal.pounds_sold.to_i %> data-left=<%= #animal.pounds_left.to_i %> ></div>
// Here, the numbers equal 406 and 38, as in the above.
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var sold = $(document).find('#chart_div').attr('data-sold');
var left = $(document).find('#chart_div').attr('data-left');
var data = google.visualization.arrayToDataTable([
['Pounds', 'Sold/Left'],
['Pounds Sold', sold],
['Left', left]
]);
var options = {
};
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
One possible clue is that when I hover over the sections in this erroring chart, although the hover says the right numbers (406, 38), it says these sections account for only 1 and 0.2 percent of the pie, respectively, even though the rest of the pie is blank (and has no hover/hover value).
Any ideas what's going on here? I'm guessing I'm committing some javascript/jquery crime, cause I'm fairly new to it, but I don't know what.
Thanks!
EDIT -- Another weird thing. I tried to see what would happen in a hybrid scenario with both dynamic numbers and straight numbers, i.e the below modification to the dynamic version above:
...
var other = 50;
var sold = $(document).find('#chart_div').attr('data-sold');
var left = $(document).find('#chart_div').attr('data-left');
var data = google.visualization.arrayToDataTable([
['Pounds', 'Sold/Left'],
['Pounds Sold', sold],
['Left', left],
['Test', other]
]);
...
This, inexplicably (to me), led to NO CHART AT ALL.

I think the issue is that you are specifying the "values" of each sliver as a string. Try defining them as an INT and your pie should work

Related

Instead of creating new chart in ChartJS, the new updated chart keeps the old data and adds the new

I have been trying to solve this problem with ChartJS for a few days now, and I am completely stumped
My program shows the user a set of input elements they use to select data needing to be charted, plus a button that has an event to chart their data. The first chart works great. If they make a change to the data and click the button a second, third, or more time, all the data from the previous charts is plotted, PLUS their most recent selection.
It is behaving exactly like you might expect if the chart.destroy() object is not working, or perhaps would work if I created the chart object using a CONST (and could therefore add new data but not delete the beginning data).
I have tried all combinations of the browsers, chartjs and jquery libraries below:
Three different browsers:
• Chrome: Version 107.0.5304.121 (Official Build) (64-bit)
• Microsoft Edge: Version 107.0.1418.56 (Official build) (64-bit)
• Firefox: 107.0 64-bit
I have tried at least three different versions of Chart.js, including
• Versions 3.9.1
• 3.6.2
• 3.7.0
Jquery.js
• v3.6.1
• v1.11.1
Other things I have tried:
"use strict" (no luck)
In addition to destroying the chart object, removed the div containing the canvas, and appending it again.
using setTimeout() function before updating the chart after destroying it (because I thought maybe giving the destroy method more time might help)
type here
Software:
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/chart.js"></script>
<script type="text/javascript" src="js/dropdownLists.js"></script>
<script type="text/javascript" src="js/chartDataFunctions.js"></script>
<script type="text/javascript" src="js/chartJSFunctions.js"></script>
<body>
<div class = metadatasetup4" id = "buttons">
<button class="download" id="getchart" value="Get Chart">Chart</button>
<button class="download" id="downloadchart" value="Download">Download</button>
</div>
<div id = "bigchartdiv" class="bigchart">
<canvas id="myChart"></canvas>
</div>
</body>
<script>
$(window).on('load',function(){
//NOTE 1: In of my attempts to troubleshoot I tried strict mode (it didn't work)
//"use strict";
let data = {
labels: lbl,
datasets: [
]
};
let config = {
type: 'line',
data: data,
options: {
scales: {
y: {
type: 'linear',
display: true,
position: 'left',
min:0,
pointStyle:'circle',
},
y1: {
type: 'linear',
display: true,
position: 'right',
suggestedMax: 25,
min: 0,
pointStyle: 'cross',
// grid line settings
grid: {
drawOnChartArea: false, // only want the grid lines for one axis to show up
},
},
}
}
};
// NOTE 2: The next line below, beginning with "var bigChartHTML =" was one of my later attempts to
// solve the problem. It didn't work, but my thought process was that if I removed
// the div containing the canvas, AND destroyed the chart object, that appending a "fresh"
// chart div to the body might be a work-around. This did not work.
var bigChartHTML = '<div id = "bigchartdiv" class="bigchart"><canvas id="myChart"></canvas></div>'
let ctx = document.getElementById('myChart').getContext('2d');
let bigChart = null;
// The getChartData() function below uses Ajax to populate various dropdown lists
// which enable the user to select the data is to be charted.
// There are no chartjs-related operations in getChartData()
getChartData();
$('#buttons').on('click','#getchart',function(){
if (bigChart!=null) {
//removeData(bigChart);
bigChart.destroy();
//bigChart = 1;
}
$("#bigchartdiv").empty(); //for this and next 2 lines, see NOTE 2 above
$("#bigchartdiv").remove();
$(bigChartHTML).insertAfter("#chartcontrols");
bigChart = new Chart(document.getElementById('myChart'),config);
//NOTE 3: I thought maybe bigChart.destroy() took time, so I tried
// using the setTimeout function to delay updating the chart
// (didn't work, but I left it in the code, anyway.)
setTimeout(function() {updateChart(bigChart)}, 2000);
//updateChart(bigChart);
});
// NOTE: The updateChart() function is actually included in "js/chartDataFunctions.js"
function updateChart(chart) {
/*
This section of the program reads the HTML elements then uses them
to make an Ajax request to sql server, and these become the
parameters for the newDataSet() function below.
*/
newDataset(chart,firstElement,newdataset,backgroundcolor,color);
}
// NOTE: The newDataSet() function is actually included in "js/chartJSFunctions.js"
// I show it here for brevity.
// It decides which axis (y or y1) to use to plot the datasets
// the dataset is pushed into the data, and chart.update() puts it in the chart object
function newDataset(chart,label,data,bgcolor='white',color='rgb(255,255,255)') {
var maxValue = Math.max(...data);
if (Number.isNaN(maxValue)) {
return;
}
if (maxValue == 0) {
return;
}
var axisID = 'y';
var ptStyle = 'circle';
//var pStyle = 'circle';
if (maxValue < 50) {
axisID = 'y1';
bgcolor = 'white';
//ptStyle = 'Star'
}
chart.data.datasets.push({
label:label,
yAxisID:axisID,
data:data,
borderColor:color,
backgroundColor:bgcolor,
//pointStyle:ptStyle
});
chart.update();
}
});
</script>
I found a work-around that solves my problem, but I still think this is a bug in ChartJS. Before calling bigChart.destroy(), I now do two things: First, reset the data object back to it's original value, and second, reset the config object back to it's original value, THEN call bigChart.destroy().
I think the destroy() method should handle that for me, but in my case, for whatever reason, it doesn't.
So, what I have is a work-around, not really a solution, but I'll take it.

JS - How to rotate labels (hAxis) on Google Graphs (slantedText)?

I have been trying to simply rotate my hAxis on the following graph for long now. Tried several solutions explained below! Cant believe something that simple seems that hard to do. Source code below:
<html>
<title>VM Allocation Performance</title>
<meta http-equiv="refresh" content="30">
<head>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["bar"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['09/12/2015 10:00:00',3.52],['09/12/2015 10:30:00',7.56],['09/12/2015 11:00:00',8.99],['09/12/2015 11:30:00',4.93],['09/12/2015 12:00:00',10.26],['09/12/2015 12:30:00',9.82],['09/12/2015 13:00:00',12.62],['09/12/2015 13:30:00',9.07],['09/12/2015 14:00:00',4.94],['09/12/2015 14:30:00',8.98],['09/12/2015 15:00:00',7.85],['09/12/2015 15:30:00',3.59],['09/12/2015 16:00:00',5.64]],true);
var options = {
chart: {
title: 'VM Allocation',
subtitle: 'Since Shift Start',
}
//I tried with slantedText: true here but while my graph was rendering, labels were not rotated!
};
var chart = new google.charts.Bar(document.getElementById('chart_div'));
chart.draw(data, google.charts.Bar.convertOptions(options));
}
</script>
</head>
<body>
<div id='chart_div' style='width: 450px; height: 400px;'></div>
</body>
</html>
Here is what I tried so far:
I read the Google documentation, changed my code accordingly (because it is a "material" graph etc...) and still nothing.
I tried using the same hAxis block from this jsfiddle I found, no luck.
I went into a bit more details and saw on the Google doc that the option "slantedText" would work only on discrete axis, so I thought I had to change my hAxis type from Date/Time to String, I tried and did not succeed.
I kept on and tried using this solution from SO and while I can still render the graph, my date/time labels are still not showing entirely (which is why I want to rotate them).
Can anybody please help on this?
Change to a columnchart and not a bar.
See http://jsfiddle.net/Swtv3/51/
function drawChart() {
var data = google.visualization.arrayToDataTable([
['09/12/2015 10:00:00',3.52],['09/12/2015 10:30:00',7.56],['09/12/2015 11:00:00',8.99],['09/12/2015 11:30:00',4.93],['09/12/2015 12:00:00',10.26],['09/12/2015 12:30:00',9.82],['09/12/2015 13:00:00',12.62],['09/12/2015 13:30:00',9.07],['09/12/2015 14:00:00',4.94],['09/12/2015 14:30:00',8.98],['09/12/2015 15:00:00',7.85],['09/12/2015 15:30:00',3.59],['09/12/2015 16:00:00',5.64]],true);
var options = {
chart: {
title: 'VM Allocation',
subtitle: 'Since Shift Start',
},
chartArea: {
top: 28,
height: '40%'
},
hAxis: {
title: 'Sources',
slantedText: true
}
//I tried with slantedText: true here but while my graph was rendering, labels were not rotated!
};
var chart = new google.visualization.ColumnChart(document.getElementById('chart'));
chart.draw(data, options);
}
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);

Google Graphs show decimal places on scatter points

I have created a scatter chart using the Google Graphs API and all is fine apart from the fact that it will only so scatter points as decimal places if they're less than 10.
Here's the jsFiddle
google.load('visualization', '1.1', {packages: ['scatter']});
google.setOnLoadCallback(drawChart);
function drawChart () {
var data = google.visualization.arrayToDataTable([
["Period", "C Spencer Ltd"],
["1", -11.4],["2", 36.7],
["3", null],
["4", null],
["5", null]
]);
var options = {
chart: {
title: 'Scoring Trends',
subtitle: '*All LAG scores validated from Period 4'
},
width: 900,
height: 500
};
var chart = new google.charts.Scatter(document.getElementById('full_stacked_div'));
chart.draw(data, options);
}
I've tried using the NumberFormatter and the vAxis.format shown here all with no joy.
You should use google.charts.Scatter.convertOptions(options) in your draw (chart.draw(data, google.charts.Scatter.convertOptions(options));) when working with material charts, otherwise options like format won't work.
See the bottom part of Material Chart section.
Working fiddle with the option vAxis:{format:'decimal'} to accomplish what you're requesting.
EDIT:
Just want to note that this is a very common mistake and maybe someone should try to push google the emphasize the importance of this.

How to get a continuous ColumnChart?

I'm using a ColumnChart to represent the elevation in a map, as suggested by Google.
However, the columns are separated by spaces, and that renders ugly white spaces between the
columns, like in Google's own example:
https://developers.google.com/maps/documentation/javascript/examples/elevation-paths
Is there a way to tell the column chart to make columns that fill up the whole space? I would like something like this:
http://4.bp.blogspot.com/-4I8oi3WqY5o/UIZnzbXql_I/AAAAAAAAAcE/GO4wl6I2-lM/s1600/Charts.png
I suspect that the only way is with lots of points.
My code:
var option = {
legend: 'none',
backgroundColor: 'transparent',
colors: ["#C9CFF5"],
titleColor: '#C9CFF5',
focusBorderColor: '#00AA00',
titleY: 'Elevation (m)',
bar: { groupWidth: '100%' }
}
// Build data
var data = new google.visualization.DataTable();
data.addColumn('string', 'Sample');
data.addColumn('number', 'Elevation (m):');
for (var i = 0; i < trackmarks.length; i++) {
data.addRow(['', trackaltis[i]]);
}
// Draw the chart using the data within its DIV.
chart = new google.visualization.ColumnChart(document.getElementById('elevation_chart'));
chart.draw(data, option);
My code is pretty standard: same as Google's, same result.
Thanks!
You can specify option:
bar: {groupWidth: "100%"}
bar.groupWidth: Percentage of the available width for each group (e.g. '20%'), where '100%' means that groups have no space between them
Update: That example uses old version of column charts which loads package columnchart
google.load("visualization", "1", {packages:["columnchart"]});
The latest code for column chart is loaded using corechart:
google.load('visualization', '1', {packages: ['corechart']});
Change that and example should work as expected without spaces.

How to draw a column chart with one single field and multiple colors using google charts

Here is my code: jsfiddle
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" ></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
function drawColumnChart(container, data) {
var data = google.visualization.arrayToDataTable(data);
var chart = new google.visualization.ColumnChart(container);
var options = {fontSize: 16};
chart.draw(data, options);
}
$(document).ready(function(){
drawColumnChart($("#satisfactionBarGraph")[0], [
['satisfaction', 'percent'],
['大変満足', 10 ],
['満足', 22 ],
['やや満足', 30 ],
['やや不満', 10 ],
['不満', 5 ]
]);
});
</script>
</head>
<body>
<div id="satisfactionBarGraph" style="width: 524px; height: 370px;" class="chartContainer"></div>
</body>
</html>
And this is what I really want:
I have two problems:
(1) I want the text below the x-axis to align top bottom
I have run through the document but cannot find the option
(2) I want the columns to be in different colors
Because I have only one filed, so all of them are in the same color. I'm wondering whether I used the right chart.
And suggestion will be appreciated
Thanks a lot for all your answers. I combined your solutions and finally figured it out:
final result
Hope this can help anyone who meets the same problem
The Google Visualization API's ColumnCharts color data by series, so if you want multiple colors for your bars, you have to split them into different series.
function drawColumnChart(container, data) {
var data = google.visualization.arrayToDataTable(data);
var columns = [0];
for (var i = 0; i < data.getNumberOfRows(); i++) {
columns.push({
type: 'number',
label: data.getColumnLabel(1),
calc: (function (x) {
return function (dt, row) {
return (row == x) ? dt.getValue(row, 1) : null;
}
})(i)
});
}
var view = new google.visualization.DataView(data);
view.setColumns(columns);
var chart = new google.visualization.ColumnChart(container);
var options = {
fontSize: 16,
// set the "isStacked" option to true to make the column spacing work
isStacked: true
};
chart.draw(view, options);
}
// use the callback from the google loader to draw the chart rather than document ready
google.load("visualization", "1", {packages:["corechart"], callback: function () {
drawColumnChart($("#satisfactionBarGraph")[0], [
['satisfaction', 'percent'],
['大変満足', 10],
['満足', 22],
['やや満足', 30],
['やや不満', 10],
['不満', 5]
]);
}});
Here's a jsfiddle of this code: http://jsfiddle.net/asgallant/Rrhak/
I don't think the Visualization API supports vertical writing like that. You can rotate text to be aligned vertically, but that's not what you are trying to achieve here.
You can get vertical labels like you want with a little bit of finagling.
I put a sample here:
I hope this answer makes you 大変満足.
Add Spaces
Your data needs to have each character with a space between it so that they can be broken up in to separate lines:
['satisfaction', 'percent'],
['大 変 満 足', 10 ],
['満 足', 22 ],
['や や 満 足', 30 ],
['や や 不 満', 10 ],
['不 満', 5 ]
Change Axis Display Values
For the hAxis you need to set the following options:
maxTextLines: 5,
slantedText: false,
showTextEvery: 1,
minTextSpacing: 40,
maxAlternation: 1
maxTextLines will allow your labels to be broken up in to multiple vertical lines. 4 would likely work as well as 5 here, since you only have 4 characters.
slantedText ends up being used over splitting up over multiple lines for some reason. So I turned it off manually.
showTextEvery prevents it from showing horizontal labels on one line by only display a subset of your axis labels.
minTextSpacing ensures that even though your lines are one character wide, the chart is fooled in to thinking that it needs to add line breaks.
maxAlternation prevents you from having two 'levels' of labels so that they all line up flush with the axis.
Adjust the Height of the Chart
If you leave the chart height as default, there is only space for 2 lines of labels, so you end up with labels that say
や
や
…
To prevent that, you need to artificially increase the height of the chart. There are a dozen ways to do this, I just set the height property manually.

Categories