How to put vertical lines on google chart scatter - charts

How I can make vertical lines on a scatter google chart?
I need to put the red line vertically:
here is my current code:
//making array with data
var dataArray = [];
dataArray.push(["", "", { role: 'annotation' }, "", ""]);
projects.forEach(function(item, index){
dataArray.push([parseFloat(item["bottomData"]), parseFloat((item["leftData"])), index+1, 10, 15]);
});
var data = google.visualization.arrayToDataTable(dataArray);
//define ticks
var rangeX = data.getColumnRange(0);
var ticksX = [];
for (var i = (Math.floor(rangeX.min / 5) * 5); i <= (Math.ceil(rangeX.max / 5) * 5); i = i + 5) {
ticksX.push(i);
}
var rangeY = data.getColumnRange(1);
var ticksY = [];
for (var i =(Math.floor(rangeY.min/5) * 5); i <= Math.ceil(rangeY.max/5) * 5; i=i+5) {
ticksY.push(i);
}
//define options
var options = {
series: {
1: {
lineWidth: 2,
pointSize: 0,
color: 'green'
},
2: {
lineWidth: 2,
pointSize: 0,
color: 'red'
},
},
colors:['002060'],
vAxis: {
ticks: ticksY,
},
hAxis: {
ticks: ticksX,
},
};
//print chart
var chart = new google.visualization.ScatterChart(document.getElementById("chartDiv"));
chart.draw(data, options);
I also tried using multiple axes putting some with direction=-1 or orientation=vertical but it doesn't work

in order to mix line series with scatter,
you will need to use a ComboChart
and to get vertical lines,
you will need to add multiple rows with the same x axis value,
with values for the min and max y axis values.
in the options, set the seriesType to 'scatter'
and change the series type to 'line'
see following working snippet...
google.charts.load('current', {
packages:['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
['x', 'y0', {role: 'annotation', type: 'number'}],
[26, 1, 1],
[33, 5, 2],
[36, 1, 3],
[38, 6, 4],
[58, 1, 5]
]);
var ticksX = [25, 30, 35, 40, 45, 50, 55, 60];
var ticksY = [0, 5, 10, 15, 20, 25];
data.addColumn('number', 'y1');
data.addColumn('number', 'y2');
//red line (vertical)
ticksY.forEach(function (value) {
data.addRow([40, null, null, null, value]);
});
//green line (horizontal)
ticksX.forEach(function (value) {
data.addRow([value, null, null, 10, null]);
});
data.sort([{column: 0}]);
var options = {
interpolateNulls: true,
seriesType: 'scatter',
series: {
1: {
color: 'green',
type: 'line'
},
2: {
color: 'red',
type: 'line'
},
},
colors:['002060'],
vAxis: {
ticks: ticksY
},
hAxis: {
ticks: ticksX
},
};
var chart = new google.visualization.ComboChart(document.getElementById("chartDiv"));
chart.draw(data, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chartDiv"></div>

Related

Google BarChart - the horizontal base line is not appearing

First of all, sorry for combining multiple questions in to one. The only reason is all of them are related (hopefully) to one particular chart type.
QUESTION 1: The horizontal baseline is not appearing.
Actual
Requirement
QUESTION 2: Fraction values.
Is there a way to display only integers? I don't need fraction values in grid lines. Please see the above screenshot.
QUESTION 3: Vertical Line annotation text placement.
The annotation text for the vertical black bold line is coming to the right of it hence it is getting cut. Please see the second chart in the following screenshot
This actually needs to appear like this (to the bottom of the line and the annotation text needs to come a bit below base line labels). Please see the following screenshot
Is that is not possible, is there any way to place the annotation text to the left of this line so that it doesn't get cut and the entire annotation text stays inside the chart?
Below is the chart script I am using:
google.charts.load('current', {packages: ['corechart', 'bar']});
google.charts.setOnLoadCallback(drawHorizontalChart_portal_name_stella_york_horz_month_points);
function drawHorizontalChart_portal_name_stella_york_horz_month_points() {
var data = google.visualization.arrayToDataTable([
["", "Goal Achieved", {role: 'style'}, "GOAL 13.1 points", {role: 'style'}, {role: 'annotation'}],
["", 1.5, "opacity: .75;", 13.1, "opacity: 0;", "GOAL 13.1 points"]
]);
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, {
calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation"
}, 3, 4, 5]);
var options = {
title: '',
width: '100%',
height: 120,
chartArea: {
width: '90%',
height: 70
},
hAxis: {
title: '',
minValue: 0,
gridlines: {
count: 6
}
},
bar: {
groupWidth: "60%"
},
legend: {
position: "top"
},
series: {
0: {
color: '#70b5c5',
visibleInLegend: false
}, // Goal Achieved
1: {
color: '#000000',
type: 'line',
annotations: {
textStyle: {
color: '#000000',
textPosition: 'vertical'
},
stemColor: 'none',
vertical: true
}
} // Target Goal
}
};
var chart = new google.visualization.BarChart(document.getElementById("portal-name-stella-york-horz-month-points"));
chart.draw(view, options);
drawVAxisLine(chart, 13.1);
}
jQuery(window).resize(function() {
drawHorizontalChart_portal_name_stella_york_horz_month_points();
});
function drawVAxisLine(chart, value) {
var layout = chart.getChartLayoutInterface();
var chartArea = layout.getChartAreaBoundingBox();
var svg = chart.getContainer().getElementsByTagName('svg')[0];
var xLoc = layout.getXLocation(value)
svg.appendChild(createLine(xLoc, chartArea.top + chartArea.height, xLoc, chartArea.top, '#000000', 2)); // axis line
}
function createLine(x1, y1, x2, y2, color, w) {
var line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('x1', x1);
line.setAttribute('y1', y1);
line.setAttribute('x2', x2);
line.setAttribute('y2', y2);
line.setAttribute('stroke', color);
line.setAttribute('stroke-width', w);
return line;
}
1) horizontal baseline
the horizontal baseline does not appear because you have a string value in the first column
this creates a discrete axis
// string used here --> ["", 1.5, "opacity: .75;", 13.1, "opacity: 0;", "GOAL 13.1 points"]
instead, use a continuous x-axis (number, date, etc...)
// number --> [1, 1.5, "opacity: .75;", 13.1, "opacity: 0;", "GOAL 13.1 points"]
in order to hide the axis label, as done using the string, we can provide custom axis ticks
we can use object notation to provide both the value (v:) and the formatted value (f:)
which allows us to provide an empty string for the formatted value
just make sure the tick value matches the value provided in the first column above.
vAxis: {
gridlines: {
color: 'transparent'
},
ticks: [{v: 1, f: ''}]
}
note: a continuous axis will also cause other gridlines to appear,
we can remove those by making them transparent...
2) Fraction values
we can provide a format string for the axis labels...
hAxis: {
format: '0' // <-- format as integer
},
3) annotation text placement
the only available option here is stem.length
we can provide a negative value to move the annotation to the left...
stem: {
color: 'transparent',
length: -128
},
however, the actual position will not remain constant as the chart is resized
when the chart is smaller, the text will be farther away from the line (larger closer).
instead, we can manually move the annotation text, on the chart's 'ready' event.
but we should still use a negative stem length, to ensure the annotation appears to the left, and prevent from being cut. otherwise, we'll end up moving a cut annotation.
and since we're moving the annotation below the axis,
we need to increase chartArea.bottom or else it will be cut there as well.
finally, the chart will reset the annotation's position on any interactivity,
such as hover. we must use a MutationObserver to keep the annotation in the new position.
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(drawHorizontalChart_portal_name_stella_york_horz_month_points);
function drawHorizontalChart_portal_name_stella_york_horz_month_points() {
var data = google.visualization.arrayToDataTable([
["", "Goal Achieved", {role: 'style'}, "GOAL 13.1 points", {role: 'style'}, {role: 'annotation'}],
[1, 1.5, "opacity: .75;", 13.1, "opacity: 0;", "GOAL 13.1 points"]
]);
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, {
calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation"
}, 3, 4, 5]);
var options = {
title: '',
width: '100%',
height: 132,
chartArea: {
height: '100%',
width: '100%',
top: 36,
left: 18,
right: 18,
bottom: 48
},
hAxis: {
title: '',
minValue: 0,
gridlines: {
count: 6
},
format: '0'
},
bar: {
groupWidth: "60%"
},
legend: {
position: "top"
},
series: {
0: {
color: '#70b5c5',
visibleInLegend: false
}, // Goal Achieved
1: {
color: '#000000',
type: 'line',
annotations: {
textStyle: {
color: '#000000'
},
stem: {
color: 'transparent',
length: -128
},
vertical: true
}
} // Target Goal
},
vAxis: {
gridlines: {
color: 'transparent'
},
ticks: [{v: 1, f: ''}]
}
};
var chart = new google.visualization.BarChart(document.getElementById("portal-name-stella-york-horz-month-points"));
google.visualization.events.addListener(chart, 'ready', function () {
// get x location of goal
var layout = chart.getChartLayoutInterface();
var xLoc = drawVAxisLine(chart, layout, data.getValue(0, 3));
// prevent annotation reset
var observer = new MutationObserver(function () {
var annotationText = data.getValue(0, data.getNumberOfColumns() -1);
Array.prototype.forEach.call(chart.getContainer().getElementsByTagName('text'), function(annotation) {
// find annotation
if ((annotation.textContent === annotationText) &&
(annotation.getAttribute('fill') === options.series[1].annotations.textStyle.color)) {
// move annotation
annotationBounds = annotation.getBBox();
annotation.setAttribute('x',
xLoc - (annotationBounds.width / 2)
);
annotation.setAttribute('y',
layout.getYLocation(0) + (parseInt(annotation.getAttribute('font-size')) * 3)
);
}
});
});
observer.observe(chart.getContainer(), {
childList: true,
subtree: true
});
});
chart.draw(view, options);
}
jQuery(window).resize(function() {
drawHorizontalChart_portal_name_stella_york_horz_month_points();
});
function drawVAxisLine(chart, layout, value) {
var chartArea = layout.getChartAreaBoundingBox();
var svg = chart.getContainer().getElementsByTagName('svg')[0];
var xLoc = layout.getXLocation(value)
svg.appendChild(createLine(xLoc, chartArea.top + chartArea.height, xLoc, chartArea.top, '#000000', 2)); // axis line
return xLoc;
}
function createLine(x1, y1, x2, y2, color, w) {
var line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('x1', x1);
line.setAttribute('y1', y1);
line.setAttribute('x2', x2);
line.setAttribute('y2', y2);
line.setAttribute('stroke', color);
line.setAttribute('stroke-width', w);
return line;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="portal-name-stella-york-horz-month-points"></div>
note: you should wait for the 'ready' event before making any changes / adding elements to the chart.

Offset tick labels to center between ticks on horizontal bar chart

I am creating a horizontal bar chart using Google charts and I want to position the horizontal axis tick labels between ticks (offset tick label to the right by half a tick). There is also no guarantee that each label will be the same number of characters. Is there any functionality to achieve this?
This is my function for creating the chart
function drawChart() {
var data = google.visualization.arrayToDataTable([
["Performance", "Level", { role: "style" }],
["PL", 1.01, "#5aa66d"]
]);
var view = new google.visualization.DataView(data);
view.setColumns([0, 1,
{
calc: function (dt, rowIndex) { return 'PL=' + (dt.getValue(rowIndex, 1)).toString()} ,
sourceColumn: 1,
type: "string",
role: "annotation"
},
2]);
var options = {
width: 600,
height: 100,
bar: { groupWidth: "80%" },
legend: { position: "none" },
hAxis: {
minValue: 0,
maxValue: 3,
ticks: [
{ v: 0, f: 'Col1' },
{ v: 1, f: 'Col2' },
{ v: 2, f: 'Col3' },
{ v: 3, f: 'Col4' }
]
}
};
var chart = new google.visualization.BarChart(document.getElementById("barchart_values"));
chart.draw(view, options);
}
This is the chart currently
https://imgur.com/LvQEbtY
and this is what I want to achieve:
https://imgur.com/hwvIOG2
EDIT:
For ideas, right before chart.draw I add an event listener and find all the text tags and modify the 'x' attribute to re-position the tick labels. This works, but it also affects the on-bar data label which is a problem.
google.visualization.events.addListener(chart, 'ready', function () {
var elements = document.getElementById("barchart_values").getElementsByTagName("text");
for (var i = 0; i < elements.length; i++) {
elements[i].setAttribute('x', (Number(elements[i].getAttribute('x')) + (chart.getChartLayoutInterface().getBoundingBox('chartarea').width / 4 / 2))); //chart width / tick count / 2
}
});
first, we won't be able to offset the grid lines and use the ticks option.
let's offset the grid lines by making the major transparent and the minor visible.
we can also offset the baseline by setting to a negative value.
baseline: -0.5,
minorGridlines: {
color: '#cccccc',
count: 1
},
gridlines: {
color: 'transparent',
count: 4
},
then, in order to have custom tick labels, we can use your original idea to change them manually.
just need a unique attribute to separate them from the bar labels.
here, the text-anchor attribute is used.
if (elements[i].getAttribute('text-anchor') === 'middle') {
elements[i].textContent = 'Col' + parseInt(elements[i].textContent) + 1;
}
see following working snippet...
google.charts.load('current', {
packages:['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
["Performance", "Level", { role: "style" }],
["PL", 1.01, "#5aa66d"]
]);
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, {
calc: function (dt, rowIndex) { return 'PL=' + (dt.getValue(rowIndex, 1)).toString()} ,
sourceColumn: 1,
type: "string",
role: "annotation"
}, 2]);
var options = {
width: 600,
height: 100,
bar: { groupWidth: "80%" },
legend: { position: "none" },
hAxis: {
baseline: -0.5,
minorGridlines: {
color: '#cccccc',
count: 1
},
gridlines: {
color: 'transparent',
count: 4
},
minValue: 0,
maxValue: 3,
}
};
var chart = new google.visualization.BarChart(document.getElementById("barchart_values"));
google.visualization.events.addListener(chart, 'ready', function () {
var elements = document.getElementById("barchart_values").getElementsByTagName("text");
for (var i = 0; i < elements.length; i++) {
if (elements[i].getAttribute('text-anchor') === 'middle') {
elements[i].textContent = 'Col' + (parseInt(elements[i].textContent) + 1);
}
}
});
chart.draw(view, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="barchart_values"></div>
the above will ensure all the labels remain visible, just simply moving them, could cause them to be pushed off the visible portion of the chart.

Google Charts - Apply margin on y-axis values

What I'd like to do, is to increase the margin between the y-axis values and the corresponding bar within the chart.
So if I have a bar in the chart which has a value of "Python" on the Y- axis, I want to increase the space between the string "Python" and the visual bar.
Now:
Python__========================================================
My goal:
Python___________=========================================================
___ represents the space between y-axis label and visual bar
I tried to use chartArea{right:200} and textPosition:out in the options section of the chart.
var options = {
chartArea:{right: 200},
'vAxis': {
title:'',
textStyle : {
fontSize: 25
},
textPosition: 'out'
},
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Coding-Skills', 'Skill-Level'],
['C', {v: 0.3, f:'low'}],
['Python', {v: 1, f:'medium'}],
['Javascript', {v: 1.5, f:'medium'}],
['HTML/CSS', {v: 1.5, f:'medium'} ]
]);
var options = {
chartArea: {
left: 1400
},
'hAxis': {
gridlines:{
count: 0},
textStyle : {
fontSize: 25
}
},
'vAxis': {
title:'',
textStyle : {
fontSize: 25
}
},
chart: {
},
bars: 'horizontal',
axes: {
x: {
0: { side: 'bottom', label: 'Years of experience'} ,
textStyle : {
fontSize: 35
}
}
}
};
var chart = new google.charts.Bar(document.getElementById('barchart_material'));
chart.draw(data, google.charts.Bar.convertOptions(options));
}
Applying margin-right
no options for label margins,
but you can move them manually on the chart's 'ready' event
find the labels and change the 'x' attribute
see following working snippet,
here, the chartArea option is used to ensure there is enough room...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
['Language', 'Skill-Level'],
['C', 20],
['Python', 35],
['Javascript', 50]
]);
var container = document.getElementById('chart_div');
var chart = new google.visualization.BarChart(container);
google.visualization.events.addListener(chart, 'ready', function () {
var labels = container.getElementsByTagName('text');
Array.prototype.forEach.call(labels, function(label) {
// move axis labels
if (label.getAttribute('text-anchor') === 'end') {
var xCoord = parseFloat(label.getAttribute('x'));
label.setAttribute('x', xCoord - 20);
}
});
});
var options = {
chartArea: {
left: 100,
right: 200
},
colors: ['#aaaaaa'],
hAxis: {
baselineColor: 'transparent',
gridlines: {
count: 0
},
textStyle: {
color: '#aaaaaa'
}
},
height: 400,
legend: {
textStyle: {
color: '#aaaaaa'
}
},
vAxis: {
textStyle: {
color: '#aaaaaa'
}
}
};
chart.draw(data, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
Quick addition to existing answer:
$('.transactionValuationChart text').each(function(){
if( $(this).attr('text-anchor') == 'middle' ){
$(this).attr('y', parseFloat($(this).attr('y')) + 20 );
}else{
$(this).attr('x', parseFloat($(this).attr('x')) - 20 );
console.log("left");
}
});
This is a jQuery example which adds 20px of spacing to both x & y axis

Google Stepped Area Chart with custom annotation

Thanks to White Hat in this post ,I was able to make a custom annotation for the area chart. Somehow it doesn't work the stepped area chart.
The chart draws at first everything correctly but then sets the annotation in the stepped area chart back. With help of the MutationObserver, the settings should be overridden when the chart is drawn but this applies just for the area chart.
How can I solve this ?
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data1 = new google.visualization.DataTable();
data1.addColumn('number', 'x');
data1.addColumn('number', 'green');
data1.addRows([
[0.005, 3],
[0.006, 6],
[0.007, 5],
[0.008, 8],
[0.009, 2],
[0.010, 5],
[0.011, 5],
[0.012, 4],
[0.013, 8]
]);
var data2 = new google.visualization.DataTable();
data2.addColumn('number', 'x');
data2.addColumn('number', 'red');
data2.addRows([
[0.016, 5],
[0.017, 1],
[0.018, 3],
[0.019, 9],
[0.020, 4],
[0.021, 5],
[0.022, 7],
[0.023, 7],
[0.024, 3]
]);
var joinedData = google.visualization.data.join(data1, data2, 'full',
[[0, 0]], [1], [1]);
var options = {
annotations: {
stem: {
length: 10
}
},
title: 'Playground',
colors: ['#007f01', '#fe0002'],
interpolateNulls: true,
hAxis: {
titleTextStyle: {
color: '#333'
},
direction: 1,
format: 'decimal'
},
vAxis: {
direction: 1
},
orientation: 'horizontal',
// customize colum
series: {
0: {type: "steppedArea"},
1: {type: "area"},
},
// legend: {position : 'left'},
animation: {
startup: true,
duration: 1000,
easing: 'out',
}
};
var view = new google.visualization.DataView(joinedData);
view.setColumns([0,
1,
{
calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation"
},
2,
{
calc: "stringify",
sourceColumn: 2,
type: "string",
role: "annotation"
}
]);
var container = document.getElementById('chart_div');
var chart = new google.visualization.ComboChart(container);
var observer = new MutationObserver(moveAnnotations);
observer.observe(container, {
childList: true,
subtree: true
});
function moveAnnotations() {
var chartLayout = chart.getChartLayoutInterface();
var chartBounds = chartLayout.getChartAreaBoundingBox();
var labels = container.getElementsByTagName('text');
var labelSize = 0;
Array.prototype.forEach.call(labels, function(label) {
if (label.getAttribute('text-anchor') === 'middle') {
if (options.colors.indexOf(label.getAttribute('fill')) > -1) {
labelSize = (parseFloat(label.getAttribute('font-size')) / 2);
label.setAttribute('y', chartBounds.top + labelSize);
}
}
});
var stems = container.getElementsByTagName('rect');
Array.prototype.forEach.call(stems, function(stem) {
if ((parseInt(stem.getAttribute('height')) === options.annotations.stem.length) && (stem.getAttribute('fill') === '#999999')) {
var height = parseFloat(stem.getAttribute('y')) - chartBounds.top;
stem.setAttribute('height', height);
stem.setAttribute('y', chartBounds.top + labelSize);
}
});
}
chart.draw(view.toDataTable(), options);
});
</script>
</head>
<body>
<div id="chart_div" style="width: 100%; height: 500px;"></div>
</body>
</html>
the default annotation settings for stepped area charts differ from normal area charts
for stepped, the annotations appear inside the area, which changes the color to white,
which is not a color used to find the labels and move them
an easy fix is to specify that the annotation always be outside the area...
annotations: {
alwaysOutside: true,
...
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data1 = new google.visualization.DataTable();
data1.addColumn('number', 'x');
data1.addColumn('number', 'green');
data1.addRows([
[0.005, 3],
[0.006, 6],
[0.007, 5],
[0.008, 8],
[0.009, 2],
[0.010, 5],
[0.011, 5],
[0.012, 4],
[0.013, 8]
]);
var data2 = new google.visualization.DataTable();
data2.addColumn('number', 'x');
data2.addColumn('number', 'red');
data2.addRows([
[0.016, 5],
[0.017, 1],
[0.018, 3],
[0.019, 9],
[0.020, 4],
[0.021, 5],
[0.022, 7],
[0.023, 7],
[0.024, 3]
]);
var joinedData = google.visualization.data.join(data1, data2, 'full',
[[0, 0]], [1], [1]);
var options = {
annotations: {
alwaysOutside: true,
stem: {
length: 10
}
},
title: 'Playground',
colors: ['#007f01', '#fe0002'],
interpolateNulls: true,
hAxis: {
titleTextStyle: {
color: '#333'
},
direction: 1,
format: 'decimal'
},
vAxis: {
direction: 1
},
orientation: 'horizontal',
// customize colum
series: {
0: {type: "steppedArea"},
1: {type: "area"},
},
// legend: {position : 'left'},
animation: {
startup: true,
duration: 1000,
easing: 'out',
}
};
var view = new google.visualization.DataView(joinedData);
view.setColumns([0,
1,
{
calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation"
},
2,
{
calc: "stringify",
sourceColumn: 2,
type: "string",
role: "annotation"
}
]);
var container = document.getElementById('chart_div');
var chart = new google.visualization.ComboChart(container);
var observer = new MutationObserver(moveAnnotations);
observer.observe(container, {
childList: true,
subtree: true
});
function moveAnnotations() {
var chartLayout = chart.getChartLayoutInterface();
var chartBounds = chartLayout.getChartAreaBoundingBox();
var labels = container.getElementsByTagName('text');
var labelSize = 0;
Array.prototype.forEach.call(labels, function(label) {
if (label.getAttribute('text-anchor') === 'middle') {
if (options.colors.indexOf(label.getAttribute('fill')) > -1) {
labelSize = (parseFloat(label.getAttribute('font-size')) / 2);
label.setAttribute('y', chartBounds.top + labelSize);
}
}
});
var stems = container.getElementsByTagName('rect');
Array.prototype.forEach.call(stems, function(stem) {
if ((parseInt(stem.getAttribute('height')) === options.annotations.stem.length) && (stem.getAttribute('fill') === '#999999')) {
var height = parseFloat(stem.getAttribute('y')) - chartBounds.top;
stem.setAttribute('height', height);
stem.setAttribute('y', chartBounds.top + labelSize);
}
});
}
chart.draw(view.toDataTable(), options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

Google Charts: vAxis on the right for vertical oriented charts

I have difficulties in getting the vertical axis on the right side, I read this post but it was 5 years ago and didn't work out for the vertical graph orientation. I was also not able to display vertical axis on the left and right side of the chart.
I hope there is a better way than making a dummy column ....
<html>
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {
'packages': ['corechart']
});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data1 = new google.visualization.DataTable();
data1.addColumn('number', 'x');
data1.addColumn('number', 'y1');
data1.addRows([
[0.005, 3],
[0.006, 6],
[0.007, 5],
[0.008, 8],
[0.009, 2],
[0.010, 5],
[0.011, 5],
[0.012, 4],
[0.013, 8]
]);
var data2 = new google.visualization.DataTable();
data2.addColumn('number', 'x');
data2.addColumn('number', 'y2');
data2.addRows([
[0.016, 5],
[0.017, 1],
[0.018, 3],
[0.019, 9],
[0.020, 4],
[0.021, 5],
[0.022, 7],
[0.023, 7],
[0.024, 3]
]);
var joinedData = google.visualization.data.join(data1, data2, 'full',
[[0, 0]], [1], [1]);
var options = {
title: 'playground',
colors: ['#FA7F01', '#AEAAA2'],
interpolateNulls: true,
hAxis: {
title: 'x',
titleTextStyle: {
color: '#333'
},
direction: 1,
format: 'decimal'
},
vAxis: {
title: 'y',
direction: 1
},
orientation: 'vertical',
annotations: {
alwaysOutside: true,
stem: {
color: '#ff00ff',
length: 10
},
},
// customize colum
series: {
0: {type: "steppedArea"},
1: {type: "steppedArea"},
},
};
var view = new google.visualization.DataView(joinedData);
view.setColumns([0,
1,
{
calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation"
},
2,
{
calc: "stringify",
sourceColumn: 2,
type: "string",
role: "annotation"
}
]);
var container = document.getElementById('chart_div');
var chart = new google.visualization.ComboChart(container);
chart.draw(view.toDataTable(), options);
}
</script>
</head>
<body>
<div id="chart_div" style="width: 100%; height: 500px;"></div>
<div id="visualization"></div>
</body>
</html>
normally, you could use targetAxisIndex to move the axis to the right side,
but this doesn't appear to work with --> orientation: 'vertical'
although not ideal, you could manually move the axis on the chart's 'ready' event...
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data1 = new google.visualization.DataTable();
data1.addColumn('number', 'x');
data1.addColumn('number', 'y1');
data1.addRows([
[0.005, 3],
[0.006, 6],
[0.007, 5],
[0.008, 8],
[0.009, 2],
[0.010, 5],
[0.011, 5],
[0.012, 4],
[0.013, 8]
]);
var data2 = new google.visualization.DataTable();
data2.addColumn('number', 'x');
data2.addColumn('number', 'y2');
data2.addRows([
[0.016, 5],
[0.017, 1],
[0.018, 3],
[0.019, 9],
[0.020, 4],
[0.021, 5],
[0.022, 7],
[0.023, 7],
[0.024, 3]
]);
var joinedData = google.visualization.data.join(data1, data2, 'full',
[[0, 0]], [1], [1]);
var options = {
title: 'playground',
colors: ['#FA7F01', '#AEAAA2'],
interpolateNulls: true,
hAxis: {
title: 'x',
titleTextStyle: {
color: '#333'
},
direction: 1,
format: 'decimal'
},
vAxis: {
title: 'y',
direction: 1
},
orientation: 'vertical',
annotations: {
alwaysOutside: true,
stem: {
color: '#ff00ff',
length: 10
},
},
// customize colum
series: {
0: {type: "steppedArea"},
1: {type: "steppedArea"},
},
legend: {
alignment: 'end',
position: 'top'
}
};
var view = new google.visualization.DataView(joinedData);
view.setColumns([0,
1,
{
calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation"
},
2,
{
calc: "stringify",
sourceColumn: 2,
type: "string",
role: "annotation"
}
]);
var container = document.getElementById('chart_div');
var chart = new google.visualization.ComboChart(container);
google.visualization.events.addListener(chart, 'ready', moveAxis);
function moveAxis() {
var chartLayout = chart.getChartLayoutInterface();
var chartBounds = chartLayout.getChartAreaBoundingBox();
var labelGap;
var labelIndex = -1;
var labelWidth;
var xCoord;
var yTitle;
// move axis labels
var labels = container.getElementsByTagName('text');
Array.prototype.forEach.call(labels, function(label) {
labelWidth = 0;
if (label.getAttribute('text-anchor') === 'end') {
labelIndex++;
labelWidth = chartLayout.getBoundingBox('vAxis#0#label#' + labelIndex).width;
labelGap = chartBounds.left - parseFloat(label.getAttribute('x'));
xCoord = chartBounds.left + chartBounds.width + labelWidth + labelGap;
label.setAttribute('x', xCoord);
} else if ((label.getAttribute('text-anchor') === 'middle') && (label.hasAttribute('transform'))) {
yTitle = label;
}
});
yTitle.setAttribute('y', xCoord + 92);
// swap axis baselines
var lines = container.getElementsByTagName('rect');
Array.prototype.forEach.call(lines, function(line) {
if ((parseFloat(line.getAttribute('x')) === (chartBounds.left + chartBounds.width - 1)) && (parseFloat(line.getAttribute('width')) === 1)) {
line.setAttribute('x', chartBounds.left);
} else if ((parseInt(line.getAttribute('x')) === chartBounds.left) && (parseInt(line.getAttribute('width')) === 1) && (line.getAttribute('fill') === '#333333')) {
line.setAttribute('x', chartBounds.left + chartBounds.width - 1);
}
});
}
chart.draw(view.toDataTable(), options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
Try adding this to your options:
series: {
0: { targetAxisIndex: 1, },
1: { targetAxisIndex: 1, },
}
What this means is that both your series should use the right-side axis.