简体   繁体   中英

Google maps, route with multiple distance markers and clustering

I came across a previous question (Rocket Ronnie) and answer (Geocodezip) from a few years ago which I've successfully updated to place multiple makers at separate distances along a given route.

Google maps draw distance traveled polyline

The next step which I'm having issues with is adding clustering. I'm new to Google mapping, I've used the Google clustering examples and see how they work, but can't work out how to combine the two. Any guidance or pointers would be hugely appreciated. Thanks in advance.

 var geocoder; var map; var marker; var gmarkers = []; var METERS_TO_MILES = 0.000621371192; var walked = (Math.round(550 * 1609.344)); var jMarkers = [ ['Craig Smith', 16], ['Bob Smith', 36], ['John Jones', 76], ['John Jones', 75], ['Brett Jones', 123], ['John Peterson', 145], ['John Smith', 175] ]; //ICON var iconImage = { url: 'https://maps.google.com/mapfiles/ms/micons/red.png', size: new google.maps.Size(25, 34), //MARKER SIZE (WxH) origin: new google.maps.Point(0, 0), //MARKER ORIGIN anchor: new google.maps.Point(16, 34) //MARKER ANCHOR }; //INFO WINDOW var infowindow = new google.maps.InfoWindow({ size: new google.maps.Size(150, 50) }); //CREATE MARKER function createMarker(latlng, label, html) { var contentString = '<b>' + label + '</b><br>' + html; var marker = new google.maps.Marker({ position: latlng, map: map, icon: iconImage, title: label, zIndex: Math.round(latlng.lat() * -100000) << 5 }); var markerCluster = new MarkerClusterer(map, marker, {imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'}); } 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.555967, -0.279736); var myOptions = { zoom: 9, center: latlng, mapTypeId: google.maps.MapTypeId.TERRAIN }; map = new google.maps.Map(document.getElementById("map"), myOptions); var rendererOptions = { map: map, suppressMarkers: true, }; directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions); //waypoints var point1 = new google.maps.LatLng(48.858469, 2.294353); var wps = [ {location: point1} ]; //START var org = new google.maps.LatLng(51.513872, -0.098329); //FINISH var dest = new google.maps.LatLng(45.465361, 9.191464); var request = { origin: org, destination: dest, waypoints: wps, travelMode: google.maps.DirectionsTravelMode.WALKING, }; 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: 3 }); 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); map.fitBounds(bounds); var i; for (i = 0; i < jMarkers.length; i++) { walked = 0; walked = (Math.round(jMarkers[i][1] * 1609.344)); createMarker(polyline.GetPointAtDistance(walked), jMarkers[i][0], (Math.round(walked * METERS_TO_MILES * 10) / 10) + ' miles'); } //ADD MARKER TO NEW POLYLINE AT 'X' DISTANCE // createMarker(polyline.GetPointAtDistance(walked), "You are here", (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); } } 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>

Related question: I am trying to add marker clusters to my google maps script

Proof of concept fiddle fixing your syntax errors, creating the MarkerClusterer at the beginning and adding the markers to it when they are returned from the createMarker function.

function initialize() {
  var latlng = new google.maps.LatLng(51.555967, -0.279736);
  var myOptions = {
    zoom: 9,
    center: latlng,
    mapTypeId: google.maps.MapTypeId.TERRAIN
  };

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

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

Then in your loop that creates the markers:

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], (Math.round(walked * METERS_TO_MILES * 10) / 10) + ' miles'));
}

结果地图的屏幕截图

code snippet:

 var geocoder; var map; var marker; var gmarkers = []; var markerCluster; var METERS_TO_MILES = 0.000621371192; var walked = (Math.round(550 * 1609.344)); var jMarkers = [ ['Craig Smith', 16], ['Bob Smith', 36], ['John Jones', 76], ['John Jones', 75], ['Brett Jones', 123], ['John Peterson', 145], ['John Smith', 175] ]; //ICON var iconImage = { url: 'https://maps.google.com/mapfiles/ms/micons/red.png', size: new google.maps.Size(25, 34), //MARKER SIZE (WxH) origin: new google.maps.Point(0, 0), //MARKER ORIGIN anchor: new google.maps.Point(16, 34) //MARKER ANCHOR }; //INFO WINDOW var infowindow = new google.maps.InfoWindow({ size: new google.maps.Size(150, 50) }); //CREATE MARKER function createMarker(latlng, label, html) { var contentString = '<b>' + label + '</b><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.555967, -0.279736); var myOptions = { zoom: 9, center: latlng, mapTypeId: google.maps.MapTypeId.TERRAIN }; map = new google.maps.Map(document.getElementById("map"), myOptions); // Add a marker clusterer to manage the markers. markerCluster = new MarkerClusterer(map, [], { imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m' }); var rendererOptions = { map: map, suppressMarkers: true, }; directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions); //waypoints var point1 = new google.maps.LatLng(48.858469, 2.294353); var wps = [{ location: point1 }]; //START var org = new google.maps.LatLng(51.513872, -0.098329); //FINISH var dest = new google.maps.LatLng(45.465361, 9.191464); var request = { origin: org, destination: dest, waypoints: wps, travelMode: google.maps.DirectionsTravelMode.WALKING, }; 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: 3 }); 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], (Math.round(walked * METERS_TO_MILES * 10) / 10) + ' miles')); } //ADD MARKER TO NEW POLYLINE AT 'X' DISTANCE // createMarker(polyline.GetPointAtDistance(walked), "You are here", (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); } } 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://unpkg.com/@google/markerclustererplus@4.0.1/dist/markerclustererplus.min.js"></script> <.-- Replace the value of the key parameter with your own API key: --> <script src="https.//maps.googleapis?com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap"> </script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM