14

I am having issues with markers overlapping, please do not down vote as I am not highly schooled in javascript also I have looked at the different answers offered on stackoverflow but have not been able to use them to find a solution so please help! The code is grabbing php for lat and long based on static points I have given I would simply like to list all of the information in the same marker rather than have it overlap markers any help would be highly appreciated here is the code:

  <head>

<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<META HTTP-EQUIV="refresh" >
<title>Operations</title>

<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?key=APIKEY&sensor=false"></script>
<script src="oms.min.js"></script>
<script type="text/javascript">
//<![CDATA[

var customIcons = {      

restaurant: {        icon: 'mm_20_blue.png'      },      

bar: {        icon: 'mm_20_blue.png'      }    

};

function load() {
  var map = new google.maps.Map(document.getElementById("map"), {
    center: new google.maps.LatLng(32.298342, -64.791098),
    zoom: 17,
    mapTypeId: google.maps.MapTypeId.SATELLITE
  });
  var infoWindow = new google.maps.InfoWindow;

  // Change this depending on the name of your PHP file
  downloadUrl("genxml.php", function(data) {
    var xml = data.responseXML;
    var markers = xml.documentElement.getElementsByTagName("marker");
    for (var i = 0; i < markers.length; i++) {
      var name = markers[i].getAttribute("name");
      var address = markers[i].getAttribute("address");
      var type = markers[i].getAttribute("type");
       var id = markers[i].getAttribute("permitnumber");
      var point = new google.maps.LatLng(
          parseFloat(markers[i].getAttribute("lat")),
          parseFloat(markers[i].getAttribute("lng")));
      var html = "<b>" + name + "</b> <br/>" + address + "<br/>" + '<a href="http://server/editform.php?find=' + id + '" >More Info</a> <br/> <form action="del.php" method="post" enctype="multipart/form-data"> <input type="checkbox" name="checkbox" id="checkbox" value="' + id +'"> <input name="delete" type="submit" id="delete" value="Delete">  ' ;
      var icon = customIcons[type] || {};
      var marker = new google.maps.Marker({
        map: map,
        position: point,
        icon: icon.icon,
        shadow: icon.shadow,
        animation: google.maps.Animation.BOUNCE

      });

      bindInfoWindow(marker, map, infoWindow, html);
    }
   });
   }




    function bindInfoWindow(marker, map, infoWindow, html) {
    google.maps.event.addListener(marker, 'click', function() {
    infoWindow.setContent(html);
    infoWindow.open(map, 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>


  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" type="text/javascript"></script>
  <script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.8.1/jquery.validate.min.js" type="text/javascript"></script>
  <script type="text/javascript">

  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-24568877-1']);
  _gaq.push(['_trackPageview']);

   (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
     ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-         analytics.com/ga.js';
     var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
     })();

    </script>

   </head>

   <body onload="load()" bgcolor="#A8F748" >

  <div id="map" style="margin:auto; width: 90%; height: 470px"></div>






  </body>
Learning
  • 151
  • 1
  • 1
  • 6
  • I suggest you create an array of non-overlapping markers. For each lat/lng point, check the markers you have created so far. If the X/Y coord is within some radius of the point, then assume it overlaps. Update the marker to contain the additional information. If the point is outside of the current list of markers, make a new marker and add it to the list. - OpenGeoCode.Org – Andrew - OpenGeoCode Nov 06 '13 at 19:50
  • 1
    possible duplicate of [Google Maps Multiple markers with the exact same location Not working](http://stackoverflow.com/questions/17708252/google-maps-multiple-markers-with-the-exact-same-location-not-working) – geocodezip Nov 06 '13 at 19:55
  • The markers that overlap have the exact same lat and long point I simply would like there to be one marker with all of the different content for different markers that would be on that point, unfortunately I am unfamiliar with javascript enough to achieve this. @Andrew – Learning Nov 06 '13 at 20:01
  • I have looked at this question however it is not pulling in data dynamically from PHP MYSQL DB , and I cannot understand how it will automatically grab the marker nearby and put the content in it, however the end result is actually exactly what I would like to achieve , I am just unsure how to implement it in this situation. @geocodezip – Learning Nov 06 '13 at 20:02
  • Any idea how I can achieve that solution with this code as I need to grab my marker info in through php I am struggling alot to understand how you did what you did as it is exactly what I want. @geocodezip – Learning Nov 06 '13 at 20:15

6 Answers6

7

If you don't want markers overlapping, you'll probably need to use google-maps-utility-library-v3. It has a feature called Marker Clusterer, which basically allows you to put nearby markers into one singular marker. It can be configured so that these markers reappear as separate entities once the user has zoomed in far enough. Here's a demo.

DavGarcia
  • 18,540
  • 14
  • 58
  • 96
Wayne Whitty
  • 19,513
  • 7
  • 44
  • 66
  • Liked the demo. Haven't used this google feature. Will for now on! – Andrew - OpenGeoCode Nov 06 '13 at 19:56
  • @Andrew Its very handy, especially for apps where being able to see all markers (or at least know how many of them exist in a certain area) is important! – Wayne Whitty Nov 06 '13 at 19:57
  • Thank so much for your response , I have seen this in other forums unforunately I am unsure whether this will work as I have the markers with the exact same lat and long points becuase they are for different people working in the same building the ideal solution would be for a way to put the content of the marker that it is overlapping on the same marker so that all information for that location is in once single marker infobox, thanks again alot for your help! :) @WayneWhitty – Learning Nov 06 '13 at 19:58
  • I would like to achieve the same end result as was provided by geocodezip @WayneWhitty – Learning Nov 06 '13 at 20:24
  • 2
    Demo link going to a 404 - Google Maps Utility Library has moved to github – user1380540 May 12 '16 at 15:51
  • 3
    How does the marker clusterer handle pins that are on top of one another (share the same location). For example, if you are listing all airlines that fly to a given city. You may end up with several pins clustered over a single point representing, for example, "Birmingham, Alabama". Can the clusterer spread these pins around the single map point it uses to identify that location? – Scott B Feb 20 '18 at 12:50
3

I use this - https://github.com/jawj/OverlappingMarkerSpiderfier

See a demo here - http://jawj.github.io/OverlappingMarkerSpiderfier/demo.html

Vince Lowe
  • 3,521
  • 7
  • 36
  • 63
  • 2
    This plugin has one weakness in that it isn't possible to tell when a marker is perfectly hidden behind another marker. So, as the original repo seems to be abandoned, I forked the repo and made one with the option to [nudge perfectly overlapped markers](https://github.com/fritz-c/OverlappingMarkerSpiderfier/releases/tag/v1.1.0) out from under each other: https://github.com/fritz-c/OverlappingMarkerSpiderfier – Chris Jun 07 '16 at 23:29
  • The demo doesn't exist anymore... 404. – Shanimal Sep 13 '17 at 17:20
  • Demo here: https://jawj.github.io/OverlappingMarkerSpiderfier/demo-3.html – candlejack Dec 27 '17 at 04:56
1

I have found a solution through much searching and thanks to posts by @geocodezip , I am still having one small problem when zooming into the markers any marker thats directly on another will stay in clustered mode, I would like to achieve the infoWindow sharing both markers content any help would be awesome , thanks again geocodezip for your posts!

<!DOCTYPE html >
<head>

    <meta charset="utf-8"/>
    <title>Google Maps API V3 with Marker Manager</title>
    <meta name="description" content="Google Maps API V3 with MarkerCluster, Coincident Markers Share Infowindow" />
    <meta name="keywords" content="google maps api v3, markerclusterer, markers, infowindow" />
    <meta name="author" content="Casey P. Thomas" />
    <script type="text/javascript"  src="http://maps.google.com/maps/api/js?sensor=false"></script>
    <script type="text/javascript"  src="http://maps.caseypthomas.org/markerclusterer.js"></script>
<script type="text/javascript">
//<![CDATA[
        var map;

    //marker clusterer
    var mc;
    var mcOptions = {gridSize: 20, maxZoom: 17};
    var markers;        
    //global infowindow
    var infowindow = new google.maps.InfoWindow();

    //geocoder
    var geocoder = new google.maps.Geocoder(); 


  var customIcons = {
  restaurant: {
    icon: 'mm_20_blue.png',
    shadow: 'http://labs.google.com/ridefinder/images/mm_20_shadow.png'
  },
  bar: {
    icon: 'mm_20_blue.png',
    shadow: 'http://labs.google.com/ridefinder/images/mm_20_shadow.png'
  }
 };

 function load() {
  var cluster = [];
  var map = new google.maps.Map(document.getElementById("map"), {
    center: new google.maps.LatLng(32.298342, -64.791098),
    zoom: 13,
    mapTypeId: google.maps.MapTypeId.SATELLITE
  });
var infowindow = new google.maps.InfoWindow();

  // Change this depending on the name of your PHP file
  downloadUrl("genxml.php", function(data) {
    var xml = data.responseXML;
    var markers = xml.documentElement.getElementsByTagName("marker");
    for (var i = 0; i < markers.length; i++) {
      var name = markers[i].getAttribute("name");
      var address = markers[i].getAttribute("address");
      var type = markers[i].getAttribute("type");
       var id = markers[i].getAttribute("permitnumber");
      var point = new google.maps.LatLng(
          parseFloat(markers[i].getAttribute("lat")),
          parseFloat(markers[i].getAttribute("lng")));
      var html = "<b>" + name + "</b> <br/>" + address + "<br/>" + '<a href="http://server/editform.php?find=' + id + '" >More Info</a> <br/> <form action="del.php" method="post" enctype="multipart/form-data"> <input type="checkbox" name="checkbox" id="checkbox" value="' + id +'"> <input name="delete" type="submit" id="delete" value="Delete">  ' ;
      var icon = customIcons[type] || {};
      var marker = new google.maps.Marker({
        map: map,
        position: point,
        icon: icon.icon,
        shadow: icon.shadow,
        animation: google.maps.Animation.BOUNCE
      });

      google.maps.event.addListener(marker, 'click', (function(marker, i) {
                    return function() {
                         var id = markers[i].getAttribute("permitnumber");
                        var name = markers[i].getAttribute("name");
                        var address = markers[i].getAttribute("address");
                        var type = markers[i].getAttribute("type");
                        infowindow.setContent("<b>" + name + "</b> <br/>" + address + "<br/>" + '<a href="http://server/editform.php?find=' + id + '" >More Info</a> <br/> <form action="del.php" method="post" enctype="multipart/form-data"> <input type="checkbox" name="checkbox" id="checkbox" value="' + id +'"> <input name="delete" type="submit" id="delete" value="Delete">  ');
                        infowindow.open(map, marker);

                    }
                })(marker, i));
      cluster.push(marker);
    }
    var mc = new MarkerClusterer(map,cluster);
  });
}

function bindInfoWindow(marker, map, infoWindow, html) {
  google.maps.event.addListener(marker, 'click', function() {
    infoWindow.setContent(html);
    infoWindow.open(map, 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> 



 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" type="text/javascript"></script>
 <script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.8.1/jquery.validate.min.js" type="text/javascript"></script>
 <script type="text/javascript">

var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-24568877-1']);
_gaq.push(['_trackPageview']);

 (function() {
 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-  analytics.com/ga.js';
 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
 })();

 </script>


 </head>

 <body onload="load()" bgcolor="#A8F748" >

 <div id="map" style="margin:auto; width: 90%; height: 470px"></div>






</body>

</html>
Learning
  • 151
  • 1
  • 1
  • 6
0

You can use the MarkerClusterer from google maps utility library.

Here is a step by step example: https://developers.google.com/maps/documentation/javascript/marker-clustering

And you can download the library from the google maps github repo: https://github.com/googlemaps/v3-utility-library/tree/master/markerclusterer

MazarD
  • 2,759
  • 2
  • 22
  • 33
0

Add small random numbers to the marker latitude and longitude.

This displaces the overlapping markers around their correct position. When zoomed in, the markers will separate. Smaller random numbers improve accuracy but more zooming in is needed. Also alter the marker icon or label to indicate it's overlapping.

In this example, four different markers are used. If there are more than 4 overlapping points, the slight randomization is added.

Example: http://waveneyramblers.org.uk/walks/next_eight_days

View source to see the JavaScript.

0

Here is a solution without using any libraries but just simple javascript as a workaround for the overlapping issue.

It opens an infowindow only on the markers which has more then 1 markers at the same lat and lng

var maplocations = [["1200€", "52.50752849999999", "13.471243500000014", "96063", "No", 1],
["12€", "52.50752849999999", "13.471243500000014", "198866", "No", 1],
["12€", "52.504747174113696", "13.420449523925754", "228262", "No", 1],
["888€", "52.5024031", "13.377901000000065", "228317", "No", 1]]

 function initMap() {

        var map = new google.maps.Map(document.getElementById('map'), {
            zoom: 10,
            center: new google.maps.LatLng(52.530339,13.347451),
            mapTypeId: google.maps.MapTypeId.ROADMAP
          });


         groupedMapList=[];
        for(var i=0;i<maplocations.length;i++){
            if(!groupedMapList.find(item => item[1] == maplocations[i][1] && item[2]== maplocations[i][2])){
                groupedMapList.push(maplocations[i])
            }else{
               let valueIndex = groupedMapList.findIndex(item => item[1] == maplocations[i][1] && item[2]== maplocations[i][2]);
               groupedMapList[valueIndex][5] = groupedMapList[valueIndex][5] + 1;
            }
        }

You will get a grouped list which needs to be mapped on the map. Add infowindow only to the items which are more than 1 - "groupedMapList[i][5]>1"

var groupedMapList = [ ["1200€", "52.50752849999999", "13.471243500000014", "96063", "No", 2], ["12€", "52.504747174113696", "13.420449523925754", "228262", "No", 1], ["888€", "52.5024031", "13.377901000000065", "228317", "No", 1]]

        var infowindow = new google.maps.InfoWindow();
        //   var bounds = new google.maps.LatLngBounds();
          var marker, i;
          var prevId;
          var prevMarker;

          for(i=0;i<groupedMapList.length;i++){

                marker = new google.maps.Marker({
                position: new google.maps.LatLng(parseFloat(groupedMapList[i][1]), parseFloat(groupedMapList[i][2])),
                label: {text: groupedMapList[i][0], color: "black"},
                map: map
                });

              google.maps.event.addListener(marker, 'click', (function(marker, i) {
              return function() {
                //reset previous marker

                if(prevMarker)
                {

                    var label = prevMarker.getLabel();
                    label.color="black";
                    prevMarker.setLabel(label); 
                    prevMarker.setZIndex();
                    infowindow.close();
                }

                if(groupedMapList[i][5] > 1){
                    let contentString = '<div id="content">'+ '<b>'+ groupedMapList[i][5] +' Apartments</b></div>'
                    infowindow.setContent(contentString);
                    infowindow.open(map, marker);
                }

                prevId = groupedMapList[i][3];
                prevMarker = this;

                var label = this.getLabel();
                label.color="white";
                this.setLabel(label); 
                this.setZIndex(1001);

              }

            })(marker, i));

        }

    }
Sitaram
  • 428
  • 9
  • 12