Google Maps MarkerCluster плюс Spiderfier - PullRequest
       94

Google Maps MarkerCluster плюс Spiderfier

1 голос
/ 04 августа 2020

Предыдущие вопросы и ответы предоставили отличный пример того, что я хочу делать с картой, но мне явно чего-то не хватает, когда я интегрирую части в свою страницу, так как я все время получаю сообщение об ошибке и не вижу где я ошибаюсь.

Предыдущие вопросы и ответы:

Перекрывающиеся указатели с MarkerClustererPlus и OverlappingMarkerSpiderfier

Я работаю над страницей для направленного маршрута с путевыми точками и сгруппированными маркерами на заданных расстояниях вдоль маршрута / ломаной линии. Он отлично работает как есть, но обледенением будут кластерные маркеры Spiderfied.

Вот мой код:

var geocoder;
var map;
var marker;
var gmarkers = [];
var markerCluster;
var METERS_TO_MILES = 0.000621371192;
var walked = (Math.round(25000 * 1609.344));

var jMarkers = [
  ['Vehicle1', 16.1, '#1'],
  ['Vehicle1', 16.1, '#1'],
  ['Vehicle3', 25.2, '#45' ]
];


//ICON
var iconImage = {
  url: 'https://maps.google.com/mapfiles/ms/micons/red.png',
  size: new google.maps.Size(25, 34), 
  origin: new google.maps.Point(0, 0), 
  anchor: new google.maps.Point(16, 34) 
};


//INFO WINDOW
var infowindow = new google.maps.InfoWindow({
  size: new google.maps.Size(150, 50)
});



//CREATE MARKER
function createMarker(latlng, label, team, html) {
  var contentString = '<b>' + label + '</b><br>' + team + '<br>' + html;
  var marker = new google.maps.Marker({
    position: latlng,
    map: map,
    icon: iconImage,
    title: label,
    zIndex: Math.round(latlng.lat() * -100000) << 5
  });

  marker.myname = label;
  gmarkers.push(marker);

  google.maps.event.addListener(marker, 'click', function() {
    infowindow.setContent(contentString);
    infowindow.open(map, marker);
  });
  return marker;
}


function initialize() {
  var latlng = new google.maps.LatLng(51.469768, 0.261950);
  var myOptions = {
    zoom: 9,
    maxZoom:16,
    center: latlng,
    mapTypeId: google.maps.MapTypeId.TERRAIN
  };

  map = new google.maps.Map(document.getElementById("map"), myOptions);


  google.maps.event.addListenerOnce(map, 'idle', function() {
    var oms = new OverlappingMarkerSpiderfier(map, {
      markersWontMove: true,
      markersWontHide: true,
          keepSpiderfied: true
        });
    });


  // Add a marker clusterer to manage the markers.
  markerCluster = new MarkerClusterer(map, [], {
    imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'
  });
  
  minClusterZoom = 14;
  markerCluster.setMaxZoom(minClusterZoom);


  var rendererOptions = {
    map: map,
    suppressMarkers: true,
  };

  directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);

  //waypoints
  var point1 = new google.maps.LatLng(51.679356, 0.124934);
  var point2 = new google.maps.LatLng(51.714827, -0.392763);
  var point3 = new google.maps.LatLng(51.494842, -0.494127);
  var point4 = new google.maps.LatLng(51.526885, -0.498285);

  var wps = [{
    location: point1,
    location: point2,
    location: point3,
    location: point4
  }];

  //START
  var org = new google.maps.LatLng(51.469768, 0.261950);

  //FINISH
  var dest = new google.maps.LatLng(51.469768, 0.261950);

  var request = {
    origin: org,
    destination: dest,
    waypoints: wps,
    travelMode: google.maps.DirectionsTravelMode.DRIVING,
  };

  directionsService = new google.maps.DirectionsService();
  directionsService.route(request, function(response, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      //SHOW ROUTE
      directionsDisplay.setDirections(response);

      //COPY POLY FROM DIRECTION SERVICE
      var polyline = new google.maps.Polyline({
        path: [],
        strokeColor: '#FF0000',
        strokeWeight: 1
      });

      var bounds = new google.maps.LatLngBounds();
      var lengthMeters = 0;
      var legs = response.routes[0].legs;
      for (i = 0; i < legs.length; i++) {
        var steps = legs[i].steps;
        for (j = 0; j < steps.length; j++) {
          var nextSegment = steps[j].path;
          for (k = 0; k < nextSegment.length; k++) {

            if (lengthMeters <= walked) {
              polyline.getPath().push(nextSegment[k]);
              if (polyline.getPath().getLength() > 1) {
                var lastPt = polyline.getPath().getLength() - 1;
                lengthMeters += google.maps.geometry.spherical.computeDistanceBetween(polyline.getPath().getAt(lastPt - 1), polyline.getPath().getAt(lastPt));
              }
            }
            bounds.extend(nextSegment[k]);

          }
        }
      }

      polyline.setMap(map);

      var i;
      for (i = 0; i < jMarkers.length; i++) {
        walked = 0;
        walked = (Math.round(jMarkers[i][1] * 1609.344));
        markerCluster.addMarker(createMarker(polyline.GetPointAtDistance(walked), jMarkers[i][0], jMarkers[i][2], (Math.round(walked * METERS_TO_MILES * 10) / 10) + ' miles'));
        }

        oms.addMarker(createMarker(polyline.GetPointAtDistance(walked), jMarkers[i][0], jMarkers[i][2], (Math.round(walked * METERS_TO_MILES * 10) / 10) + ' miles'));


      //GET THE TOTAL DISTANCE
      var distance = 0;
      //var METERS_TO_MILES = 0.000621371192;
      for (i = 0; i < response.routes[0].legs.length; i++) {
        //FOR EACH LEG GET THE DISTANCE AND ADD IT TO THE TOTAL
        distance += parseFloat(response.routes[0].legs[i].distance.value);
      }
alert(Math.round(distance * METERS_TO_MILES * 10) / 10 + ' miles');
    } else if (status == google.maps.DirectionsStatus.MAX_WAYPOINTS_EXCEEDED) {
      alert('Max waypoints exceeded');
    } else {
      alert('failed to get directions');
    }
  });
};
window.onload = function() {
  initialize();
};

/*********************************************************************\
*                                                                     *
* epolys.js                                          by Mike Williams *
* updated to API v3                                  by Larry Ross    *
*                                                                     *
* A Google Maps API Extension                                         *
*                                                                     *
* Adds various Methods to google.maps.Polygon and google.maps.Polyline *
*                                                                     *
* .Contains(latlng) returns true is the poly contains the specified   *
*                   GLatLng                                           *
*                                                                     *
* .Area()           returns the approximate area of a poly that is    *
*                   not self-intersecting                             *
*                                                                     *
* .Distance()       returns the length of the poly path               *
*                                                                     *
* .Bounds()         returns a GLatLngBounds that bounds the poly      *
*                                                                     *
* .GetPointAtDistance() returns a GLatLng at the specified distance   *
*                   along the path.                                   *
*                   The distance is specified in metres               *
*                   Reurns null if the path is shorter than that      *
*                                                                     *
* .GetPointsAtDistance() returns an array of GLatLngs at the          *
*                   specified interval along the path.                *
*                   The distance is specified in metres               *
*                                                                     *
* .GetIndexAtDistance() returns the vertex number at the specified    *
*                   distance along the path.                          *
*                   The distance is specified in metres               *
*                   Returns null if the path is shorter than that      *
*                                                                     *
* .Bearing(v1?,v2?) returns the bearing between two vertices          *
*                   if v1 is null, returns bearing from first to last *
*                   if v2 is null, returns bearing from v1 to next    *
*                                                                     *
*                                                                     *
***********************************************************************
*                                                                     *
*   This Javascript is provided by Mike Williams                      *
*   Blackpool Community Church Javascript Team                        *
*   http://www.blackpoolchurch.org/                                   *
*   http://econym.org.uk/gmap/                                        *
*                                                                     *
*   This work is licenced under a Creative Commons Licence            *
*   http://creativecommons.org/licenses/by/2.0/uk/                    *
*                                                                     *
***********************************************************************
*                                                                     *
* Version 1.1       6-Jun-2007                                        *
* Version 1.2       1-Jul-2007 - fix: Bounds was omitting vertex zero *
*                                add: Bearing                         *
* Version 1.3       28-Nov-2008  add: GetPointsAtDistance()           *
* Version 1.4       12-Jan-2009  fix: GetPointsAtDistance()           *
* Version 3.0       11-Aug-2010  update to v3                         *
*                                                                     *
\*********************************************************************/

// === first support methods that don't (yet) exist in v3
google.maps.LatLng.prototype.distanceFrom = function(newLatLng) {
  var EarthRadiusMeters = 6378137.0; // meters
  var lat1 = this.lat();
  var lon1 = this.lng();
  var lat2 = newLatLng.lat();
  var lon2 = newLatLng.lng();
  var dLat = (lat2 - lat1) * Math.PI / 180;
  var dLon = (lon2 - lon1) * Math.PI / 180;
  var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  var d = EarthRadiusMeters * c;
  return d;
}

google.maps.LatLng.prototype.latRadians = function() {
  return this.lat() * Math.PI / 180;
}

google.maps.LatLng.prototype.lngRadians = function() {
  return this.lng() * Math.PI / 180;
}

// === A method which returns the length of a path in metres ===
google.maps.Polygon.prototype.Distance = function() {
  var dist = 0;
  for (var i = 1; i < this.getPath().getLength(); i++) {
    dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i - 1));
  }
  return dist;
}

// === A method which returns a GLatLng of a point a given distance along the path ===
// === Returns null if the path is shorter than the specified distance ===
google.maps.Polygon.prototype.GetPointAtDistance = function(metres) {
  // some awkward special cases
  if (metres == 0) return this.getPath().getAt(0);
  if (metres < 0) return null;
  if (this.getPath().getLength() < 2) return null;
  var dist = 0;
  var olddist = 0;
  for (var i = 1;
    (i < this.getPath().getLength() && dist < metres); i++) {
    olddist = dist;
    dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i - 1));
  }
  if (dist < metres) {
    return null;
  }
  var p1 = this.getPath().getAt(i - 2);
  var p2 = this.getPath().getAt(i - 1);
  var m = (metres - olddist) / (dist - olddist);
  return new google.maps.LatLng(p1.lat() + (p2.lat() - p1.lat()) * m, p1.lng() + (p2.lng() - p1.lng()) * m);
}

// === A method which returns an array of GLatLngs of points a given interval along the path ===
google.maps.Polygon.prototype.GetPointsAtDistance = function(metres) {
  var next = metres;
  var points = [];
  // some awkward special cases
  if (metres <= 0) return points;
  var dist = 0;
  var olddist = 0;
  for (var i = 1;
    (i < this.getPath().getLength()); i++) {
    olddist = dist;
    dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i - 1));
    while (dist > next) {
      var p1 = this.getPath().getAt(i - 1);
      var p2 = this.getPath().getAt(i);
      var m = (next - olddist) / (dist - olddist);
      points.push(new google.maps.LatLng(p1.lat() + (p2.lat() - p1.lat()) * m, p1.lng() + (p2.lng() - p1.lng()) * m));
      next += metres;
    }
  }
  return points;
}

// === A method which returns the Vertex number at a given distance along the path ===
// === Returns null if the path is shorter than the specified distance ===
google.maps.Polygon.prototype.GetIndexAtDistance = function(metres) {
  // some awkward special cases
  if (metres == 0) return this.getPath().getAt(0);
  if (metres < 0) return null;
  var dist = 0;
  var olddist = 0;
  for (var i = 1;
    (i < this.getPath().getLength() && dist < metres); i++) {
    olddist = dist;
    dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i - 1));
  }
  if (dist < metres) {
    return null;
  }
  return i;
}

// === Copy all the above functions to GPolyline ===
google.maps.Polyline.prototype.Distance = google.maps.Polygon.prototype.Distance;
google.maps.Polyline.prototype.GetPointAtDistance = google.maps.Polygon.prototype.GetPointAtDistance;
google.maps.Polyline.prototype.GetPointsAtDistance = google.maps.Polygon.prototype.GetPointsAtDistance;
google.maps.Polyline.prototype.GetIndexAtDistance = google.maps.Polygon.prototype.GetIndexAtDistance;
html,
body,
#map,
#container {
  height: 100%;
  width: 100%;
  background: #000;
  padding: 0px;
  margin: 0px;
<div id="container">
  <div id="map"></div>
</div>

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

<script src="https://unpkg.com/@google/markerclustererplus@4.0.1/dist/markerclustererplus.min.js"></script>
<script src="https://jawj.github.io/OverlappingMarkerSpiderfier/bin/oms.min.js"></script>

1 Ответ

1 голос
/ 04 августа 2020

Я получаю ошибку javascript с вашим фрагментом кода: Uncaught ReferenceError: oms is not defined, потому что эта переменная является локальной для прослушивателя событий map idle.

Если я сделаю ее глобальной, но оставлю ее в прослушивателе событий idle, тогда я получаю другую ошибку (потому что oms не инициализируется при использовании).

Инициализация во встроенном состоянии решает проблему, но я считаю, что вы хотите добавить те же маркеры в oms, как и MarkerClusterer (если функциональность, которую вы пытаетесь реализовать, отличается от ожидаемой)

for (i = 0; i < jMarkers.length; i++) {
  walked = 0;
  walked = (Math.round(jMarkers[i][1] * 1609.344));
  var marker = createMarker(polyline.GetPointAtDistance(walked), jMarkers[i][0], jMarkers[i][2], (Math.round(walked * METERS_TO_MILES * 10) / 10) + ' miles');
  markerCluster.addMarker(marker);
  oms.addMarker(marker);
}

фрагмент рабочего кода:

var geocoder;
var map;
var oms;
var marker;
var gmarkers = [];
var markerCluster;
var METERS_TO_MILES = 0.000621371192;
var walked = (Math.round(25000 * 1609.344));

var jMarkers = [
  ['Vehicle1', 16.1, '#1'],
  ['Vehicle1', 16.1, '#1'],
  ['Vehicle3', 25.2, '#45']
];


//ICON
var iconImage = {
  url: 'https://maps.google.com/mapfiles/ms/micons/red.png',
  size: new google.maps.Size(25, 34),
  origin: new google.maps.Point(0, 0),
  anchor: new google.maps.Point(16, 34)
};


//INFO WINDOW
var infowindow = new google.maps.InfoWindow({
  size: new google.maps.Size(150, 50)
});



//CREATE MARKER
function createMarker(latlng, label, team, html) {
  var contentString = '<b>' + label + '</b><br>' + team + '<br>' + html;
  var marker = new google.maps.Marker({
    position: latlng,
    map: map,
    icon: iconImage,
    title: label,
    zIndex: Math.round(latlng.lat() * -100000) << 5
  });

  marker.myname = label;
  gmarkers.push(marker);

  google.maps.event.addListener(marker, 'click', function() {
    infowindow.setContent(contentString);
    infowindow.open(map, marker);
  });
  return marker;
}


function initialize() {
  var latlng = new google.maps.LatLng(51.469768, 0.261950);
  var myOptions = {
    zoom: 9,
    maxZoom: 16,
    center: latlng,
    mapTypeId: google.maps.MapTypeId.TERRAIN
  };

  map = new google.maps.Map(document.getElementById("map"), myOptions);

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

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

  minClusterZoom = 14;
  markerCluster.setMaxZoom(minClusterZoom);


  var rendererOptions = {
    map: map,
    suppressMarkers: true,
  };

  directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);

  //waypoints
  var point1 = new google.maps.LatLng(51.679356, 0.124934);
  var point2 = new google.maps.LatLng(51.714827, -0.392763);
  var point3 = new google.maps.LatLng(51.494842, -0.494127);
  var point4 = new google.maps.LatLng(51.526885, -0.498285);

  var wps = [{
    location: point1,
    location: point2,
    location: point3,
    location: point4
  }];

  //START
  var org = new google.maps.LatLng(51.469768, 0.261950);

  //FINISH
  var dest = new google.maps.LatLng(51.469768, 0.261950);

  var request = {
    origin: org,
    destination: dest,
    waypoints: wps,
    travelMode: google.maps.DirectionsTravelMode.DRIVING,
  };

  directionsService = new google.maps.DirectionsService();
  directionsService.route(request, function(response, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      //SHOW ROUTE
      directionsDisplay.setDirections(response);

      //COPY POLY FROM DIRECTION SERVICE
      var polyline = new google.maps.Polyline({
        path: [],
        strokeColor: '#FF0000',
        strokeWeight: 1
      });

      var bounds = new google.maps.LatLngBounds();
      var lengthMeters = 0;
      var legs = response.routes[0].legs;
      for (i = 0; i < legs.length; i++) {
        var steps = legs[i].steps;
        for (j = 0; j < steps.length; j++) {
          var nextSegment = steps[j].path;
          for (k = 0; k < nextSegment.length; k++) {

            if (lengthMeters <= walked) {
              polyline.getPath().push(nextSegment[k]);
              if (polyline.getPath().getLength() > 1) {
                var lastPt = polyline.getPath().getLength() - 1;
                lengthMeters += google.maps.geometry.spherical.computeDistanceBetween(polyline.getPath().getAt(lastPt - 1), polyline.getPath().getAt(lastPt));
              }
            }
            bounds.extend(nextSegment[k]);
          }
        }
      }

      polyline.setMap(map);

      var i;
      for (i = 0; i < jMarkers.length; i++) {
        walked = 0;
        walked = (Math.round(jMarkers[i][1] * 1609.344));
        var marker = createMarker(polyline.GetPointAtDistance(walked), jMarkers[i][0], jMarkers[i][2], (Math.round(walked * METERS_TO_MILES * 10) / 10) + ' miles');
        markerCluster.addMarker(marker);
        oms.addMarker(marker);
      }

      //GET THE TOTAL DISTANCE
      var distance = 0;
      //var METERS_TO_MILES = 0.000621371192;
      for (i = 0; i < response.routes[0].legs.length; i++) {
        //FOR EACH LEG GET THE DISTANCE AND ADD IT TO THE TOTAL
        distance += parseFloat(response.routes[0].legs[i].distance.value);
      }
      console.log(Math.round(distance * METERS_TO_MILES * 10) / 10 + ' miles');
    } else if (status == google.maps.DirectionsStatus.MAX_WAYPOINTS_EXCEEDED) {
      alert('Max waypoints exceeded');
    } else {
      alert('failed to get directions');
    }
  });
};
window.onload = function() {
  initialize();
};

/*********************************************************************\
*                                                                     *
* epolys.js                                          by Mike Williams *
* updated to API v3                                  by Larry Ross    *
*                                                                     *
* A Google Maps API Extension                                         *
*                                                                     *
* Adds various Methods to google.maps.Polygon and google.maps.Polyline *
*                                                                     *
* .Contains(latlng) returns true is the poly contains the specified   *
*                   GLatLng                                           *
*                                                                     *
* .Area()           returns the approximate area of a poly that is    *
*                   not self-intersecting                             *
*                                                                     *
* .Distance()       returns the length of the poly path               *
*                                                                     *
* .Bounds()         returns a GLatLngBounds that bounds the poly      *
*                                                                     *
* .GetPointAtDistance() returns a GLatLng at the specified distance   *
*                   along the path.                                   *
*                   The distance is specified in metres               *
*                   Reurns null if the path is shorter than that      *
*                                                                     *
* .GetPointsAtDistance() returns an array of GLatLngs at the          *
*                   specified interval along the path.                *
*                   The distance is specified in metres               *
*                                                                     *
* .GetIndexAtDistance() returns the vertex number at the specified    *
*                   distance along the path.                          *
*                   The distance is specified in metres               *
*                   Returns null if the path is shorter than that      *
*                                                                     *
* .Bearing(v1?,v2?) returns the bearing between two vertices          *
*                   if v1 is null, returns bearing from first to last *
*                   if v2 is null, returns bearing from v1 to next    *
*                                                                     *
*                                                                     *
***********************************************************************
*                                                                     *
*   This Javascript is provided by Mike Williams                      *
*   Blackpool Community Church Javascript Team                        *
*   http://www.blackpoolchurch.org/                                   *
*   http://econym.org.uk/gmap/                                        *
*                                                                     *
*   This work is licenced under a Creative Commons Licence            *
*   http://creativecommons.org/licenses/by/2.0/uk/                    *
*                                                                     *
***********************************************************************
*                                                                     *
* Version 1.1       6-Jun-2007                                        *
* Version 1.2       1-Jul-2007 - fix: Bounds was omitting vertex zero *
*                                add: Bearing                         *
* Version 1.3       28-Nov-2008  add: GetPointsAtDistance()           *
* Version 1.4       12-Jan-2009  fix: GetPointsAtDistance()           *
* Version 3.0       11-Aug-2010  update to v3                         *
*                                                                     *
\*********************************************************************/

// === first support methods that don't (yet) exist in v3
google.maps.LatLng.prototype.distanceFrom = function(newLatLng) {
  var EarthRadiusMeters = 6378137.0; // meters
  var lat1 = this.lat();
  var lon1 = this.lng();
  var lat2 = newLatLng.lat();
  var lon2 = newLatLng.lng();
  var dLat = (lat2 - lat1) * Math.PI / 180;
  var dLon = (lon2 - lon1) * Math.PI / 180;
  var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  var d = EarthRadiusMeters * c;
  return d;
}

google.maps.LatLng.prototype.latRadians = function() {
  return this.lat() * Math.PI / 180;
}

google.maps.LatLng.prototype.lngRadians = function() {
  return this.lng() * Math.PI / 180;
}

// === A method which returns the length of a path in metres ===
google.maps.Polygon.prototype.Distance = function() {
  var dist = 0;
  for (var i = 1; i < this.getPath().getLength(); i++) {
    dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i - 1));
  }
  return dist;
}

// === A method which returns a GLatLng of a point a given distance along the path ===
// === Returns null if the path is shorter than the specified distance ===
google.maps.Polygon.prototype.GetPointAtDistance = function(metres) {
  // some awkward special cases
  if (metres == 0) return this.getPath().getAt(0);
  if (metres < 0) return null;
  if (this.getPath().getLength() < 2) return null;
  var dist = 0;
  var olddist = 0;
  for (var i = 1;
    (i < this.getPath().getLength() && dist < metres); i++) {
    olddist = dist;
    dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i - 1));
  }
  if (dist < metres) {
    return null;
  }
  var p1 = this.getPath().getAt(i - 2);
  var p2 = this.getPath().getAt(i - 1);
  var m = (metres - olddist) / (dist - olddist);
  return new google.maps.LatLng(p1.lat() + (p2.lat() - p1.lat()) * m, p1.lng() + (p2.lng() - p1.lng()) * m);
}

// === A method which returns an array of GLatLngs of points a given interval along the path ===
google.maps.Polygon.prototype.GetPointsAtDistance = function(metres) {
  var next = metres;
  var points = [];
  // some awkward special cases
  if (metres <= 0) return points;
  var dist = 0;
  var olddist = 0;
  for (var i = 1;
    (i < this.getPath().getLength()); i++) {
    olddist = dist;
    dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i - 1));
    while (dist > next) {
      var p1 = this.getPath().getAt(i - 1);
      var p2 = this.getPath().getAt(i);
      var m = (next - olddist) / (dist - olddist);
      points.push(new google.maps.LatLng(p1.lat() + (p2.lat() - p1.lat()) * m, p1.lng() + (p2.lng() - p1.lng()) * m));
      next += metres;
    }
  }
  return points;
}

// === A method which returns the Vertex number at a given distance along the path ===
// === Returns null if the path is shorter than the specified distance ===
google.maps.Polygon.prototype.GetIndexAtDistance = function(metres) {
  // some awkward special cases
  if (metres == 0) return this.getPath().getAt(0);
  if (metres < 0) return null;
  var dist = 0;
  var olddist = 0;
  for (var i = 1;
    (i < this.getPath().getLength() && dist < metres); i++) {
    olddist = dist;
    dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i - 1));
  }
  if (dist < metres) {
    return null;
  }
  return i;
}

// === Copy all the above functions to GPolyline ===
google.maps.Polyline.prototype.Distance = google.maps.Polygon.prototype.Distance;
google.maps.Polyline.prototype.GetPointAtDistance = google.maps.Polygon.prototype.GetPointAtDistance;
google.maps.Polyline.prototype.GetPointsAtDistance = google.maps.Polygon.prototype.GetPointsAtDistance;
google.maps.Polyline.prototype.GetIndexAtDistance = google.maps.Polygon.prototype.GetIndexAtDistance;
  html,
body,
#map,
#container {
  height: 100%;
  width: 100%;
  background: #000;
  padding: 0px;
  margin: 0px;
<div id="container">
  <div id="map"></div>
</div>

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

<script src="https://unpkg.com/@google/markerclustererplus@4.0.1/dist/markerclustererplus.min.js"></script>
<script src="https://jawj.github.io/OverlappingMarkerSpiderfier/bin/oms.min.js"></script>
...