Search code examples
javascriptgoogle-mapsgeojsoninfowindowmarkerclusterer

using google maps .loadGeoJson, markerclusterer and infowindow breaking


Trying to get infowindows to open on click with loadGeoJson and MarkerClusterers. I'm using the code below because I want to be able to add a link to the infowindow.

https://codepen.io/cbrady97/pen/qKoERJ

<!DOCTYPE html>
<html>
<body>
<div id="map" style="height: 2000px;width: 100%;"></div>

<script>
    var infowindow = new google.maps.InfoWindow();
    var markers;
    function initMap() {
        var map = new google.maps.Map(document.getElementById('map'), {
            zoom: 7,
            center: { lat: 42.25, lng: -109.05 },
            mapTypeId: 'terrain'
        });
        map.data.loadGeoJson('https://cors.io/?https://solveatlas.com/s/map-easj.geojson', null, function (features){
            markers = features.map(function(feature) {
                return new google.maps.Marker({
                    position: feature.getGeometry().get(0)
                });
            });
         // When the user clicks, open an infowindow
        map.data.addListener('click', function(event) {
             var feat = event.feature;
             var html = "<b>"+feat.getProperty('name')+"</b><br>"+feat.getProperty('description');
             html += "<br><a class='normal_link' target='_blank' href='"+feat.getProperty('link')+"'>link</a>";
             infowindow.setContent(html);
             infowindow.setPosition(event.latLng);
             infowindow.setOptions({pixelOffset: new google.maps.Size(0,-34)});
             infowindow.open(map);
});
        var markerCluster = new MarkerClusterer(map, markers,
                {imagePath: 'https://solveatlas.com/s/m'});   
        });

        map.data.setMap(null);
    }
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<script src="https://solveatlas.com/s/markerclusterer.js">
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBty3z-bpSUEgG54LF34eu7Sz_4zv7aiss&callback=initMap">
</script>
</body>
</html>

Solution

  • You have a number of issues in your code:

    1. google.maps.event.addDomListener(window, 'load', initialize); there is no initialize function in your code. Also you are loading the API asynchronously and this isn't inside the callback function.
    2. Your are instantiating the infowindow before the API is loaded (outside of the callback function): var infowindow = new google.maps.InfoWindow();
    3. You are creating markers from the GeoJson, but not adding the click listener to display the data to them, you are using map.data.addListener, but the data layer has been removed from the map (map.data.setMap(null);).

    To make the infowindows appear on a marker click:

    1. move the instantiation of the InfoWindow inside the initMap function.
    2. create click listeners for the markers:
    map.data.loadGeoJson('https://cors.io/?https://solveatlas.com/s/map-easj.geojson', null, function(features) {
      markers = features.map(function(feature) {
        var marker = new google.maps.Marker({
          position: feature.getGeometry().get(0)
        });
        // When the user clicks, open an infowindow
        marker.addListener('click', function(event) {
          var feat = feature;
          var html = "<b>" + feat.getProperty('name') + "</b><br>" + feat.getProperty('description');
          html += "<br><a class='normal_link' target='_blank' href='" + feat.getProperty('link') + "'>link</a>";
          infowindow.setContent(html);
          infowindow.open(map, marker);
        });
        return marker;
      });
    
    1. remove the click listener on the data layer (it doesn't work):
      // When the user clicks, open an infowindow
      map.data.addListener('click', function(event) {
        var feat = event.feature;
        var html = "<b>"+feat.getProperty('name')+"</b><br>"+feat.getProperty('description');
        html += "<br><a class='normal_link' target='_blank' href='"+feat.getProperty('link')+"'>link</a>";
        infowindow.setContent(html);
        infowindow.setPosition(event.latLng);
        infowindow.setOptions({pixelOffset: new google.maps.Size(0,-34)});
        infowindow.open(map);
    });
    

    proof of concept fiddle

    enter image description here

    code snippet:

    var infowindow;
    var markers;
    
    function initMap() {
      var map = new google.maps.Map(document.getElementById('map'), {
        zoom: 7,
        center: {
          lat: 42.25,
          lng: -109.05
        },
        mapTypeId: 'terrain'
      });
      infowindow = new google.maps.InfoWindow();
      map.data.loadGeoJson('https://cors.io/?https://solveatlas.com/s/map-easj.geojson', null, function(features) {
        markers = features.map(function(feature) {
          var marker = new google.maps.Marker({
            position: feature.getGeometry().get(0)
          });
          // When the user clicks, open an infowindow
    
          marker.addListener('click', function(event) {
            var feat = feature;
            var html = "<b>" + feat.getProperty('name') + "</b><br>" + feat.getProperty('description');
            html += "<br><a class='normal_link' target='_blank' href='" + feat.getProperty('link') + "'>link</a>";
            infowindow.setContent(html);
            infowindow.open(map, marker);
          });
          return marker;
        });
    
        var markerCluster = new MarkerClusterer(map, markers, {
          imagePath: 'https://solveatlas.com/s/m'
        });
      });
    
      map.data.setMap(null);
    }
    html,
    body,
    #map {
      height: 100%;
      width: 100%;
      margin: 0px;
      padding: 0px
    }
    <script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap"></script>
    <script src="https://cdn.rawgit.com/googlemaps/v3-utility-library/master/markerclustererplus/src/markerclusterer.js"></script>
    <div id="map"></div>