OmniOwl
OmniOwl

Reputation: 5709

Horizontal Intervals in Google Chart?

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

Answers (1)

WhiteHat
WhiteHat

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

Related Questions