Vertical lines on hover in google charts
Asked Answered
B

4

5

I am working with google line charts and angularjs directive in my project, I am searching how to get vertical lines on hover like Google Trends instead put a fixed lines, but I can't find how to do this.

This is that I want trying to do:

enter image description here

I just got hide vertical lines but not show on mouse hover, this is my options for angular-google-chart directive

options: {
  vAxis: {
    title: 'My title',
    gridlines: {
      count: 10
    }
  },
  hAxis: {
    title: 'title hAxis',
    gridlines: {
      color: 'transparent'
    }
  }
}
Bastien answered 20/2, 2017 at 17:18 Comment(0)
A
3

there are no standard config options for this, but you could add your own line on hover...

see following working snippet for an example...

google.charts.load('current', {
  callback: drawChart,
  packages: ['corechart']
});

function drawChart() {
  var dataTable = new google.visualization.DataTable({
    cols: [
      {id: 'x', label: 'Date', type: 'date'},
      {id: 'y', label: 'Fn', type: 'number'}
    ]
  });

  var formatDate = new google.visualization.DateFormat({
    pattern: 'MMM d, yyyy'
  });

  var oneDay = (1000 * 60 * 60 * 24);
  var startDate = new Date(2016, 1, 21);
  var endDate = new Date();
  var ticksAxisH = [];
  for (var i = startDate.getTime(); i < endDate.getTime(); i = i + oneDay) {
    // x = date
    var rowDate = new Date(i);
    var xValue = {
      v: rowDate,
      f: formatDate.formatValue(rowDate)
    };

    // y = 2x + 8
    var yValue = (2 * ((i - startDate.getTime()) / oneDay) + 8);

    // add data row
    dataTable.addRow([
      xValue,
      yValue
    ]);

    // add tick every 90 days
    if ((((i - startDate.getTime()) / oneDay) % 90) === 0) {
      ticksAxisH.push(xValue);
    }
  }

  var container = document.getElementById('chart_div');
  var chart = new google.visualization.ChartWrapper({
    chartType: 'LineChart',
    dataTable: dataTable,
    options: {
      hAxis: {
        gridlines: {
          color: 'transparent'
        },
        ticks: ticksAxisH,
        title: 'title hAxis'
      },
      tooltip: {
        isHtml: true
      },
      vAxis: {
        gridlines: {
          count: 10
        },
        title: 'My title'
      }
    }
  });

  // add hover line
  google.visualization.events.addOneTimeListener(chart, 'ready', function () {
    var svgParent = container.getElementsByTagName('svg')[0];
    var layout = chart.getChart().getChartLayoutInterface();
    var lineHeight = layout.getBoundingBox('chartarea').height - 18;
    var lineTop = layout.getBoundingBox('chartarea').top;

    var hoverLine = container.getElementsByTagName('rect')[0].cloneNode(true);
    hoverLine.setAttribute('y', lineTop);
    hoverLine.setAttribute('height', lineHeight);
    hoverLine.setAttribute('width', '1');
    hoverLine.setAttribute('stroke', 'none');
    hoverLine.setAttribute('stroke-width', '0');
    hoverLine.setAttribute('fill', '#cccccc');

    google.visualization.events.addListener(chart.getChart(), 'onmouseover', function (p) {
      if (p.row !== null) {
        var xPos = layout.getXLocation(dataTable.getValue(p.row, 0));
        svgParent.appendChild(hoverLine);
        hoverLine.setAttribute('x', xPos);
      }
    });

    google.visualization.events.addListener(chart.getChart(), 'onmouseout', function (p) {
      if (p.row !== null) {
        svgParent.removeChild(hoverLine);
      }
    });
  });

  chart.draw(container);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
Aerator answered 21/2, 2017 at 14:20 Comment(1)
I get error "message": "Script error.", "filename": "", "lineno": 0, "colno": 0 when I hover over legendChampionship
V
4

Crosshairs are available now via standard config options:

https://developers.google.com/chart/interactive/docs/crosshairs

Example config for your case:

crosshair: {orientation: 'vertical', trigger: 'focus'}
Vendee answered 19/8, 2019 at 18:50 Comment(0)
A
3

there are no standard config options for this, but you could add your own line on hover...

see following working snippet for an example...

google.charts.load('current', {
  callback: drawChart,
  packages: ['corechart']
});

function drawChart() {
  var dataTable = new google.visualization.DataTable({
    cols: [
      {id: 'x', label: 'Date', type: 'date'},
      {id: 'y', label: 'Fn', type: 'number'}
    ]
  });

  var formatDate = new google.visualization.DateFormat({
    pattern: 'MMM d, yyyy'
  });

  var oneDay = (1000 * 60 * 60 * 24);
  var startDate = new Date(2016, 1, 21);
  var endDate = new Date();
  var ticksAxisH = [];
  for (var i = startDate.getTime(); i < endDate.getTime(); i = i + oneDay) {
    // x = date
    var rowDate = new Date(i);
    var xValue = {
      v: rowDate,
      f: formatDate.formatValue(rowDate)
    };

    // y = 2x + 8
    var yValue = (2 * ((i - startDate.getTime()) / oneDay) + 8);

    // add data row
    dataTable.addRow([
      xValue,
      yValue
    ]);

    // add tick every 90 days
    if ((((i - startDate.getTime()) / oneDay) % 90) === 0) {
      ticksAxisH.push(xValue);
    }
  }

  var container = document.getElementById('chart_div');
  var chart = new google.visualization.ChartWrapper({
    chartType: 'LineChart',
    dataTable: dataTable,
    options: {
      hAxis: {
        gridlines: {
          color: 'transparent'
        },
        ticks: ticksAxisH,
        title: 'title hAxis'
      },
      tooltip: {
        isHtml: true
      },
      vAxis: {
        gridlines: {
          count: 10
        },
        title: 'My title'
      }
    }
  });

  // add hover line
  google.visualization.events.addOneTimeListener(chart, 'ready', function () {
    var svgParent = container.getElementsByTagName('svg')[0];
    var layout = chart.getChart().getChartLayoutInterface();
    var lineHeight = layout.getBoundingBox('chartarea').height - 18;
    var lineTop = layout.getBoundingBox('chartarea').top;

    var hoverLine = container.getElementsByTagName('rect')[0].cloneNode(true);
    hoverLine.setAttribute('y', lineTop);
    hoverLine.setAttribute('height', lineHeight);
    hoverLine.setAttribute('width', '1');
    hoverLine.setAttribute('stroke', 'none');
    hoverLine.setAttribute('stroke-width', '0');
    hoverLine.setAttribute('fill', '#cccccc');

    google.visualization.events.addListener(chart.getChart(), 'onmouseover', function (p) {
      if (p.row !== null) {
        var xPos = layout.getXLocation(dataTable.getValue(p.row, 0));
        svgParent.appendChild(hoverLine);
        hoverLine.setAttribute('x', xPos);
      }
    });

    google.visualization.events.addListener(chart.getChart(), 'onmouseout', function (p) {
      if (p.row !== null) {
        svgParent.removeChild(hoverLine);
      }
    });
  });

  chart.draw(container);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
Aerator answered 21/2, 2017 at 14:20 Comment(1)
I get error "message": "Script error.", "filename": "", "lineno": 0, "colno": 0 when I hover over legendChampionship
M
3

add

focusTarget: 'category',
crosshair: {orientation: 'vertical', trigger: 'focus'},

to your options.

example:

google.charts.load('current', {packages: ['corechart', 'line']});
google.charts.setOnLoadCallback(drawLogScales);

function drawLogScales() {
      var data = new google.visualization.DataTable();
      data.addColumn('number', 'X');
      data.addColumn('number', 'rate');
      

      data.addRows([[25,5.240266007932762],[26,5.253756507319332],[27,5.22029650790401],[28,5.268704059004204],[29,5.233683845050076],[30,5.289605815622391],[31,5.232041091123958],[1,5.2301254401862955],[2,5.250722035402405],[3,5.283736492427697],[4,5.296890906826341],[5,5.355039204322343],[6,5.346735747035125],[7,5.326231782387644],[8,5.3273666240507165],[9,5.328501949410373],[10,5.291005414482904],[11,5.317451861825049],[12,5.3344712035425745],[13,5.318865815686569],[14,5.3273666240507165],[15,5.327650410031998],
[16,5.33532534905194],[17,5.294647171789238],[18,5.243288403010766],[19,5.2449386384155785],[20,5.265097477347184],
[21,5.291005414482904],[22,5.290165399493866],[23,5.243013533000918],[24,5.177591381675723],[25,5.136106760580972],
[26,5.118754990317601],[27,5.132943184294443],[28,5.093984040401572],[29,5.092946441953961],[1,5.096580274206888]]);

     var view = new google.visualization.DataView(data);
     view.setColumns([{ sourceColumn: 0, type: 'string',
       calc: function(dt, rowIndex) {
         return String(dt.getValue(rowIndex, 0));
       }}, 1]);
     
      var options = {
        focusTarget: 'category',
        crosshair: {orientation: 'vertical', trigger: 'focus'},
        hAxis: {
          title: 'day',
          logScale: false
          
        },
        vAxis: {
          title: 'rates',
          logScale: false
          
        },
        colors: ['#a52714', '#097138']
      };
        
      var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
      chart.draw(view, options);
    }
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
  <div id="chart_div"></div>

lines 22,23

Machuca answered 19/8, 2021 at 21:40 Comment(0)
B
0

Thanks to @WhiteHat in his previous answer, I have adjusted his code to use it with angular-google-charts in an angular 1.5 component, this is my approach:

Angular-google-charts have some directives to attach custom events like mouseover, mouseout, ready etc, Example:

 <div google-chart agc-on-mouseover="$ctrl.onMouseOver(row, column)"
       chart="$ctrl.data" agc-on-ready="$ctrl.onReady(chartWrapper)" agc-on-mouseout="$ctrl.onMouseOut(row, column)>
 </div>

If you can see, I have added agc-on-ready, agc-on-mouseover and agc-on-mouseout this directives allow me to attach my custom functions to these events.

Using @WhiteHat solutions my functions are here:

self.onMouseOver = function (row, column) {
    if (row !== null) {
        var dataTable=self.chartWrapper.getDataTable();
        var xPos = self.layout.getXLocation(dataTable.getValue(row, 0));
        self.svgParent.appendChild(self.hoverLine);
        self.hoverLine.setAttribute('x', xPos);

        // This line is neccesary to move the line under the tooltip     
        self.svgParent.insertBefore(self.hoverLine, self.svgParent.children[4]);
    }
}

self.onMouseOut = function (row, column) {
    if (row !== null) {
        self.svgParent.removeChild(self.hoverLine);
    }
}

self.onReady = function (chartWrapper) {
    // Define vars for draw vertical line on hoverLine  
    self.chartWrapper = chartWrapper;

    // Getting container from chartWrapper.getContainerId()
    var container = angular.element(chartWrapper.getContainerId());
    self.svgParent = container[0].getElementsByTagName('svg')[0];
    self.layout = chartWrapper.getChart().getChartLayoutInterface();
    self.lineHeight = self.layout.getBoundingBox('chartarea').height - 18;
    self.lineTop = self.layout.getBoundingBox('chartarea').top;

    self.hoverLine = container[0].getElementsByTagName('rect')[0].cloneNode(true);
    self.hoverLine.setAttribute('y', self.lineTop);
    self.hoverLine.setAttribute('z', 100);
    self.hoverLine.setAttribute('height', self.lineHeight);
    self.hoverLine.setAttribute('width', '1');
    self.hoverLine.setAttribute('stroke', 'none');
    self.hoverLine.setAttribute('stroke-width', '0');
    self.hoverLine.setAttribute('fill', '#cccccc');

};

I hope you find it useful and your comments to improve this implementation.

Bastien answered 24/2, 2017 at 22:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.