Search code examples
javascriptphpgoogle-maps-api-3google-maps-markersmarkerclusterer

Trying to create a google maps api cluster from external php file marker data


I am trying to display markers from locations in my database and cluster them. I can display the markers ok but cannot seem to figure out how to create an array out of the lat's and long's for the cluster. I am grabbing the data from an external php file like so -

function initMap() {
     var map = new google.maps.Map(document.getElementById('grid-map'), {
         var infoWindow = new google.maps.InfoWindow;

         downloadUrl('myfile.php', function(data) {
         var xml = data.responseXML;
         var markers = xml.documentElement.getElementsByTagName('marker');
         Array.prototype.forEach.call(markers, function(markerElem) {

         // Returned marker data from php file //
          var id = markerElem.getAttribute('id');
          var name = markerElem.getAttribute('title');
          var city = markerElem.getAttribute('city');

          // Lat and Long for each marker
          var point = new google.maps.LatLng(
            parseFloat(markerElem.getAttribute('lat')),
            parseFloat(markerElem.getAttribute('lng'))
          );

          var marker;
            var iconBase = 'mysite.com/img/';           
            marker = new google.maps.Marker({
                map: map,
                position: point,         
                title: name,
                icon: iconBase + 'loc.png'
            });   

           marker.addListener('click', function() {
               map.setZoom(14);
               map.setCenter(marker.getPosition());
           });

           marker.addListener('click', function() {
               infoWindow.setContent(infowincontent);
               infoWindow.open(map, marker);
               return marker;
           });  

         });
     });
}
 function downloadUrl(url, callback) {
       var request = window.ActiveXObject ?
       new ActiveXObject('Microsoft.XMLHTTP') :
       new XMLHttpRequest;
       request.onreadystatechange = function() {
           if (request.readyState == 4) {
               request.onreadystatechange = doNothing;
               callback(request, request.status);
           }
       };
        request.open('GET', url, true);
        request.send(null);       
   }
    function doNothing() {}

<script src="https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/markerclusterer.js"></script>

Here is the Cluster call -

 // Add a marker cluster to manage the markers.
    var markerCluster = new MarkerClusterer(map, markers,
        {imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m',zoomOnClick: false});

Here is the loop from myfile.php

$sql = "SELECT * FROM `table`";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
    while($row = $result->fetch_assoc()) {
        $id = $row['id'];
        $lat = $row['lat'];
        $lng = $row['lng'];
        $title =$row['post_title'];
        $city = $row['post_city'];
        $price = $row['post_price'];

        echo "<marker id='".$id."' price='".$price."' title='".$title."' city='".$city."'  lat='".$lat."' lng='".$lng."' type='X'/>";
   }
}

I just copied the pertinent code from my file to try and keep it readable so I may be missing a bracket. Basically I think I need to create an array of the coordinates for the cluster or is there a way to cluster the locations as they are already being displayed?


Solution

  • Simplest way with your existing code is to define the MarkerClusterer before creating the markers, then add each marker to it as you create them

    1. create the MarkerClusterer with an empty array, before loading the XML:
    var markerCluster = new MarkerClusterer(map, [], {
      imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m',
      zoomOnClick: false
    });
    
    1. load the XML, as you create each marker, add it to the MarkerClusterer with the addMarker method:
    downloadUrl('myfile.php', function(data) {
      var xml = data.responseXML;
      var markers = xml.documentElement.getElementsByTagName('marker');
      Array.prototype.forEach.call(markers, function(markerElem) {
    
        // Returned marker data from php file //
        var id = markerElem.getAttribute('id');
        var name = markerElem.getAttribute('title');
        var city = markerElem.getAttribute('city');
    
       // Lat and Long for each marker
       var point = new google.maps.LatLng(
         parseFloat(markerElem.getAttribute('lat')),
         parseFloat(markerElem.getAttribute('lng'))
       );
    
       var marker = new google.maps.Marker({
         map: map,
         position: point,
         title: name,
       });
    
       markerCluster.addMarker(marker); // <=========================== add this line
    
       marker.addListener('click', function() {
         map.setZoom(14);
         map.setCenter(marker.getPosition());
       });
       var infowincontent = name+"<br>"+city+"<br>"+point.toUrlValue(6);
       marker.addListener('click', function() {
         infoWindow.setContent(infowincontent);
         infoWindow.open(map, marker);
       });
     });
    

    proof of concept fiddle

    screenshot of resulting map

    code snippet:

    function initMap() {
      var map = new google.maps.Map(document.getElementById('grid-map'), {
        center: {lat: 0, lng: 0},
        zoom: 2
      });
      var infoWindow = new google.maps.InfoWindow();
      var bounds = new google.maps.LatLngBounds();
      // Add a marker cluster to manage the markers.
      var markerCluster = new MarkerClusterer(map, [markers], {
        imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m',
        zoomOnClick: false
      });
    
      // downloadUrl('myfile.php', function(data) {
      var xml = parseXml(xmlStr); // data.responseXML;
      var markers = xml.documentElement.getElementsByTagName('marker');
      Array.prototype.forEach.call(markers, function(markerElem) {
    
        // Returned marker data from php file //
        var id = markerElem.getAttribute('id');
        var name = markerElem.getAttribute('title');
        var city = markerElem.getAttribute('city');
    
        // Lat and Long for each marker
        var point = new google.maps.LatLng(
          parseFloat(markerElem.getAttribute('lat')),
          parseFloat(markerElem.getAttribute('lng'))
        );
        bounds.extend(point);
        map.fitBounds(bounds);
    
        var marker = new google.maps.Marker({
          map: map,
          position: point,
          title: name
        });
        markerCluster.addMarker(marker);
        marker.addListener('click', function() {
          map.setZoom(14);
          map.setCenter(marker.getPosition());
        });
        var infowincontent = name + "<br>" + city + "<br>" + point.toUrlValue(6);
        marker.addListener('click', function() {
          infoWindow.setContent(infowincontent);
          infoWindow.open(map, marker);
          return marker;
        });
    
      });
      //});
    }
    
    function downloadUrl(url, callback) {
      var request = window.ActiveXObject ?
        new ActiveXObject('Microsoft.XMLHTTP') :
        new XMLHttpRequest;
      request.onreadystatechange = function() {
        if (request.readyState == 4) {
          request.onreadystatechange = doNothing;
          callback(request, request.status);
        }
      };
      request.open('GET', url, true);
      request.send(null);
    }
    
    function doNothing() {}
    
    function parseXml(str) {
      if (window.ActiveXObject) {
        var doc = new ActiveXObject('MicrosoftXMLDOM');
        doc.loadXML(str);
        return doc;
      } else if (window.DOMParser) {
        return (new DOMParser).parseFromString(str, 'text/xml');
      }
    };
    google.maps.event.addDomListener(window, 'load', initMap);
    var xmlStr = '<markers><marker id="1" title="Love.Fish" city="580 Darling Street, Rozelle, NSW" lat="-33.861034" lng="151.171936" type="restaurant"/><marker id="2" title="Young Henrys" city="76 Wilford Street, Newtown, NSW" lat="-33.898113" lng="151.174469" type="bar"/><marker id="3" title="Hunter Gatherer" city="Greenwood Plaza, 36 Blue St, North Sydney NSW" lat="-33.840282" lng="151.207474" type="bar"/><marker id="4" title="The Potting Shed" city="7A, 2 Huntley Street, Alexandria, NSW" lat="-33.910751" lng="151.194168" type="bar"/><marker id="5" title="Nomad" city="16 Foster Street, Surry Hills, NSW" lat="-33.879917" lng="151.210449" type="bar"/><marker id="6" title="Three Blue Ducks" city="43 Macpherson Street, Bronte, NSW" lat="-33.906357" lng="151.263763" type="restaurant"/><marker id="7" title="Single Origin Roasters" city="60-64 Reservoir Street, Surry Hills, NSW" lat="-33.881123" lng="151.209656" type="restaurant"/><marker id="8" title="Red Lantern" city="60 Riley Street, Darlinghurst, NSW" lat="-33.874737" lng="151.215530" type="restaurant"/></markers>'
    html,
    body,
    #grid-map {
      height: 100%;
      margin: 0;
      padding: 0;
    }
    <div id="grid-map"></div>
    <!-- Replace the value of the key parameter with your own API key. -->
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk">
    </script>
    <script src="https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/markerclusterer.js"></script>