Google directions route - marker at midpoint

自作多情 提交于 2020-04-18 08:41:55

问题


How can I add a clickable marker in the middle of rendered route, which would then display a info window with custom data, because a info window can't be directly added to directions renderer?

 function loadRoute0() {
  var request0 = {
    origin: new google.maps.LatLng(46.56300788, 15.62779705),
    destination: new google.maps.LatLng(46.55953332, 15.62616729),
    travelMode: google.maps.TravelMode.WALKING
  };

  directionsService.route(request0, function(result, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      var renderer = new google.maps.DirectionsRenderer({
        polylineOptions: {
          strokeColor: "#00FF00"
        },
        suppressMarkers: true,
        map: map
      });
      renderer.setDirections(result);
    }
  });
 }

I read that we can use step, but I'm not sure how to implement that.

 marker.setPosition(myRoute.steps[i].start_location);

回答1:


To calculate the midpoint of your route:

  1. capture the entire route returned from the directions service
polyline.setPath([]);
var route = result.routes[0];

var path = result.routes[0].overview_path;
var legs = result.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++) {
      polyline.getPath().push(nextSegment[k]);
    }
  }
}
  1. compute its length
function computeTotalDistance(result) {
  totalDist = 0;
  totalTime = 0;
  var myroute = result.routes[0];
  for (i = 0; i < myroute.legs.length; i++) {
    totalDist += myroute.legs[i].distance.value;
    totalTime += myroute.legs[i].duration.value;
  }
  putMarkerOnRoute(50);

  totalDist = totalDist / 1000.
  document.getElementById("total").innerHTML = "total distance is: " + totalDist + " km<br>total time is: " + (totalTime / 60).toFixed(2) + " minutes";
}
  1. find the point at 50% of that length (one option for doing that would be to use the GetPointAtDistance function from the epoly library, ported to the v3 API).
function putMarkerOnRoute(percentage) {
  var distance = (percentage / 100) * totalDist;
  var time = ((percentage / 100) * totalTime / 60).toFixed(2);
  if (!marker) {
    marker = createMarker(polyline.GetPointAtDistance(distance), "time: " + time, "marker");
  } else {
    marker.setPosition(polyline.GetPointAtDistance(distance));
    marker.setTitle("time:" + time);
  }
}

proof of concept fiddle

code snippet:

function loadRoute0() {
  var request0 = {
    origin: new google.maps.LatLng(46.56300788, 15.62779705),
    destination: new google.maps.LatLng(46.55953332, 15.62616729),
    travelMode: google.maps.TravelMode.WALKING
  };

  directionsService.route(request0, function(result, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      var renderer = new google.maps.DirectionsRenderer({
        polylineOptions: {
          strokeColor: "#00FF00"
        },
        suppressMarkers: true,
        map: map
      });
      renderer.setDirections(result);
      polyline.setPath([]);
      var route = result.routes[0];

      var path = result.routes[0].overview_path;
      var legs = result.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++) {
            polyline.getPath().push(nextSegment[k]);
          }
        }
      }
      computeTotalDistance(result);
    }
  });
}
var directionsService, map, marker, polyline, infowindow;

function initialize() {
  map = new google.maps.Map(
    document.getElementById("map_canvas"), {
      center: new google.maps.LatLng(37.4419, -122.1419),
      zoom: 13,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    });
  polyline = new google.maps.Polyline({
    path: [],
    strokeColor: '#FF0000',
    strokeWeight: 3
  });
  infowindow = new google.maps.InfoWindow();
  directionsService = new google.maps.DirectionsService();
  loadRoute0();
}
google.maps.event.addDomListener(window, "load", initialize);
var totalDist = 0;
var totalTime = 0;

function computeTotalDistance(result) {
  totalDist = 0;
  totalTime = 0;
  var myroute = result.routes[0];
  for (i = 0; i < myroute.legs.length; i++) {
    totalDist += myroute.legs[i].distance.value;
    totalTime += myroute.legs[i].duration.value;
  }
  putMarkerOnRoute(50);

  totalDist = totalDist / 1000.
  document.getElementById("total").innerHTML = "total distance is: " + totalDist + " km<br>total time is: " + (totalTime / 60).toFixed(2) + " minutes";
}

function putMarkerOnRoute(percentage) {
  var distance = (percentage / 100) * totalDist;
  var time = ((percentage / 100) * totalTime / 60).toFixed(2);
  if (!marker) {
    marker = createMarker(polyline.GetPointAtDistance(distance), "time: " + time, "midpoint");
  } else {
    marker.setPosition(polyline.GetPointAtDistance(distance));
    marker.setTitle("time:" + time);
  }
  google.maps.event.trigger(marker, 'click');
}

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

  google.maps.event.addListener(marker, 'click', function() {
    infowindow.setContent(contentString + "<br>" + marker.getPosition().toUrlValue(6));
    infowindow.open(map, marker);
  });
  return marker;
}
// modified from epoly http://econym.org.uk/gmap/epoly.htm
// (ported to v3)
// === 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.Polyline.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 += google.maps.geometry.spherical.computeDistanceBetween(this.getPath().getAt(i), 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);
}
html,
body {
  height: 100%;
  width: 100%;
  margin: 0px;
  padding: 0px;
}

#map_canvas {
  height: 90%;
  width: 100%;
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div id="total"></div>
<div id="map_canvas"></div>


来源:https://stackoverflow.com/questions/50844421/google-directions-route-marker-at-midpoint

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!