I need to draw two bar charts facing each other in one page. (The chart on the left faces right, and the one on the right faces left).
But with Google Charts, I only managed to make both charts face right.
Is it possible to implement? What should I do?
using a 100% stacked chart, you can get the bars to align to the right
then color the first series transparent,
and manipulate the data to reveal the proper length
then when the chart's 'ready' event fires,
you can move around the chart elements,
such as the y-axis, and the order of the x-axis labels
first, you need to allow enough room on the left,
for the original y-axis labels to print
otherwise they will be cutoff, i.e.
Canis Major Dwarf vs. Canis Maj...
then need to leave enough room on the right,
by limiting the chartArea, otherwise cutoff and simply not visible, i.e.
Canis Major Dwarf vs. Canis M
might be easier, providing your own labels
this should give you something to tweak on...
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawStuff);
function drawStuff() {
var data = new google.visualization.arrayToDataTable([
['Galaxy', 'Distance', 'Brightness'],
['Canis Major Dwarf', 10, 20],
['Sagittarius Dwarf', 20, 40],
['Ursa Major II Dwarf', 40, 50],
['Lg. Magellanic Cloud', 60, 80],
['Bootes I', 80, 120]
]);
var options = {
isStacked: 'percent',
colors: ['transparent', 'magenta'],
legend: {
position: 'bottom'
},
chartArea: {
left: 200,
width: 400
},
width: 800
};
var container = document.getElementById('dual_x_div');
var chart = new google.visualization.BarChart(container);
google.visualization.events.addListener(chart, 'ready', function () {
var labels = container.getElementsByTagName('text');
var hAxisLabels = [];
Array.prototype.forEach.call(labels, function (text, index) {
switch (text.getAttribute('text-anchor')) {
// move y axis labels
case 'end':
text.setAttribute('x', parseFloat(text.getAttribute('x')) + 540);
break;
// save x axis labels
case 'middle':
// save x position here
// otherwise, x position will change
// before you know where the next should have been
hAxisLabels.push({
text: text,
x: parseFloat(text.getAttribute('x'))
});
break;
}
});
// swap label positions
hAxisLabels.forEach(function (label, index) {
label.text.setAttribute('x', hAxisLabels[hAxisLabels.length - index - 1].x);
});
});
chart.draw(data, options);
};
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="dual_x_div"></div>
Related
I would like to show label and percentage in Google pie chart. Is there any way to do it? In the docs, I found that it is possible to modify text with pieSliceText option. Possible values are:
label - show name of data (e. g. Apples)
value - show absolute value (e. g. 7)
percentage - show percentage value (e. g. 50%)
value-and-percentage - show both value and percentage (e. g. 7 (50%))
But is there something like label-and-percentage to show something like that Apples (50%)?
the only config option that will show both the label & percentage is for the legend...
legend: {
position: 'labeled'
},
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
['Tasks', 'Completed'],
['Morning', 28],
['Afternoon', 43],
['Evening', 80],
['Night', 161]
]);
var options = {
width: 900,
height: 400,
title: 'Tasks Completed',
pieHole: 0.5,
colors: ['#008000', '#ffbf00', '#FF0000','#4E6282'],
pieSliceText: 'value',
sliceVisibilityThreshold :0,
fontSize: 17,
legend: {
position: 'labeled'
},
};
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
chart.draw(data, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
You can show either label or percentage on pie charts. Look at the pieSliceText options here.
But if this is your requirement and you HAVE to show label and percentage both on pie chart that you can try this:
set, pieSliceText: 'value' in options.
And then pass formatted value in data of chart by calculating the percentage of every slice data and passing the label + percentage as formatted value:
data.addRows([
['Label', {v:value, f:'formatted value'}],
]);
here v: is the value of chart
and f: is formatted value of chart which in your case will be label +
percentage.
Eg:
[chartlabels, {v: chartvalue, f: chartlabels+" "+((100 * chartvalue) / totalofvalues).toFixed(2)+"%"}]
How can I create multiple x Axis labels using the google charts API?
Im trying to create a bar graph right now with the main x axis labels as "products" and the individual bars relating to the products in question. However, I would like to segregate a set of 'n' products (data coming in from a database) by months.
Essentially I want a main X Axis label "product" and a dividing line between each set of products and a label underneath this set of bar graphs pertaining to the products grouping together each 'product set' by month
Thanks in advance to anyone who can help me with this!!
Sample double x-axis bar chart with google charts. Taken from their api documentation which can be found here:
Double x-axis bar chart
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['bar']});
google.charts.setOnLoadCallback(drawStuff);
function drawStuff() {
var data = new google.visualization.arrayToDataTable([
['Galaxy', 'Distance', 'Brightness'],
['Canis Major Dwarf', 8000, 23.3],
['Sagittarius Dwarf', 24000, 4.5],
['Ursa Major II Dwarf', 30000, 14.3],
['Lg. Magellanic Cloud', 50000, 0.9],
['Bootes I', 60000, 13.1]
]);
var options = {
width: 800,
chart: {
title: 'Nearby galaxies',
subtitle: 'distance on the left, brightness on the right'
},
bars: 'horizontal', // Required for Material Bar Charts.
series: {
0: { axis: 'distance' }, // Bind series 0 to an axis named 'distance'.
1: { axis: 'brightness' } // Bind series 1 to an axis named 'brightness'.
},
axes: {
x: {
distance: {label: 'parsecs'}, // Bottom x-axis.
brightness: {side: 'top', label: 'apparent magnitude'} // Top x-axis.
}
}
};
var chart = new google.charts.Bar(document.getElementById('dual_x_div'));
chart.draw(data, options);
};
</script>
</head>
<body>
<div id="dual_x_div" style="width: 900px; height: 500px;"></div>
</body>
</html>
Not sure if that is exactly what you want to do, but if not let us know and we can modify this slightly.
Have some trouble with Chart.js
1) is it possible to move bottom labels on top of the chart?
2) is it possible to hide left labels with first grey line?
3) is it possible to set up permanent tooltips(to show temperature) on every point instead of hover tooltips?
Here is my chart http://jsfiddle.net/JohnnyJuarez/ojc09hv4/:
<canvas id="weeksChart" width="651" height="335"></canvas>
var dayTemperatureArray = [-5, 14, 15, 15, 17, 18, 19, 21, 22, 25, 24, 20, 19, 16];
var nightTemperatureArray = [-10, 4, 5, 6, 8, 11, 12, 15, 17, 15, 13, 12, 11, 9];
var dataWeeks = {
labels: ["16.02", "17.02", "18.02", "19.02", "20.02", "21.02", "22.02", "23.02", "24.02", "25.02", "26.02", "27.02", "28.02", "01.03"],
datasets: [
{
label: "Days temperature chart",
fillColor: "transparent",
strokeColor: "rgba(244, 6, 6, 1)",
data: dayTemperatureArray
},
{
label: "Nights temperature chart",
strokeColor: "#3f6bf5",
data: nightTemperatureArray
}
]
};
var ctx = document.getElementById("weeksChart").getContext("2d");
window.weeksChart = new Chart(ctx).Line(dataWeeks, {
responsive: true,
pointDot: true,
datasetStrokeWidth: 0.5,
scaleSteps: 2,
scaleLabel: "<%=value + '°'%>",
tooltipTemplate: "<%= value %>",
showTooltips: true
});
Thanx a lot in advance!
p.s. please avoid jquery, if it's possible :-)
Let's start with the easiest one first
2) is it possible to hide left labels with first grey line?
I assume you meant the y axis labels. You can set the scaleShowLabels option to false in the chart options to hide the y axis labels
window.weeksChart = new Chart(ctx).Line(dataWeeks, {
scaleShowLabels: false,
...
1) is it possible to move bottom labels on top of the chart?
I assume you mean the x axis labels. Chart.js doesn't have a direct option to do this. However you can hide the actual x axis labels and draw the x axis labels at the top of the chart by yourself.
Again, Chart.js doesn't have an option to hide x axis labels, but luckily there is an option to control the scale font color. Just set it to transparent and your original x axis labels are now hidden!
window.weeksChart = new Chart(ctx).Line(dataWeeks, {
scaleFontColor: "transparent",
...
Now the drawing of the x axis labels at the top of the chart. To save us the trouble of extending the chart, we can add a post animation event handler and do this in that, like so
window.weeksChart = new Chart(ctx).Line(dataWeeks, {
onAnimationComplete: function () {
animationComplete.apply(this)
}
...
with
var animationComplete = function () {
var self = this;
Chart.helpers.each(self.datasets[0].points, function (point, index) {
self.chart.ctx.font = Chart.helpers.fontString(self.fontSize, self.fontStyle, self.fontFamily)
self.chart.ctx.textAlign = 'center';
self.chart.ctx.textBaseline = "middle";
self.chart.ctx.fillStyle = "#666";
self.chart.ctx.fillText(point.label, point.x, self.scale.startPoint);
});
};
We just loop through all points in one of the dataset and add the labels (scale.startPoint is the top edge of the chart area)
Note - why do we set the font, alignment, etc. every iteration? That's for when we add the tooltips.
3) is it possible to set up permanent tooltips(to show temperature) on every point instead of hover tooltips?
The first step would be to actually show the tooltips. This is fairly simple, though a bit tedious. We loop through all the x axis point, build the label (by going through each dataset) and then construct a tooltip (fortunately, we can use Chart.MultiTooltip function for this.
We add it into the same loop we used to construct the new x axis labels. Since we need to color our tooltips, we need to get and store the set of colors in an array (which we pass on to the MultiTooltip function - we need to do this only once, so we take it out of the loop.
The modified animationComplete function is now this
var animationComplete = function () {
var self = this;
var tooltipColors = []
Chart.helpers.each(self.datasets, function (dataset) {
tooltipColors.push({
fill: dataset.strokeColor,
stroke: dataset.strokeColor
})
});
Chart.helpers.each(self.datasets[0].points, function (point, index) {
var labels = []
var total = 0;
Chart.helpers.each(self.datasets, function (dataset) {
labels.push(dataset.points[index].value)
total += Number(dataset.points[index].y);
});
new Chart.MultiTooltip({
x: point.x,
y: total / 2,
xPadding: self.options.tooltipXPadding,
yPadding: self.options.tooltipYPadding,
xOffset: self.options.tooltipXOffset,
fillColor: self.options.tooltipFillColor,
textColor: self.options.tooltipFontColor,
fontFamily: self.options.tooltipFontFamily,
fontStyle: self.options.tooltipFontStyle,
fontSize: self.options.tooltipFontSize,
titleTextColor: self.options.tooltipTitleFontColor,
titleFontFamily: self.options.tooltipTitleFontFamily,
titleFontStyle: self.options.tooltipTitleFontStyle,
titleFontSize: self.options.tooltipTitleFontSize,
cornerRadius: self.options.tooltipCornerRadius,
labels: labels,
legendColors: tooltipColors,
legendColorBackground: self.options.multiTooltipKeyBackground,
title: point.label,
chart: self.chart,
ctx: self.chart.ctx,
custom: self.options.customTooltips
}).draw()
self.chart.ctx.font = Chart.helpers.fontString(self.fontSize, self.fontStyle, self.fontFamily)
self.chart.ctx.textAlign = 'center';
self.chart.ctx.textBaseline = "middle";
self.chart.ctx.fillStyle = "#666";
self.chart.ctx.fillText(point.label, point.x, self.scale.startPoint);
});
};
It looks complex, but all we are doing is passing a options that we copy from the chart instance options to the MultiTooltip function.
The tooltips all show up when the animation is complete. HOWEVER, once you move your mouse over the chart they all up and disappear! That's because the chart instance listens for multiple events to decide whether to start checking if tooltips should be shown - one of these is mousemove (and that causes it to redraw the chart, wiping out all our hard drawn tooltips and, if we are lucky, it draws a tooltip based on the point our mouse is hovering over)
This is a configurable option. So, all we have to do is remove all such events.
window.weeksChart = new Chart(ctx).Line(dataWeeks, {
tooltipEvents: []
...
Working fiddle - http://jsfiddle.net/fuodxsfv/
Unless your chart is wide enough, you will have tooltips (mostly the middle 2 ones) overlap (of course you could incorporate logic into the above loop to handle that), but anyhoo, those were actually meant to be tooltips!
I am trying to size a background image on a HighCharts line chart dynamically depending on the position of the top plot line. The image I am trying to size is the bell curve in the image below.
I can't set the height of the image as a static value because the size of the screen can change and the top plot line also changes over time.
At the moment I am setting the position of the plot lines with external functions like this:
plotLines: [
value: upperControl3()}, {
color: '#ccc',
zIndex: 3,
width: 1,
label: {
text: '-2s',
x: 520,
y: 3
}
The closest thing to the y value of the top plot line I have been able to find is a dataMax value but this stays the same on every chart load.
I have been trying to overlay and size the image with a function at the end of the chart like this:
function(chart) {
console.log(chart.yAxis[0].plotLinesAndBands[7].axis.plotLinesAndBands[0].axis);
var h = chart.yAxis[0].plotLinesAndBands[7].axis.plotLinesAndBands[0].axis.dataMax;
var y = chart.yAxis[0].axisTitle.y + extra;
// X, Y, Width, Height
chart.renderer.image('images/bell.jpg', 60, y, 200, h).add();
}
Is the any way to find the coordinates of a plot line in highcharts?
You can use plotLinesAndBands object, where plotlines are kept. In the options you have value, whcih can be translated into pixels value by toPixels function.
var $button = $('#button'),
$report = $('#report'),
chart = $('#container').highcharts();
$button.click(function () {
chart.xAxis[0].addPlotLine({
value: 5.5,
color: 'red',
width: 2,
id: 'plot-line-1'
});
var plotline = chart.xAxis[0].plotLinesAndBands[0];
$report.html('Value: ' + plotline.options.value + ' Pixels: ' + chart.xAxis[0].toPixels(plotline.options.value));
});
http://jsfiddle.net/HhP39/1/
If you know which plot line (by index) it is, you can do this:
chart.yAxis[0].plotLinesAndBands[0].options.value
Of course, you need to make sure your data is actually normally distributed, or else that normal curve means nothing :)
And zero-bounded data is not usually normally distributed.
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.