Reputation: 5709
I'm using React at work and we've been thinking about trying to draw boxes around points in a Scatterplot using built in methods. Now, we can use the built-in Vertical Intervals but is there a way to also add an interval that goes horizontally?
I can't seem to find anything about that anywhere. If it isn't possible can we achieve the same in some other way?
Upvotes: 0
Views: 232
Reputation: 61275
there are no built-in options to draw a box around a set of points.
however, there are chart methods available to find the coordinates of the points drawn.
first, use chart method --> getChartLayoutInterface()
which returns the layout interface.
the layout interface has a method for --> getBoundingBox(id)
where id
is the point you want to investigate.
the id
should be in the form --> point#0#0
where the first 0
is the series, and the second is the row.
e.g.
var chartLayout = chart.getChartLayoutInterface();
var bounds = chartLayout.getBoundingBox('point#0#0');
bounds
will be an object with properties for --> top, left, height, & width
once we have the coordinates, we can draw our own box,
on the chart's 'ready'
event...
see following working snippet,
function drawBox
takes an array of points the box should be drawn around.
drawBox([
{series: 0, row: 1},
{series: 0, row: 3},
{series: 0, row: 4}
]);
google.charts.load('current', {
packages:['controls', 'corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
['x', 'y'],
[8, 12],
[4, 5.5],
[11, 14],
[4, 5],
[3, 3.5],
[6.5, 7]
]);
var chartWrapper = new google.visualization.ChartWrapper({
chartType: 'ScatterChart',
containerId: 'chart_div',
dataTable: data,
options: {
chartArea: {
height: '100%',
width: '100%',
top: 36,
left: 36,
right: 18,
bottom: 36
},
height: '100%',
legend: {
position: 'top'
},
pointSize: 8,
width: '100%',
}
});
google.visualization.events.addListener(chartWrapper, 'ready', function () {
google.visualization.events.addListener(chartWrapper.getChart(), 'click', function (gglClick) {
console.log(JSON.stringify(gglClick));
});
drawBox([
{series: 0, row: 1},
{series: 0, row: 3},
{series: 0, row: 4}
]);
});
function drawBox(points) {
var chart = chartWrapper.getChart();
var chartLayout = chart.getChartLayoutInterface();
var container = document.getElementById(chartWrapper.getContainerId())
var xCoord = {min: null, max: null};
var yCoord = {min: null, max: null};
points.forEach(function (point) {
var bounds = chartLayout.getBoundingBox('point#' + point.series + '#' + point.row);
xCoord.min = xCoord.min || bounds.left;
xCoord.min = Math.min(bounds.left, xCoord.min);
xCoord.max = xCoord.max || bounds.left;
xCoord.max = Math.max(bounds.left, xCoord.max);
yCoord.min = yCoord.min || bounds.top;
yCoord.min = Math.min(bounds.top, yCoord.min);
yCoord.max = yCoord.max || bounds.top;
yCoord.max = Math.max(bounds.top, yCoord.max);
});
xCoord.min = xCoord.min - chartWrapper.getOption('pointSize');
xCoord.max = xCoord.max + (chartWrapper.getOption('pointSize') * 2);
yCoord.min = yCoord.min - chartWrapper.getOption('pointSize');
yCoord.max = yCoord.max + (chartWrapper.getOption('pointSize') * 2);
var svg = container.getElementsByTagName('svg')[0];
var svgNS = svg.namespaceURI;
var circle = container.getElementsByTagName('circle')[1];
var box = document.createElementNS(svgNS, 'polygon');
box.setAttribute('fill', 'transparent');
box.setAttribute('stroke', '#000000');
box.setAttribute('stroke-width', '2');
box.setAttribute('points', xCoord.min + ',' + yCoord.min + ' ' + xCoord.max + ',' + yCoord.min + ' ' + xCoord.max + ',' + yCoord.max + ' ' + xCoord.min + ',' + yCoord.max);
circle.parentNode.appendChild(box);
}
window.addEventListener('resize', function () {
chartWrapper.draw();
});
chartWrapper.draw();
});
html, body {
height: 100%;
margin: 0px 0px 0px 0px;
overflow: hidden;
padding: 0px 0px 0px 0px;
}
.chart {
height: 100%;
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div class="chart" id="chart_div"></div>
Upvotes: 1