Add a google chart to a FusionTableLayer infowindo

2019-02-21 05:48发布

问题:

I'm trying to display chart (Google Chart API) inside InfoWindow (Fusion Table layer), but the problem is with container "Uncaught Error: The container is null or not defined." whenever I try to include div inside InfoWindow.

I was trying to solve the problem based on this solution, but it's not working with fusion table Add a google chart to a infowindow using google maps api

Please help

<script type="text/javascript">
google.load('visualization', '1', {packages: ['corechart']});
    function drawVisualization() {
      var queryText = encodeURIComponent("SELECT Year, Austria, Bulgaria, Denmark, Greece FROM 641716");
      google.visualization.drawChart({
        "containerId": 'visualization_div',
        "dataSourceUrl": 'https://www.google.com/fusiontables/gvizdata?tq=',
        "query":"SELECT Year, Austria, Bulgaria, Denmark, Greece FROM 641716",
        "refreshInterval": 5,
        "chartType": "PieChart",
        "options": {
          "title":"Yearly Coffee Consumption by Country",
          "vAxis": {"title": "Year"},
          "hAxis": {"title": "Cups"}
        }
      });
    }
      function initialize() {
        var map = new google.maps.Map(document.getElementById('map-canvas'), {
          center: new google.maps.LatLng(29.296435107347698, -29.54822280000008),
          zoom: 2,
          mapTypeId: google.maps.MapTypeId.ROADMAP
        });

        var layer = new google.maps.FusionTablesLayer({
          query: {
            select: 'col0',
            from: '1PoUAVtdJKOKnJT_ZYkoM7yDpGw-wNJMHXakPeC0'
          },
          map: map
        });
        google.maps.event.addListener(layer, 'click', function(e) {
        drawVisualization(this);
          e.infoWindowHtml += "<div id='visualization_div'></div>";{
          }
        });
      }

      google.maps.event.addDomListener(window, 'load', initialize);

    </script>

PS.

One more thing ! It's possible to display chart from data from one row. In my example for one country that is clicked ?

回答1:

It's a bit more difficult.

The infowindow of a FTLayer doesn't open immediately, because the data for the infowindow will be requested asynchronously.

When you call drawVisualization immediately there is no guarantee that the infowindow-content is already available in the DOM, the #visualization_div will not be available yet.

The problem: there is no domready-event for the infowindow of the FTLayer, you'll never know when the infowindow is ready.

Another problem: the chart will also be drawn asynchronously, the result would be a undesirable look of the infowindow(the chart will be drawn under the infowindow, not inside)

Possible solution(there may be others): use a custom infowindow instead:

<script type="text/javascript">
google.load('visualization', '1', {packages: ['corechart']});

  //pass the infowindow as argument, we need it later
function drawVisualization(infowindow) {
  var queryText = encodeURIComponent("SELECT Year, Austria, Bulgaria, \
                                      Denmark, Greece FROM 641716");

    /*note:      we don't need the ContainerId here, 
                 we use the node-reference with draw
     *also note: we use ChartWrapper here, because we need 
                 the ready-event of the chart to redraw the infowindow
    */
  var chart=new google.visualization.ChartWrapper({
    "dataSourceUrl": 'https://www.google.com/fusiontables/gvizdata?tq=',
    "query":"SELECT Year, Austria, Bulgaria, Denmark, Greece FROM 641716",
    "refreshInterval": 5,
    "chartType": "PieChart",
    "options": {
      "title":"Yearly Coffee Consumption by Country",
      "vAxis": {"title": "Year"},
      "hAxis": {"title": "Cups"}
    }
  });


  var ready=google.visualization.events.addListener(chart, 'ready', function(){
      //re-assign the map-property to redraw the 
      //infowindow when the chart has been drawn
    infowindow.setMap(infowindow.getMap());
      //remove the ready-listener
    google.visualization.events.removeListener(ready);
   });

    //draw the chart
  chart.draw(infowindow.getContent().lastChild);

}

function initialize() {
    map = new google.maps.Map(document.getElementById('map-canvas'), {
      center: new google.maps.LatLng(29.296435107347698, -29.54822280000008),
      zoom: 2,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    });

    var layer = new google.maps.FusionTablesLayer({
      query: {
        select: 'col0',
        from: '1PoUAVtdJKOKnJT_ZYkoM7yDpGw-wNJMHXakPeC0'
      },
      map: map,
        //don't use the infowindows of the FTLayer
      suppressInfoWindows:true
    });
      //a custom infowindow
    infowindow=new google.maps.InfoWindow();


    google.maps.event.addListener(layer, 'click', function(e) {
      //call drawVisualization when the infowindow is ready
      google.maps.event.addListenerOnce(infowindow,'domready',function(){
        drawVisualization(infowindow);
      });
        //create the content for the infowindow
      var node=document.createElement('div');
      node.innerHTML=e.infoWindowHtml;
        //create the node where the chart will be drawn
      node.appendChild(document.createElement('div'));
        //open the infowindow
      infowindow.setOptions({position:e.latLng,content:node,map:map});
     });
  }

  google.maps.event.addDomListener(window, 'load', initialize);

</script>


回答2:

I found also second way, maybe not so sophisticated but working
1. Create chart in Fusion Table
2. Copy link from Publish tab
3. Paste the link inside iframe. I made some tabs for this

'<div id="tab-2">' + //firts tab content 
    '<iframe src="https://www.google.com/fusiontables/embedviz?containerId=googft-gviz-canvas&q=select+col2%2C+col3+from+1NLk1HStpHzzSedbjQioau_7fSxeVlmb4G4A46MM+order+by+col3+desc+limit+6&viz=GVIZ&t=PIE&uiversion=2&gco_forceIFrame=true&gco_hasLabelsColumn=true&gco_useFirstColumnAsDomain=true&gco_is3D=false&gco_pieHole=0.5&gco_booleanRole=certainty&gco_colors=%5B%22%233366CC%22%2C%22%23DC3912%22%2C%22%23FF9900%22%2C%22%23109618%22%2C%22%23990099%22%2C%22%230099C6%22%2C%22%23DD4477%22%2C%22%2366AA00%22%2C%22%23B82E2E%22%2C%22%23316395%22%2C%22%23994499%22%2C%22%2322AA99%22%2C%22%23AAAA11%22%2C%22%236633CC%22%2C%22%23E67300%22%2C%22%238B0707%22%2C%22%23651067%22%2C%22%23329262%22%2C%22%235574A6%22%2C%22%233B3EAC%22%2C%22%23B77322%22%2C%22%2316D620%22%2C%22%23B91383%22%2C%22%23F4359E%22%2C%22%239C5935%22%2C%22%23A9C413%22%2C%22%232A778D%22%2C%22%23668D1C%22%2C%22%23BEA413%22%2C%22%230C5922%22%2C%22%23743411%22%5D&gco_hAxis=%7B%22useFormatFromData%22%3Atrue%2C+%22viewWindow%22%3A%7B%22max%22%3Anull%2C+%22min%22%3Anull%7D%2C+%22minValue%22%3Anull%2C+%22maxValue%22%3Anull%7D&gco_vAxes=%5B%7B%22useFormatFromData%22%3Atrue%2C+%22viewWindow%22%3A%7B%22max%22%3Anull%2C+%22min%22%3Anull%7D%2C+%22minValue%22%3Anull%2C+%22maxValue%22%3Anull%7D%2C%7B%22useFormatFromData%22%3Atrue%2C+%22viewWindow%22%3A%7B%22max%22%3Anull%2C+%22min%22%3Anull%7D%2C+%22minValue%22%3Anull%2C+%22maxValue%22%3Anull%7D%5D&gco_theme=maximized&gco_legend=none&width=00&height=150"frameborder="0"; scrolling="no"/>' +
    '</div>' +

DEMO

And we can also insert query into URL so just selected rows are in Google Chart

e.row['Country_Name'].value

'<div id="tab-2">' + //firts tab content 
    '<iframe src="https://www.google.com/fusiontables/embedviz?containerId=googft-gviz-canvas&q=select+col0%2C+col1%2C+col2%2Ccol3+from+1r4egxlD-9QeK-4gBrdtTGQFrhdrBoxNhBwQbWUc+%20WHERE%20Country_Name=%27'+ e.row['Country_Name'].value +'%27+order+by+col1+asc+limit+10&viz=GVIZ&t=COLUMN&uiversion=2&gco_forceIFrame=true&gco_hasLabelsColumn=true&att=true&gco_theme=maximized&width=300&height=150"frameborder="0"; scrolling="no"/>' +

DEMO 2



回答3:

I solved this by rendering the charts to PNG with gnuplot and serving them as static images from a column of URLs in the Fusion Table.

It's not a Google Chart/javascript solution, but we have more data points than we want to plot on the fly with Google Chart anyway.