Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect zoom event for a Google Line chart?

Is it possible to detect a zoom/rangechange event with Google Line Chart api? If I use a annotated timeline i can do it, but not with a LineChart.

As you see i´m trying to synchronise two graphs. It works OK, but when i zoom in the upper graph, i want to zoom in on the lower graph aswell.

Im using the following code:

  google.charts.load('current', {
  callback: function () {

    var chart1;
    var chart2;

    var data1 = new google.visualization.DataTable();
    var data2 = new google.visualization.DataTable();

    var outDiv1 = document.getElementById('mcs-chart-event');
    var outDiv2 = document.getElementById('snr-chart-event');

    var options1 = {title:'Wot',
      height:300,
      displayAnnotations: false,
      displayZoomButtons: false,
      chartArea: { width:'95%',height:'90%'},
      lineWidth: 1.5,
      legend: { position: 'none' },
      crosshair: {
        trigger: 'both',
        orientation: 'vertical'
      },
      explorer: {
          actions: ['dragToZoom', 'rightClickToReset'],
          axis: 'horizontal',
          keepInBounds: true,
          maxZoomIn: 10.0
      },
    };

    var options2 = {
      displayZoomButtons: false,
      displayRangeSelector: false,
      title:'rsi typ',
      chartArea: { width:'95%',height:'90%'},
      height:100,
      lineWidth: 1.5,
      colors: ['red'],
      legend: { position: 'none' },
      crosshair: {
        trigger: 'both',
        orientation: 'vertical'
      },
      explorer: {
          actions: ['dragToZoom', 'rightClickToReset'],
          axis: 'horizontal',
          keepInBounds: true,
          maxZoomIn: 10.0
      },
    };


    drawChartOne(data1);
    drawChartTwo(data2);

    google.visualization.events.addListener(chart1, 'onmouseover', function(selection) {
        chart1.setSelection(selection);
         chart2.setSelection([{ row: selection.row, column: null }]);
     });
		
    //Only works when using AnnotatedTimeLine...
     google.visualization.events.addListener(chart1, 'rangechange', function(data) {
     //Only works when using AnnotatedTimeLine...
          chart2.setVisibleChartRange(data.start,data.end);
      });

     google.visualization.events.addListener(chart2, 'onmouseover', function(selection) {
          chart2.setSelection(selection);
          chart1.setSelection([{ row: selection.row, column: null }]);
      });

    chart1.draw(data1, options1);
    chart2.draw(data2, options2);

    function drawChartOne(data) {
      data.addColumn('date', 'Date');
      data.addColumn('number', 'Sessions');
      data.addColumn({type: 'string', role: 'style'});
      data.addColumn({type:'string', role:'annotation'});

      var sessions = [786, 450, 866, 814, 192, 466, 984, 780, 922, 458, 786, 758, 701, 831, 901, 557, 114, 393, 689, 658, 103, 837, 164, 727, 593, 193, 945, 583, 948, 338];
      var start = new Date(1458345600 * 1000);
      var date;

      var dates = [];

      for(var i = 0; i < sessions.length; i++) {
        var newDate = start.setDate(start.getDate() + 1);
        if(i == 10){
            data.addRow([new Date(newDate), sessions[i],'point { size: 6; shape-type: circle; fill-color: green;','Buy']);

        }else{
          data.addRow([new Date(newDate), sessions[i],null,null]);
        }

      }

      chart1 = new google.visualization.LineChart(document.getElementById('mcs-chart'));
    }

    function drawChartTwo(data) {
      data.addColumn('date', 'Date');
      data.addColumn('number', 'Other Sessions');

      var rsi = [100, 450, 200, 333, 192, 466, 984, 77, 922, 458, 200, 758, 701, 831, 901, 557, 114, 393, 500, 658, 103, 837, 300, 727, 593, 193, 945, 583, 948, 338];

      var start = new Date(1458345600 * 1000);
      var date;

      for(var i = 0; i < rsi.length; i++) {
        var newDate = start.setDate(start.getDate() + 1);
        data.addRow([new Date(newDate), rsi[i]]);
      }

      chart2 = new google.visualization.LineChart(document.getElementById('snr-chart'));
    }
  },
  packages: ['corechart','annotatedtimeline']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="mcs-chart"></div>
<div id="snr-chart"></div>
<div id="mcs-chart-event"></div>
<div id="snr-chart-event"></div>
like image 748
joxxe Avatar asked Feb 14 '17 20:02

joxxe


1 Answers

first, use a MutationObserver to know when interactivity, including zoom, has occurred on chart1

    // sync chart2
    var observer = new MutationObserver(function () {
      setRange(getCoords());
    });

    // start observing on 'ready'
    google.visualization.events.addListener(chart1, 'ready', function() {
      observer.observe(container1, {
        childList: true,
        subtree: true
      });
    });

next, grab the coordinates of each axis from chart1, and set the viewWindow on chart2

the coordinates are obtained using the following methods...

getChartLayoutInterface() --> Returns an object containing information about the onscreen placement of the chart and its elements.

getChartAreaBoundingBox() --> Returns an object containing the left, top, width, and height of the chart content (i.e., excluding labels and legend)

see functions for getCoords and setRange below...


see following working snippet, run once, then choose "Full page" to get the "full effect"...

google.charts.load('current', {
  callback: function () {
    var chart1;
    var chart2;

    var data1 = new google.visualization.DataTable();
    var data2 = new google.visualization.DataTable();

    var container1 = document.getElementById('mcs-chart');
    var container2 = document.getElementById('snr-chart');

    var outDiv1 = document.getElementById('mcs-chart-event');
    var outDiv2 = document.getElementById('snr-chart-event');

    var options1 = {title:'Wot',
      height:300,
      displayAnnotations: false,
      displayZoomButtons: false,
      chartArea: { width:'95%',height:'90%'},
      lineWidth: 1.5,
      legend: { position: 'none' },
      crosshair: {
        trigger: 'both',
        orientation: 'vertical'
      },
      explorer: {
          actions: ['dragToZoom', 'rightClickToReset'],
          axis: 'horizontal',
          keepInBounds: true,
          maxZoomIn: 10.0
      },
    };

    var options2 = {
      displayZoomButtons: false,
      displayRangeSelector: false,
      title:'rsi typ',
      chartArea: { width:'95%',height:'90%'},
      height:100,
      lineWidth: 1.5,
      colors: ['red'],
      legend: { position: 'none' },
      crosshair: {
        trigger: 'both',
        orientation: 'vertical'
      },
      explorer: {
          actions: ['dragToZoom', 'rightClickToReset'],
          axis: 'horizontal',
          keepInBounds: true,
          maxZoomIn: 10.0
      },
    };

    drawChartOne(data1);
    drawChartTwo(data2);

    google.visualization.events.addListener(chart1, 'onmouseover', function(selection) {
      chart1.setSelection(selection);
      chart2.setSelection([{ row: selection.row, column: null }]);
    });

    // sync chart2
    var observer = new MutationObserver(function () {
      setRange(getCoords());
    });

    // start observing on 'ready'
    google.visualization.events.addListener(chart1, 'ready', function() {
      observer.observe(container1, {
        childList: true,
        subtree: true
      });
    });

    google.visualization.events.addListener(chart2, 'onmouseover', function(selection) {
      chart2.setSelection(selection);
      chart1.setSelection([{ row: selection.row, column: null }]);
    });

    drawCharts();
    window.addEventListener('resize', drawCharts, false);
    function drawCharts() {
      chart1.draw(data1, options1);
      chart2.draw(data2, options2);
    }

    function drawChartOne(data) {
      data.addColumn('date', 'Date');
      data.addColumn('number', 'Sessions');
      data.addColumn({type: 'string', role: 'style'});
      data.addColumn({type:'string', role:'annotation'});

      var sessions = [786, 450, 866, 814, 192, 466, 984, 780, 922, 458, 786, 758, 701, 831, 901, 557, 114, 393, 689, 658, 103, 837, 164, 727, 593, 193, 945, 583, 948, 338];
      var start = new Date(1458345600 * 1000);
      var date;

      var dates = [];

      for(var i = 0; i < sessions.length; i++) {
        var newDate = start.setDate(start.getDate() + 1);
        if(i == 10){
            data.addRow([new Date(newDate), sessions[i],'point { size: 6; shape-type: circle; fill-color: green;','Buy']);

        }else{
          data.addRow([new Date(newDate), sessions[i],null,null]);
        }

      }

      chart1 = new google.visualization.LineChart(container1);
    }

    function drawChartTwo(data) {
      data.addColumn('date', 'Date');
      data.addColumn('number', 'Other Sessions');

      var rsi = [100, 450, 200, 333, 192, 466, 984, 77, 922, 458, 200, 758, 701, 831, 901, 557, 114, 393, 500, 658, 103, 837, 300, 727, 593, 193, 945, 583, 948, 338];

      var start = new Date(1458345600 * 1000);
      var date;

      for(var i = 0; i < rsi.length; i++) {
        var newDate = start.setDate(start.getDate() + 1);
        data.addRow([new Date(newDate), rsi[i]]);
      }

      chart2 = new google.visualization.LineChart(container2);
    }

    // get axis coordinates from chart1
    function getCoords() {
      var chartLayout = chart1.getChartLayoutInterface();
      var chartBounds = chartLayout.getChartAreaBoundingBox();
      return {
        x: {
          min: chartLayout.getHAxisValue(chartBounds.left),
          max: chartLayout.getHAxisValue(chartBounds.width + chartBounds.left)
        },
        y: {
          min: chartLayout.getVAxisValue(chartBounds.top),
          max: chartLayout.getVAxisValue(chartBounds.height + chartBounds.top)
        }
      };
    }

    // set axis coordinates on chart2
    function setRange(coords) {
      options2.hAxis = {};
      options2.vAxis = {};
      options2.hAxis.viewWindow = {};
      options2.vAxis.viewWindow = {};
      if (coords) {
        options2.hAxis.viewWindow.min = coords.x.min;
        options2.hAxis.viewWindow.max = coords.x.max;
        options2.vAxis.viewWindow.min = coords.y.min;
        options2.vAxis.viewWindow.max = coords.y.max;
      }
      chart2.draw(data2, options2);
    }
  },
  packages: ['corechart','annotatedtimeline']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="mcs-chart"></div>
<div id="snr-chart"></div>
<div id="mcs-chart-event"></div>
<div id="snr-chart-event"></div>
like image 51
WhiteHat Avatar answered Oct 16 '22 16:10

WhiteHat