Change chart y-axis text orientation - javascript

I want to change my Google Chart's y-axis title to horizontal orientation. Currently, it is drawn with vertical writing, as shown in this image:
My chart drawing code
function drawVisualization() {
// Some raw data (not necessarily accurate)
var data = google.visualization.arrayToDataTable(temp);
var options = {
title: 'Report',
// vAxis: {title: 'Cups'},
hAxis: {
title: 'Date'
},
seriesType: 'bars',
series: {
0: {
targetAxisIndex: 0
},
1: {
targetAxisIndex: 1,
type: 'line'
}
},
vAxes: {
0: {
title: '報酬額',
titleTextStyle: {
italic: false,
}
},
1: {
title: '再生',
titleTextStyle: {
italic: false,
}
},
},
'chartArea' : {'width': '70%', left: '15%'}
};
var chart = new google.visualization.ComboChart(document.getElementById('chart_div'));
chart.draw(data, options);
}

You can see in the Axis Overview:
Direction - You can customize the direction using the
hAxis/vAxis.direction option.
hAxis.direction The direction in which the values along the
horizontal axis grow. Specify -1 to reverse the order of the values.
Type: 1 or -1 Default: 1
If this didn't answer the question, try the workarounds from this SO post.

I did like this. And works well. I don't think this is pretty way.
If anyone find better way Please say to me thanks.
var textTags = document.getElementsByTagName("text");
var searchPlay = "Play";
var searchProfit = "Profit"
$.each(textTags, function(index,value){
if (value.textContent == searchPlay) {
$(this).css('transform','rotate(1turn)');
console.log(value);
}
if (value.textContent == searchProfit) {
console.log(value);
$(this).css('transform', 'rotate(1turn)');
}
});

Related

Format numbers on google bar chart with dual x-Axes (decimal)

How is it possible to format the number values on a google bar chart with dual x-Axes?
The top axes with the label support should have at least four decimal places, like the value shown in the tooltip.
What I have tried is this approach, but it doesn't seem to work.
My code:
data.addColumn('string', 'RuleName');
data.addColumn('number', 'Lift');
data.addColumn('number', 'Support');
for (var i = 0; i < chartsdata.length; i++) {
data.addRow([rule, Lift,Support)]);
}
// format numbers in second column to 5 decimals
var formatter = new google.visualization.NumberFormat({
pattern: '#,##0.00000'
}); // This does work, but only for the value in the tooltip.
formatter.format(data, 2);
// Passing in some options
var chart = new google.charts.Bar(document.getElementById('barChart'));
var options = {
title: "Association Rules by lift and support",
bars: 'horizontal',
series: {
0: { axis: 'Lift', targetAxisIndex: 0, },
1: { axis: 'Support', targetAxisIndex: 1}
},
axes: {
x: {
Lift: { label: 'Lift', format: '0,000' //Doesn't work, }, // Bottom x-axis.
Support: { side: 'top', label: 'Support' } // Top x-axis.
}
}, ..........
What I also tried is this approach from the google doc:
series:{hAxes:{1:{title:'abc', format: '0,0000'}}
Any help would be greatly appreciated!
there are several options that are not supported by Material charts
see --> Tracking Issue for Material Chart Feature Parity
although format is not listed, there are several options not supported for --> {hAxis,vAxis,hAxes.*,vAxes.*}
so that could be the problem
note: the above options should stand alone and not be included in the series option,
as seen in the question (What I also tried...)
you can change both x-axis formats by using hAxis.format
but don't think you'll be able to change just one
see following working snippet...
google.charts.load('current', {
packages: ['bar']
}).then(function () {
var data = new google.visualization.DataTable();
data.addColumn('string', 'RuleName');
data.addColumn('number', 'Lift');
data.addColumn('number', 'Support');
for (var i = 0; i < 10; i++) {
data.addRow([i.toString(), i+2, i+3]);
}
var formatter = new google.visualization.NumberFormat({
pattern: '#,##0.00000'
});
formatter.format(data, 2);
var chart = new google.charts.Bar(document.getElementById('barChart'));
var options = {
chart: {
title: 'Association Rules by lift and support'
},
bars: 'horizontal',
series: {
0: {axis: 'Lift'},
1: {axis: 'Support'}
},
axes: {
x: {
Lift: {label: 'Lift'},
Support: {side: 'top', label: 'Support'}
}
},
hAxis: {
format: '#,##0.00000'
},
height: 320
};
chart.draw(data, google.charts.Bar.convertOptions(options));
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="barChart"></div>

How to display several labels in Highchart.js?

I have basic Waterfall chart (HighChart.js) basic Waterfall chart image example
How display two labels on each column? Besides, first label must be at top of column and another label must be on bottom of column. So it should be exactly like on image.
Now I have two ideas:
First label is rendered on first chart, second value will be rendered on additional hidden chart (link to example: [http://jsfiddle.net/gk14kh3q/1/][3])
$(function () {
$('#container').highcharts({
chart: {
type: 'waterfall'
},
title: {
text: 'Highcharts Waterfall'
},
xAxis: {
type: 'category'
},
yAxis: {
title: {
text: 'USD'
}
},
legend: {
enabled: false
},
series: [{
dataLabels: {
enabled: true,
// here need align label
}
}, {
dataLabels: {
enabled: true,
// here need align label
}
}]
});
});
Combine two label in one by using formatting function and useHTML property. And after that set position to labels by using css or external js
May be some others practices exist? I'll be very pleased for help. Even discussion can be usefull. Thank you!
P.S. How I could insert icons to chart like on provided image?
You can use chart.renderer.label for adding new dataLabels for your column points. You can also use chart.renderer.image for adding arrows to your chart:
var addLabels = function(chart) {
$('.custom').remove();
var series = chart.series[0],
url;
Highcharts.each(series.data, function(p, i) {
if (i) {
chart.renderer.label(p.secondLabel, p.plotX + chart.plotLeft, p.yBottom + chart.plotTop).attr({
'text-anchor': 'middle'
}).addClass('custom').add();
if (p.y > 0) {
url = 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/Arrow_up.svg/1000px-Arrow_up.svg.png';
} else {
url = 'https://upload.wikimedia.org/wikipedia/en/f/f1/Down_Arrow_Icon.png'
}
chart.renderer.image(url, p.plotX + chart.plotLeft, chart.plotTop + chart.plotHeight - 15, 8, 13).addClass('custom').add()
}
});
};
Here you can find an example how it can work:
http://jsfiddle.net/zc2fb8vt/

Data Not Showing in Highcharts

I'm attempting to combine a couple of different chart demos from Highcharts.
My examples are: Data classes and popup and Small US with data labels
I want the map from the first with the popup feature of the second. I need to connect the map to my own google spreadsheet but for now I'm just trying to get the data from the first example to work.
This is what I have so far but can't seem to get any data in the map. I thought I had a joinBy problem, and I may still, but when I set joinBy to null I thought "the map items are joined by their position in the array", yet nothing happened.
https://jsfiddle.net/9eq6mydv/
$(function () {
// Load the data from a Google Spreadsheet
// https://docs.google.com/a/highsoft.com/spreadsheet/pub?hl=en_GB&hl=en_GB&key=0AoIaUO7wH1HwdFJHaFI4eUJDYlVna3k5TlpuXzZubHc&output=html
Highcharts.data({
googleSpreadsheetKey: '0AoIaUO7wH1HwdDFXSlpjN2J4aGg5MkVHWVhsYmtyVWc',
googleSpreadsheetWorksheet: 1,
// custom handler for columns
parsed: function (columns) {
// Make the columns easier to read
var keys = columns[0],
names = columns[1],
percent = columns[10],
// Initiate the chart
options = {
chart : {
renderTo: 'container',
type: 'map',
borderWidth : 1
},
title : {
text : 'US presidential election 2008 result'
},
subtitle: {
text: 'Source: <a href="http://en.wikipedia.org/wiki/United_States_presidential_election,' +
'_2008#Election_results">Wikipedia</a>'
},
mapNavigation: {
enabled: true,
enableButtons: false
},
legend: {
align: 'right',
verticalAlign: 'top',
x: -100,
y: 70,
floating: true,
layout: 'vertical',
valueDecimals: 0,
backgroundColor: (Highcharts.theme && Highcharts.theme.legendBackgroundColor) || 'rgba(255, 255, 255, 0.85)'
},
colorAxis: {
dataClasses: [{
from: -100,
to: 0,
color: '#C40401',
name: 'McCain'
}, {
from: 0,
to: 100,
color: '#0200D0',
name: 'Obama'
}]
},
series : [{
data : data,
dataLabels: {
enabled: true,
color: '#FFFFFF',
format: '{point.code}',
style: {
textTransform: 'uppercase'
}
},
mapData: Highcharts.geojson(Highcharts.maps['countries/us/custom/us-small']),
joinBy: keys,
name: 'Democrats margin',
point: {
events: {
click: pointClick
}
},
tooltip: {
ySuffix: ' %'
},
cursor: 'pointer'
}, {
type: 'mapline',
data: Highcharts.geojson(Highcharts.maps['countries/us/custom/us-small'], 'mapline'),
color: 'silver'
}]
};
/**
* Event handler for clicking points. Use jQuery UI to pop up
* a pie chart showing the details for each state.
*/
function pointClick() {
var row = this.options.row,
$div = $('<div></div>')
.dialog({
title: this.name,
width: 400,
height: 300
});
window.chart = new Highcharts.Chart({
chart: {
renderTo: $div[0],
type: 'pie',
width: 370,
height: 240
},
title: {
text: null
},
series: [{
name: 'Votes',
data: [{
name: 'Obama',
color: '#0200D0',
y: parseInt(columns[3][row], 10)
}, {
name: 'McCain',
color: '#C40401',
y: parseInt(columns[4][row], 10)
}],
dataLabels: {
format: '<b>{point.name}</b> {point.percentage:.1f}%'
}
}]
});
}
// Read the columns into the data array
var data = [];
$.each(keys, function (i, key) {
data.push({
key: key,//.toUpperCase(),
value: parseFloat(percent[i]),
name: names,
row: i
});
});
// Initiate the chart
window.chart = new Highcharts.Map(options);
},
error: function () {
$('#container').html('<div class="loading">' +
'<i class="icon-frown icon-large"></i> ' +
'Error loading data from Google Spreadsheets' +
'</div>');
}
});
});
UPDATE:
I wanted to share with everyone my final solution. Although Ondkloss did a magnificent job answering my question the popup feature still didn't work and this is because I forgot to include the jQuery for the .dialog call. Once I included that I had an empty popup with a highchart error 17, this is because the highmaps.js code doesn't include the pie chart class. So I had to add the highcharts.js code and include map.js module afterward. You can see my final jsfiddle here.
Thanks again to Ondkloss for the excellent answer!
The problem here mostly comes down to the use of joinBy. Also to correct it there are some required changes to your data and mapData.
Currently your joinBy is an array of strings, like ["al", "ak", ...]. This is quite simply not an accepted format of the joinBy option. You can read up on the details in the API documentation, but the simplest approach is to have a attribute in common in data and mapData and then supply a string in joinBy which then joins those two arrays by that attribute. For example:
series : [{
data : data,
mapData: mapData,
joinBy: "hc-key",
]
Here the "hc-key" attribute must exist in both data and mapData.
Here's how I'd create the data variable in your code:
var data = [];
$.each(keys, function (i, key) {
if(i != 0)
data.push({
"hc-key": "us-"+key,
code: key.toUpperCase(),
value: parseFloat(percent[i]),
name: names[i],
row: i
});
});
This skips the first key, which is just "Key" (the title of the column). Here we make the "hc-key" fit the format of the "hc-key" in our map data. An example would be "us-al". The rest is just metadata that will be joined in. Note that you were referencing your data in the options prior to filling it with data, so this has to be moved prior to this.
This is how I'd create the mapData variable in your code:
var mapData = Highcharts.geojson(Highcharts.maps['countries/us/custom/us-small']);
// Process mapdata
$.each(mapData, function () {
var path = this.path,
copy = { path: path };
// This point has a square legend to the right
if (path[1] === 9727) {
// Identify the box
Highcharts.seriesTypes.map.prototype.getBox.call(0, [copy]);
// Place the center of the data label in the center of the point legend box
this.middleX = ((path[1] + path[4]) / 2 - copy._minX) / (copy._maxX - copy._minX);
this.middleY = ((path[2] + path[7]) / 2 - copy._minY) / (copy._maxY - copy._minY);
}
// Tag it for joining
this.ucName = this.name.toUpperCase();
});
The first part is your "standard map data". The rest is to correctly center the labels for the popout states, and gotten directly from the example.
And voila, see this JSFiddle demonstration to witness your map in action.
I suggest doing some console.log-ing to see how data and mapData have the hc-key in common and that leads to the joining of the data in the series.

Bar overlapping issue in google chart - Combo chart

I am having a little problem with google chart implementation. As per requirement, I should have dual y-axis and the bars for y-axis should be overlapping. I achieved following output with my code:
Notice the two blue arrows for last two bars. The blue bar is hidden behind red bar as its smaller. It should actually look something like this:
This is my code for js file:
var chart, data;
google.load('visualization', '1.0', {'packages':['corechart']});
google.setOnLoadCallback(drawChart);
function drawChart()
{
// Create the data table.
data = new google.visualization.DataTable();
data.addColumn('string', 'Topping');
data.addColumn('number', 'Slices');
data.addColumn('number', 'pieces');
data.addColumn('number', 'ratio');
data.addColumn('number', 'ratio2');
data.addRows([
['Mushrooms', 300, 200, 50, 1],
['Onions', 100, 244, 4, 3],
['Olives', 100, 400, 56, 10]
]);
// Set chart options
options = {
chartType:"ComboChart",
containerId:"visualization",
stackSeries: true,
isStacked : true,
seriesDefaults: {
rendererOptions: {
barPadding: 0,
barMargin: 10
},
pointLabels: {
show: true,
stackedValue: true
}
},
grid: {
background: '#272424',
drawGridlines: false
},
seriesType: "bars",
series: {
0: {
targetAxisIndex: 0
},
1: {
targetAxisIndex: 1
},
2: {
targetAxisIndex: 1,
type: "line"
},
3: {
type: "line"
}
},
hAxis:{
},
vAxes: {
0: {
title: "Slices",
label:'Slices',
type:'bars'
},
1: {
title: "pieces",
label:'pieces',
type:'bars'
},
2: {
title: "ratio,",
label:'ratio',
type:'line'
},
3: {
title: "ratio2,",
label:'ratio2',
type:'line'
}
}
};
// Instantiate and draw our chart, passing in some options.
chart = new google.visualization.ComboChart(document.getElementById('chart_div'));
chart.draw(data, options);
google.visualization.events.addListener(chart, 'select', selectionHandler);
}
function selectionHandler() {
var selectedData = chart.getSelection(), row, item;
if(selectedData != '')
{
row = selectedData[0].row;
item = data.getValue(row,3);
alert("You selected :" + item);
}
}
Can anyone suggest me how could I go about this? Any help would be appreciated.
You are displaying your bars on separate axes:
0: {
targetAxisIndex: 0
},
1: {
targetAxisIndex: 1
},
2: {
targetAxisIndex: 1,
type: "line"
},
3: {
type: "line"
}
So the first bar is on the left axis, the second is on the right axis. The first bar only shows because it is taller than the red bar in front of it. This is by design. If you want them to display stacked, change your code to this:
0: {
targetAxisIndex: 0
},
1: {
targetAxisIndex: 0
},
2: {
targetAxisIndex: 1,
type: "line"
},
3: {
targetAxisIndex: 1,
type: "line"
}
This will end up with this:
Note that your two axes no longer have equivalent size. Adjust other parameters as needed. If you want them side by side, you can put them on the same axis and remove isStacked: true which will make them stand next to each other.
Note: This sort of chart is incredibly busy and is likely not good visualization practice. Regardless, if you need to create a chart, the above solution should work. If you actually mean that you want the smaller bar in front, then good luck with SVG editing.
There actually is a way to get what you want, using a DataView to split your blue data series into two. Make one series where the data is greater than red series, and one where it is less than or equal to the red series, and position them (in order) greater than, red, less than. In the series option, set this new series to be the same color as the first, and hide it from the index.
Here's the DataView you would use:
var view = new google.visualization.DataView(data);
view.setColumns([0, {
type: 'number',
label: data.getColumnLabel(1),
calc: function (dt, row) {
var val = dt.getValue(row, 1);
return (val > dt.getValue(row, 2)) ? val : null;
}
}, 2, {
type: 'number',
label: data.getColumnLabel(1),
calc: function (dt, row) {
var val = dt.getValue(row, 1);
return (val <= dt.getValue(row, 2)) ? val : null;
}
}, 3, 4]);
and here's the series option:
series: {
0: {
targetAxisIndex: 0
},
1: {
targetAxisIndex: 1
},
2: {
targetAxisIndex: 0,
visibleInLegend: false,
color: '#3366cc' // matches series 0
},
3: {
targetAxisIndex: 1,
type: "line"
},
4: {
type: "line"
}
}
Draw the chart with the view instead of the DataTable:
chart.draw(view, options);
See it working here: http://jsfiddle.net/asgallant/4jhC5/

Extjs 4.2.1 Stacked bar chart Minimum and maximium values changes based on store

Hi i am working on a extjs 4.2.1 application in which i am using the bar chart (stacked) . In x axis i want range from -100(minimum) to maximum (100) with a difference of 20 (majorTickSteps=10).
Below is the code
var store = Ext.create('Ext.data.JsonStore', {
fields: ['name', 'cost','sell'],
data: [
{'name': "2013", 'cost': -36.483395098129556, 'sell': 25.516604901870444},
{'name': "2013", 'cost': -27.483395098129556, 'sell': 8.516604901870444},
{'name': "2013", 'cost': -35.483395098129556, 'sell': 19.516604901870444},
{'name': "2013", 'cost': -25.483395098129556, 'sell': 33.516604901870444}
]
});
Ext.create('Ext.chart.Chart', {
renderTo: Ext.getBody(),
id:'chart',
width: 580,
height: 165,
animate: true,
store: store,
axes: [{
type: 'Numeric',
position: 'bottom',
fields: ['cost','sell'],
grid: true,
minimum: -100,
maximum:100
}, {
type: 'Category',
position: 'left',
fields: ['name']
}],
series: [{
type: 'bar',
axis: 'bottom',
stacked: true,
xField: 'name',
yField: ['cost','sell']
}]
});
if stacked = true , x axis minimum and maximum values are changed based on the store
if stacked = false, x axis minimum and maximum remains same , but it is not stacked.
I need stacked bar chart with minimum and maximum values which i specified. How can i proceed . Any help would be greatly appreciated.
This is a known issue (EXTJSIV-7844) in ExtJS. A solution is to override the processView function for your axis.
The original code looks like this (see the docs):
processView: function() {
var me = this,
chart = me.chart,
series = chart.series.items,
i, l;
for (i = 0, l = series.length; i < l; i++) {
if (series[i].stacked) {
// Do not constrain stacked charts (bar, column, or area).
delete me.minimum;
delete me.maximum;
me.constrain = false;
break;
}
}
if (me.constrain) {
me.doConstrain();
}
}
As you can see, there is code in place to intentionally prevent you from doing what you're trying to do. I'm not sure why the code is there, but a simple fix is to override the processView function such that it doesn't do that.
processView: function() {
var me = this;
if (me.constrain) {
me.doConstrain();
}
}
See this fiddle for a working example.

Categories