Google Charts Timeline highlight many bars on mous

2019-09-10 11:41发布

问题:

I'm currently working on some data visualization. For the visualization I am using Google Charts Timeline embedded within Dashboard (which implements functionality of zooming on x-axis). Timeline is representing players position in ranking (first, second and third place). What I am trying to achieve is - when i hover mouse on player's entry I would like to highlight his/hers other entries in timeline. Using Google's example with President, VP and Secretary of State - when I hover over Thomas Jefferson bar when he was Secretary of State I want his time as VP and as President highlighted on the chart. I am providing jsfiddle as a reference - https://jsfiddle.net/21aor2ab/

I had an idea about using 'onmouseover' event, but I had problem with setting this event properly within dashboard - simply using google.visualization.events.addListener(dashChart, 'onmouseover', function(){something over here}); won't work for some reason...

I would be happy if anyone could suggest me a solution, or at least point me in the right direction.

回答1:

when assigning chart events to chart wrappers...

you have to wait for the 'ready' event on the wrapper,
then listen for the event on wrapper.getChart()

see following example...

as for highlighting multiple entries,
here I try to trigger the onmouseover on the other rows,
the event is fired but the rows aren't highlighted

I thought about using setSelection instead, but for a Timeline chart...

only one entity can be selected at any given moment

only other option would be to modify the svg directly
but not recommended
you would need to log all the colors, including the highlight colors,
or try to provide your own

this example highlights all the Thomas Jefferson rows

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

    var dashboard = new google.visualization.Dashboard(document.getElementById('dashboard'));

    var dashControl = new google.visualization.ControlWrapper({
      'controlType': 'ChartRangeFilter',
      'containerId': 'control',
      'options': {
        'filterColumnIndex': 3,
        'ui': {
          'chartType': 'ScatterChart',
          'chartOptions': {
            'height': 70,
            'chartArea': {
              width: '80%',
              height: '80%'
            },
            'hAxis': {
              'baselineColor': 'none'
            }
          },
          'chartView': {
            'columns': [3, 4]
          },
          minRangeSize: 12*60*60*1000
        }
      }
    });

    var dashChart = new google.visualization.ChartWrapper({
      'chartType': 'Timeline',
      'containerId': 'chart',
      'options': {
        'chartArea': {
          width: '80%',
          height: '80%'
        },
        hAxis: {
          format: 'dd.MM HH:mm'
        }
      },
      'view': {
        'columns': [0, 1, 2, 3, 4]
      }
    });

    var dataTable = new google.visualization.DataTable();

    dataTable.addColumn({ type: 'string', id: 'Role' });
    dataTable.addColumn({ type: 'string', id: 'Name' });
    dataTable.addColumn({ type: "string", id: "", "role": "tooltip", "p" : { "role" : "tooltip" ,'html': true} });
    dataTable.addColumn({ type: 'date', id: 'Start' });
    dataTable.addColumn({ type: 'date', id: 'End' });

    dataTable.addRows([
      [ 'President', 'George Washington', 'some tooltip content', new Date(1789, 3, 30), new Date(1797, 2, 4) ],
      [ 'President', 'John Adams', 'some tooltip content', new Date(1797, 2, 4), new Date(1801, 2, 4) ],
      [ 'President', 'Thomas Jefferson', 'some tooltip content', new Date(1801, 2, 4), new Date(1809, 2, 4) ],
      [ 'Vice President', 'John Adams', 'some tooltip content', new Date(1789, 3, 21), new Date(1797, 2, 4)],
      [ 'Vice President', 'Thomas Jefferson', 'some tooltip content', new Date(1797, 2, 4), new Date(1801, 2, 4)],
      [ 'Vice President', 'Aaron Burr', 'some tooltip content', new Date(1801, 2, 4), new Date(1805, 2, 4)],
      [ 'Vice President', 'George Clinton', 'some tooltip content', new Date(1805, 2, 4), new Date(1812, 3, 20)],
      [ 'Secretary of State', 'John Jay', 'some tooltip content', new Date(1789, 8, 25), new Date(1790, 2, 22)],
      [ 'Secretary of State', 'Thomas Jefferson', 'some tooltip content', new Date(1790, 2, 22), new Date(1793, 11, 31)],
      [ 'Secretary of State', 'Edmund Randolph', 'some tooltip content', new Date(1794, 0, 2), new Date(1795, 7, 20)],
      [ 'Secretary of State', 'Timothy Pickering', 'some tooltip content', new Date(1795, 7, 20), new Date(1800, 4, 12)],
      [ 'Secretary of State', 'Charles Lee', 'some tooltip content', new Date(1800, 4, 13), new Date(1800, 5, 5)],
      [ 'Secretary of State', 'John Marshall', 'some tooltip content', new Date(1800, 5, 13), new Date(1801, 2, 4)],
      [ 'Secretary of State', 'Levi Lincoln', 'some tooltip content', new Date(1801, 2, 5), new Date(1801, 4, 1)],
      [ 'Secretary of State', 'James Madison', 'some tooltip content', new Date(1801, 4, 2), new Date(1809, 2, 3)]
    ]);

    google.visualization.events.addListener(dashChart, 'ready', function () {
      google.visualization.events.addListener(dashChart.getChart(), 'onmouseover', function (e) {
        Array.prototype.forEach.call(document.getElementById(dashChart.getContainerId()).getElementsByTagName('rect'), function(bar) {
          if (bar.getAttribute('fill') === '#f4b400') {
            bar.setAttribute('fill', '#f7cb4d')
          }
        });
      });
      google.visualization.events.addListener(dashChart.getChart(), 'onmouseout', function (e) {
        Array.prototype.forEach.call(document.getElementById(dashChart.getContainerId()).getElementsByTagName('rect'), function(bar) {
          if (bar.getAttribute('fill') === '#f7cb4d') {
            bar.setAttribute('fill', '#f4b400')
          }
        });
      });
    });

    dashboard.bind(dashControl, dashChart);
    dashboard.draw(dataTable);
  },
  packages:['controls', 'corechart', 'timeline']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="dashboard">
    <div id="chart" style="height: 200px;"></div>
    <div id="control"></div>
</div>



回答2:

with a little bit of tweaking using jQuery I was able to achieve my goal. just posting this for future reference or possible google'rs

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

    var dashboard = new google.visualization.Dashboard(document.getElementById('dashboard'));

    var dashControl = new google.visualization.ControlWrapper({
      'controlType': 'ChartRangeFilter',
      'containerId': 'control',
      'options': {
        'filterColumnIndex': 3,
        'ui': {
          'chartType': 'ScatterChart',
          'chartOptions': {
            'height': 70,
            'chartArea': {
              width: '80%',
              height: '80%'
            },
            'hAxis': {
              'baselineColor': 'none'
            }
          },
          'chartView': {
            'columns': [3, 4]
          },
          minRangeSize: 12*60*60*1000
        }
      }
    });

    var dashChart = new google.visualization.ChartWrapper({
      'chartType': 'Timeline',
      'containerId': 'chart',
      'options': {
        'chartArea': {
          width: '80%',
          height: '80%'
        },
        hAxis: {
          format: 'dd.MM HH:mm'
        }
      },
      'view': {
        'columns': [0, 1, 2, 3, 4]
      }
    });

    var dataTable = new google.visualization.DataTable();

    dataTable.addColumn({ type: 'string', id: 'Role' });
    dataTable.addColumn({ type: 'string', id: 'Name' });
    dataTable.addColumn({ type: "string", id: "", "role": "tooltip", "p" : { "role" : "tooltip" ,'html': true} });
    dataTable.addColumn({ type: 'date', id: 'Start' });
    dataTable.addColumn({ type: 'date', id: 'End' });

    dataTable.addRows([
      [ 'President', 'George Washington', 'some tooltip content', new Date(1789, 3, 30), new Date(1797, 2, 4) ],
      [ 'President', 'John Adams', 'some tooltip content', new Date(1797, 2, 4), new Date(1801, 2, 4) ],
      [ 'President', 'Thomas Jefferson', 'some tooltip content', new Date(1801, 2, 4), new Date(1809, 2, 4) ],
      [ 'Vice President', 'John Adams', 'some tooltip content', new Date(1789, 3, 21), new Date(1797, 2, 4)],
      [ 'Vice President', 'Thomas Jefferson', 'some tooltip content', new Date(1797, 2, 4), new Date(1801, 2, 4)],
      [ 'Vice President', 'Aaron Burr', 'some tooltip content', new Date(1801, 2, 4), new Date(1805, 2, 4)],
      [ 'Vice President', 'George Clinton', 'some tooltip content', new Date(1805, 2, 4), new Date(1812, 3, 20)],
      [ 'Secretary of State', 'John Jay', 'some tooltip content', new Date(1789, 8, 25), new Date(1790, 2, 22)],
      [ 'Secretary of State', 'Thomas Jefferson', 'some tooltip content', new Date(1790, 2, 22), new Date(1793, 11, 31)],
      [ 'Secretary of State', 'Edmund Randolph', 'some tooltip content', new Date(1794, 0, 2), new Date(1795, 7, 20)],
      [ 'Secretary of State', 'Timothy Pickering', 'some tooltip content', new Date(1795, 7, 20), new Date(1800, 4, 12)],
      [ 'Secretary of State', 'Charles Lee', 'some tooltip content', new Date(1800, 4, 13), new Date(1800, 5, 5)],
      [ 'Secretary of State', 'John Marshall', 'some tooltip content', new Date(1800, 5, 13), new Date(1801, 2, 4)],
      [ 'Secretary of State', 'Levi Lincoln', 'some tooltip content', new Date(1801, 2, 5), new Date(1801, 4, 1)],
      [ 'Secretary of State', 'James Madison', 'some tooltip content', new Date(1801, 4, 2), new Date(1809, 2, 3)]
    ]);

    google.visualization.events.addListener(dashChart, 'ready', function () {
  var original_rect_color;
  var new_rect_color;
  google.visualization.events.addListener(dashChart.getChart(), 'onmouseover', function (e) {
    var original_rect = $("div#dashboard div#chart g rect").filter(function(){return $(this).attr('style') == 'display: none;'})[0];
	var temp_original_color = $(original_rect).attr('fill');
	if(temp_original_color!=original_rect_color)
	{
		$("div#dashboard div#chart g rect").filter(function(){return $(this).attr('fill') == new_rect_color}).each(function(){
			$(this).attr('fill',original_rect_color);
		});
	}
	original_rect_color = temp_original_color;
	var original_rect_x = $(original_rect).attr('x');
	var original_rect_y = $(original_rect).attr('y');
	new_rect_color = $($("div#dashboard div#chart g rect").filter(function(){return $(this).attr('x') == original_rect_x && $(this).attr('y') == original_rect_y})[1]).attr('fill');
	$("div#dashboard div#chart g rect").filter(function(){return $(this).attr('fill') == original_rect_color}).each(function(){
		$(this).attr('fill',new_rect_color);
	});
  });
  google.visualization.events.addListener(dashChart.getChart(), 'onmouseout', function (e) {
    $("div#dashboard div#chart g rect").filter(function(){return $(this).attr('fill') == new_rect_color}).each(function(){
		$(this).attr('fill',original_rect_color);
	});
  });
});

    dashboard.bind(dashControl, dashChart);
    dashboard.draw(dataTable);
  },
  packages:['controls', 'corechart', 'timeline']
});
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="dashboard">
    <div id="chart" style="height: 200px;"></div>
    <div id="control"></div>
</div>