tempranova
tempranova

Reputation: 937

Trigger click on a single geoJSON polygon after load

A client has loaded some polygons onto a map using Google Maps APIv3 loadGeoJson() method. I want to be able to search through those polygons and, when one matches a submitted string, zoom/centre on it and trigger a click event, opening the infowindow of that polygon.

Some answers hint that, to reference the geoJSON feature, it's best to use getId(), then use that reference to select the polygon on the map. Comes out undefined, and not sure if it would help anyways; few other methods really seem to work (getGeometry() is broken), through getProperty() does. This makes me think maybe I'm iterating over the wrong array.

This JSBin illustrates what I'm trying to do, especially lines 85-100:

// Trying to search in the layer and trigger an event
geoJsonLayer.forEach(function(feature) {
  if(searchString===feature.getProperty('letter')) {
    // Match found, Zoom to this feature and pop its infobox
    var foundFeatureId = feature.getId(); // Is undefined
    // var foundFeatureId = feature.id; // Is undefined
    // var foundFeatureGeo = feature.getGeometry().get(); // Not a function
    console.log(foundFeatureId);
    google.maps.event.trigger(map,'click',feature); // seems to do nothing
  }
});

On search of a character ("g","o","l", for instance), the search finds a match and then tries to trigger the click event of that geoJSON polygon (ultimately, so the infowindow is opened).

This is the part that's stumping me. I've tried defining the ID, but it's undefined using getId(). Can't seem to directly trigger it either when iterating over the Data layer. Can't seem to find it when trying to look into maps.data either.

How do I properly trigger this event using the geoJSON layer only?

Upvotes: 4

Views: 4233

Answers (2)

geocodezip
geocodezip

Reputation: 161404

A google.maps.Data.Polygon doesn't have a get() method, it has a getArray() method, which returns an array of the contained Data.LinearRings. So for the "o" it will have 2 entries, for the "G" it will only have one.

This will zoom the map to fit a polygon based on its "letter" property:

geoJsonLayer.forEach(function(feature) {
  if(searchString===feature.getProperty('letter')) {
    var foundFeatureGeo = feature.getGeometry().getAt(0).getArray(); // Also broken
    var bounds = new google.maps.LatLngBounds();
    for (var i=0; i<foundFeatureGeo.length; i++) {
      bounds.extend(foundFeatureGeo[i]);
    }
    map.fitBounds(bounds);
}

To open an infowindow you need to determine where you want it to open. There is no access to a google.maps.Polygon to trigger a click on, and to trigger it on the DataLayer, you need to provide the "event data", both the .feature and the latLng properties of the event.

var name =  feature.getProperty('letter');
var myHTMLss = '<table>' +
  '<tr><td>Name:</td><td>'+name+'</td></tr>' + 
  '</table>';
infowindow.setContent(myHTMLss);
// arbirarily pick the first point
infowindow.setPosition(foundFeatureGeo[0]);
infowindow.open(map);

proof of concept fiddle

code snippet:

// Loading stuff
function initMap() {
  map = new google.maps.Map(document.getElementById('map-canvas'), {
    zoom: 4,
    center: {
      lat: -28,
      lng: 137
    },
    mapTypeId: google.maps.MapTypeId.SATELLITE
  });

  // Load geoJSON
  geoJsonLayer = new google.maps.Data();
  geoJsonLayer.addGeoJson(sampleJSON);
  geoJsonLayer.setMap(map);

  // Set click event for infowindow
  var infowindow = new google.maps.InfoWindow();
  geoJsonLayer.addListener('click', function(event) {
    var name = event.feature.getProperty('letter');
    var myHTMLss = '<table>' +
      '<tr><td>Name:</td><td>' + name + '</td></tr>' +
      '</table>';
    infowindow.setContent(myHTMLss);
    infowindow.setPosition(event.latLng);
    infowindow.open(map);
  });

  // Search for property in geoJson
  $('#search').click(function() {
    var searchString = $('#searchInput').val();

    // Search in the layer and trigger an event
    geoJsonLayer.forEach(function(feature) {
      if (searchString === feature.getProperty('letter')) {
        // Zoom to this feature and pop its infobox
        var foundFeatureGeo = feature.getGeometry().getAt(0).getArray();
        var bounds = new google.maps.LatLngBounds();
        for (var i = 0; i < foundFeatureGeo.length; i++) {
          bounds.extend(foundFeatureGeo[i]);
        }
        map.fitBounds(bounds);
        google.maps.event.trigger(geoJsonLayer, 'click', {
          // arbirarily pick the first point of the outer ring of the polygon
          latLng: foundFeatureGeo[0],
          "feature": feature
        });
      }
    });
  });
}
google.maps.event.addDomListener(window, 'load', initMap);
var sampleJSON = {
  "type": "FeatureCollection",
  "features": [{
    "type": "Feature",
    "properties": {
      "letter": "G",
      "color": "blue",
      "rank": "7",
      "ascii": "71",
      "id": 0
    },
    "geometry": {
      "type": "Polygon",
      "coordinates": [
        [
          [123.61, -22.14],
          [122.38, -21.73],
          [121.06, -21.69],
          [119.66, -22.22],
          [119.00, -23.40],
          [118.65, -24.76],
          [118.43, -26.07],
          [118.78, -27.56],
          [119.22, -28.57],
          [120.23, -29.49],
          [121.77, -29.87],
          [123.57, -29.64],
          [124.45, -29.03],
          [124.71, -27.95],
          [124.80, -26.70],
          [124.80, -25.60],
          [123.61, -25.64],
          [122.56, -25.64],
          [121.72, -25.72],
          [121.81, -26.62],
          [121.86, -26.98],
          [122.60, -26.90],
          [123.57, -27.05],
          [123.57, -27.68],
          [123.35, -28.18],
          [122.51, -28.38],
          [121.77, -28.26],
          [121.02, -27.91],
          [120.49, -27.21],
          [120.14, -26.50],
          [120.10, -25.64],
          [120.27, -24.52],
          [120.67, -23.68],
          [121.72, -23.32],
          [122.43, -23.48],
          [123.04, -24.04],
          [124.54, -24.28],
          [124.58, -23.20],
          [123.61, -22.14]
        ]
      ]
    }
  }, {
    "type": "Feature",
    "properties": {
      "letter": "o",
      "color": "red",
      "rank": "15",
      "ascii": "111",
      id: 1
    },
    "geometry": {
      "type": "Polygon",
      "coordinates": [
        [
          [128.84, -25.76],
          [128.18, -25.60],
          [127.96, -25.52],
          [127.88, -25.52],
          [127.70, -25.60],
          [127.26, -25.79],
          [126.60, -26.11],
          [126.16, -26.78],
          [126.12, -27.68],
          [126.21, -28.42],
          [126.69, -29.49],
          [127.74, -29.80],
          [128.80, -29.72],
          [129.41, -29.03],
          [129.72, -27.95],
          [129.68, -27.21],
          [129.33, -26.23],
          [128.84, -25.76]
        ],
        [
          [128.45, -27.44],
          [128.32, -26.94],
          [127.70, -26.82],
          [127.35, -27.05],
          [127.17, -27.80],
          [127.57, -28.22],
          [128.10, -28.42],
          [128.49, -27.80],
          [128.45, -27.44]
        ]
      ]
    }
  }]
};
html,
body,
#map-canvas {
  height: 100%;
  width: 100%;
  margin: 0px;
  padding: 0px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<input type="text" id="searchInput" />
<button id="search">Search</button>
<div id="map-canvas"></div>

Upvotes: 3

wf9a5m75
wf9a5m75

Reputation: 6158

Trigger click event to map.data like below. (In the below code, I add a polygon instead of loading geojson file, in order to test anyone without file)

update: searching a feature, use map.data.forEach() method.

update2: Case of a custom layer.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <style type="text/css">
    #map_canvas {
      width: 600px;
      height: 400px;
      border: 1px solid gray;
    }
    </style>
    <script src="https://maps.googleapis.com/maps/api/js"></script>
    <script>

      function initMap() {


        var div = document.getElementById("map_canvas");
        var map = new google.maps.Map(div, {
          center: {lat: 41.79763176991999, lng: 140.75910257175565},
          zoom: 15,
          mapTypeId: google.maps.MapTypeId.ROADMAP
        });

        //map.data.loadGeoJson("polygons.json");

        //----------------------------------------------
        // Start - Adding a feature (instead of loadGeoJson for test)
        //----------------------------------------------

        // polygon paths
        var exteriorBoundary = new google.maps.Data.LinearRing([
          {lat: 41.79567213554726, lng: 140.75482176616788},
          {lat: 41.795888098191426, lng: 140.75384544208646},
          {lat: 41.79604007146779, lng: 140.75370596721768},
          {lat: 41.79621604007439, lng: 140.75369523838162},
          {lat: 41.79739981632479, lng: 140.7546071894467},
          {lat: 41.79878352706213, lng: 140.75461791828275},
          {lat: 41.79895148991592, lng: 140.75470374897122},
          {lat: 41.79899947922187, lng: 140.7548968680203},
          {lat: 41.798743535841595, lng: 140.75671004131436},
          {lat: 41.79915944331544, lng: 140.7585554011166},
          {lat: 41.79914344692405, lng: 140.7587699778378},
          {lat: 41.79895948813609, lng: 140.75889872387052},
          {lat: 41.79763176991999, lng: 140.75910257175565},
          {lat: 41.796487990607034, lng: 140.7601754553616},
          {lat: 41.79630402419653, lng: 140.76018618419766},
          {lat: 41.79618404581822, lng: 140.76005743816495},
          {lat: 41.79561614511331, lng: 140.75835155323148},
          {lat: 41.79444033470146, lng: 140.7573108561337},
          {lat: 41.794408339558885, lng: 140.75716065242887},
          {lat: 41.79443233591732, lng: 140.75695680454373},
          {lat: 41.795024243248456, lng: 140.75621651485562},
          {lat: 41.79467229900768, lng: 140.7550578005612},
          {lat: 41.794736289013386, lng: 140.7548968680203},
          {lat: 41.79567213554726, lng: 140.75482176616788}
        ]);

        var polygon = new google.maps.Data.Polygon([exteriorBoundary]);

        var feature = new google.maps.Data.Feature({
          geometry: polygon,
          properties: {
            name: "Goryo-kaku, Hokkaido, Japan"
          },
          id: "goryokaku"
        });

        // Add a feature to the data layer.
        var layer = new google.maps.Data({
          map: map
        });
        layer.add(feature);

        // Fill all polygon as red
        layer.setStyle({
          scale: 6,
          strokeColor: "white",
          strokeOpacity: 1,
          strokeWeight: 1,
          fillColor: "red",
          fillOpacity: 0.5
        });

        //----------------------------------------------
        // End - adding a feature
        //----------------------------------------------

        // Catch the click event
        layer.addListener('click', function(data_mouseEvent) {
          var feature = data_mouseEvent.feature;
          feature.toGeoJson(function(geojson){
            var infoWnd = new google.maps.InfoWindow({
              content: JSON.stringify(geojson.properties, null, 2),
              position: feature.getGeometry().getAt(0).getAt(0)
            });
            infoWnd.open(map);
          });
        });

        layer.forEach(function(feature) {
          if (feature.getProperty('name') === "Goryo-kaku, Hokkaido, Japan" ) {
            google.maps.event.trigger(layer, 'click', {
              feature: feature
            });
          }
        });
      }
      google.maps.event.addDomListener(window, "load", initMap);
    </script>
  </head>
  <body>
    <div id="map_canvas"></div>
  </body>
</html>

enter image description here

Upvotes: 1

Related Questions