问题
Given the illustration
I was able to create the chart (without the points) using the following code:
<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);
var chart;
function drawStuff() {
var data = new google.visualization.arrayToDataTable([
['Y', 'Series 1','Series 2'],
["Element A", 44,11],
["Element B", 31,11],
["Element C", 12,11],
]);
var options = {
bars: 'horizontal', // Required for Material Bar Charts.
axes: {
x: {
0: { side: 'bottom', label: 'X'} // Top x-axis.
}
}
};
var div = document.getElementById('top_x_div');
var link = document.getElementById('url');
chart = new google.charts.Bar(div);
chart.draw(data, options);
//console.log(chart.getImageURI());
};
</script>
</head>
<body>
<div id="top_x_div" style="width: 900px; height: 500px;"></div>
</body>
</html>
How to insert points on top of bar charts using Google Charts?
回答1:
there were a couple ways I thought of, to accomplish...
- Use a Combo chart
- Add the points manually, on the chart's
'ready'
event
however, neither option can be achieved using a material chart.
google.charts.Bar
first, material charts do not support Combo charts.
and, material charts do not have the methods necessary to add the points manually.
not to mention, there are also several options that material charts do not support.
see --> Tracking Issue for Material Chart Feature Parity #2143
so we must use a classic chart...
google.visualization.BarChart
there is an option we can use to give the classic chart a similar look and feel as material charts...
theme: 'material'
now the solution...
when attempting to use a Combo chart,
the points align to the y-axis, in between the two bars.
there is not an option that will allow the points to align on the bars.
so we must add the points manually, on the chart's 'ready'
event...
there are few chart methods we need...
getChartLayoutInterface()
- Returns an object containing information about the onscreen placement of the chart and its elements.
getBoundingBox(id)
- Returns an object containing the left, top, width, and height of chart element id.
getXLocation(position, optional_axis_index)
- Returns the screen x-coordinate of position relative to the chart's container.
once the chart's 'ready'
event fires, we can get the layout interface using --> getChartLayoutInterface()
the other two methods mentioned above are methods of the layout interface.
we use getBoundingBox(id)
to get the coordinates of the bar, on which the point will be placed.
this will give us the Y coordinate, and the height of the point.
the id of the bar is determined by the data row and series column.
bar#C#R // where C is the series column index, and R is the row index
we are providing the X coordinate,getXLocation
will provide the location on the chart, needed to place the point on the x-axis, at our predetermined location.
// x coordinates of points to add
var points = [
[36, 8],
[28, 8],
[10, 8],
];
// loop data rows and columns
for (var r = 0; r < data.getNumberOfRows(); r++) {
for (var c = 1; c < data.getNumberOfColumns(); c++) {
// calculate position of the point
var barBounds = chartLayout.getBoundingBox('bar#' + (c - 1) + '#' + r);
var xCoord = chartLayout.getXLocation(points[r][c - 1]);
var height = barBounds.height / 4;
var top = barBounds.top + (height * 2);
// create and add the point to the chart
var point = document.createElementNS(svgNS, 'circle');
point.setAttribute('cx', xCoord);
point.setAttribute('cy', top);
point.setAttribute('r', height);
point.setAttribute('stroke', '#ffffff');
point.setAttribute('stroke-width', height);
point.setAttribute('fill', 'transparent');
svg.appendChild(point);
}
}
see following working snippet...
var chart;
google.charts.load('current', {
packages: ['corechart']
}).then(function drawStuff() {
var data = new google.visualization.arrayToDataTable([
['Y', 'Series 1', 'Series 2'],
['Element A', 44, 11],
['Element B', 31, 11],
['Element C', 12, 11],
]);
// x coordinates of points to add
var points = [
[36, 8],
[28, 8],
[10, 8],
];
var options = {
chartArea: {
left: 128,
top: 24,
right: 128,
bottom: 72,
height: '100%',
width: '100%'
},
hAxis: {
title: 'X'
},
height: '100%',
theme: 'material',
vAxis: {
title: data.getColumnLabel(0)
},
width: '100%'
};
var div = document.getElementById('top_x_div');
//var link = document.getElementById('url');
chart = new google.visualization.BarChart(div);
google.visualization.events.addListener(chart, 'ready', function () {
// get chart layour interface and svg
var chartLayout = chart.getChartLayoutInterface();
var svg = div.getElementsByTagName('svg')[0];
var svgNS = svg.namespaceURI;
// loop data rows and columns
for (var r = 0; r < data.getNumberOfRows(); r++) {
for (var c = 1; c < data.getNumberOfColumns(); c++) {
// calculate position of the point
var barBounds = chartLayout.getBoundingBox('bar#' + (c - 1) + '#' + r);
var xCoord = chartLayout.getXLocation(points[r][c - 1]);
var height = barBounds.height / 4;
var top = barBounds.top + (height * 2);
// create and add the point to the chart
var point = document.createElementNS(svgNS, 'circle');
point.setAttribute('cx', xCoord);
point.setAttribute('cy', top);
point.setAttribute('r', height);
point.setAttribute('stroke', '#ffffff');
point.setAttribute('stroke-width', height);
point.setAttribute('fill', 'transparent');
svg.appendChild(point);
}
}
});
chart.draw(data, options);
window.addEventListener('resize', function () {
chart.draw(data, options);
});
});
#top_x_div {
height: 400px;
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="top_x_div"></div>
来源:https://stackoverflow.com/questions/61627353/how-to-insert-points-on-top-of-bar-charts-using-google-charts