Infowindows on Overlapping Marker Spiderfier

560 Views Asked by At

I am using Google Maps API V3 with Marker Clusterer and Overlapping Marker Spiderfier. It is working quite well but I have an issue with the infowindows attached to each marker. When a group of markers are specified and an infowindow is opened with a click or mouseover, the infowindow is positioned relative to the true position of the marker and not the spiderfied position. Is there any way to get the infowindow to follow the spiderfier?

OMS is specified with:

var oms = new OverlappingMarkerSpiderfier(map, {
  markersWontMove: true,
  markersWontHide: true,
  keepSpiderfied: true,
  legWeight: 1
    });

And the infowindows with:

google.maps.event.addListener(marker, 'click', function(marker, e) {
  return function() {
    var myHTML = e.feature.getProperty('html');
    boxText.innerHTML = '<div class="ib">' + myHTML + '</div>';
    infowindow.setPosition(e.feature.getGeometry().get());
    infowindow.setOptions({
      pixelOffset: new google.maps.Size(0, -42)
    });
    infowindow.open(map);
  };
}(marker, e));

https://jsfiddle.net/groxmzej/

1

There are 1 best solutions below

0
On BEST ANSWER

Use the marker reference as the "anchor" in the call to open on the InfoWindow

documentation

open([options, anchor])
Parameters:

  • options: InfoWindowOpenOptions|Map|StreetViewPanorama optional Either an InfoWindowOpenOptions object (recommended) or the map|panorama on which to render this InfoWindow.
  • anchor: MVCObject optional The anchor to which this InfoWindow will be positioned. If the anchor is non-null, the InfoWindow will be positioned at the top-center of the anchor. The InfoWindow will be rendered on the same map or panorama as the anchor (when available). Return Value: None
    Opens this InfoWindow on the given map. Optionally, an InfoWindow can be associated with an anchor. In the core API, the only anchor is the Marker class. However, an anchor can be any MVCObject that exposes a LatLng position property and optionally a Point anchorPoint property for calculating the pixelOffset (see InfoWindowOptions). The anchorPoint is the offset from the anchor's position to the tip of the InfoWindow. It is recommended to use the InfoWindowOpenOptions interface as the single argument for this method. To prevent changing browser focus on open, set InfoWindowOpenOptions.shouldFocus to false.

So change your code that opens the infowindow from:

infowindow.setPosition(e.feature.getGeometry().get());
infowindow.setOptions({
  pixelOffset: new google.maps.Size(0, -42)
});
infowindow.open(map);

To:

infowindow.open(map, marker);

proof of concept fiddle

screenshot showing infowindow open on spiderified marker

code snippet:

var geoJson = {
  "type": "FeatureCollection",
  "features": [{
      "type": "Feature",
      "properties": {
        "name": "Arthur George Melhuish",
        "html": "<h2>Arthur George Melhuish</h2>Born 12 Jan 1909 in 2 Fore St, Tiverton<br><span class=addedby>Added by Admin</span>"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [-3.48882160, 50.90258030]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "name": "Harold Edward Melhuish",
        "html": "<h2>Harold Edward Melhuish</h2>Born 30 Jun 1903 in 2 Fore Street, Tiverton<br><span class=addedby>Added by Admin</span>"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [-3.48882160, 50.90258030]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "name": "John Norman Melhuish",
        "html": "<h2>John Norman Melhuish</h2>Born 3 Jan 1905 in 2 Fore Street, Tiverton<br><span class=addedby>Added by Admin</span>"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [-3.48882160, 50.90258030]
      }
    },

  ]
};
var map = null;
var bounds = new google.maps.LatLngBounds();

var boxText = document.createElement("div");

var infowindow = new google.maps.InfoWindow({
  content: boxText,
  disableAutoPan: false,
  zIndex: null,
  alignBottom: true,
  enableEventPropagation: false,
  boxStyle: {
    padding: "6px",
    border: "1px solid #666",
    background: "#fff",
    width: "240px"
  }
});



function initialize() {
  var mapOptions = {
    center: new google.maps.LatLng(51, -3.5),
    zoom: 9
  };
  map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
  google.maps.event.addListenerOnce(map, 'idle', function() {
    var oms = new OverlappingMarkerSpiderfier(map, {
      markersWontMove: true,
      markersWontHide: true,
      keepSpiderfied: true,
      legWeight: 1
    });

    oms.addListener('spiderfy', function(spidered, unspidered) {
      for (var i = 0; i < spidered.length; i++) {
        spidered[i].setLabel("");
        spidered[i].setOptions({
          zIndex: i
        });
      }
    });
    oms.addListener('unspiderfy', function(spidered, unspidered) {
      for (var i = 0; i < spidered.length; i++) {
        spidered[i].setLabel("" + (i + 1));
        spidered[i].setOptions({
          zIndex: i
        });
      }
    });

    google.maps.event.addListener(map.data, 'addfeature', function(e) {
      if (e.feature.getGeometry().getType() === 'Point') {
        var marker = new google.maps.Marker({
          position: e.feature.getGeometry().get(),
          /*title: e.feature.getProperty('name'),*/
          map: map
        });

        google.maps.event.addListener(marker, 'mouseover', function(marker, e) {
          return function() {
            var myHTML = e.feature.getProperty('html');
            boxText.innerHTML = '<div class="ib">' + myHTML + '</div>';
            infowindow.open(map, marker);
          };
        }(marker, e));

        google.maps.event.addListener(marker, 'click', function(marker, e) {
          return function() {
            var myHTML = e.feature.getProperty('html');
            boxText.innerHTML = '<div class="ib">' + myHTML + '</div>';
            infowindow.open(map, marker);
          };
        }(marker, e));


        oms.addMarker(marker);
        google.maps.event.addListener(map, 'idle', function() {
          var markersNear = oms.markersNearMarker(marker, false);
          if (markersNear.length > 0) {
            marker.setLabel("" + (markersNear.length + 1));
          }
          marker.setOptions({
            zIndex: markersNear.length
          });
        });
      }
    });
    layer = map.data.addGeoJson(geoJson);
    map.data.setMap(null);
    google.maps.event.addListener(map, "click", function() {
      infowindow.close();
    });
  });

}

google.maps.event.addDomListener(window, 'load', initialize);
#map_canvas {
  position: relative;
  width: 100%;
  height: calc(95vh)
}

.ib {
  line-height: 18px
}

.ib h2 {
  margin: 0;
  line-height: 28px
}

.addedby {
  float: right;
  color: #999;
  margin-top: 1em
}
<!DOCTYPE HTML>
<html>

<head>
  <meta charset="utf-8" />

  <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>

  <script src="https://jawj.github.io/OverlappingMarkerSpiderfier/bin/oms.min.js"></script>

</head>

<body>

  <div id="map_canvas"></div>

</body>

</html>