如何沿折线从给定百分比返回 latLng 值?我花了一天时间使用插值和单个节点。它们是否有一个更简单的功能可以让咕噜声起作用?
谷歌地图 API v3 谢谢!
如何沿折线从给定百分比返回 latLng 值?我花了一天时间使用插值和单个节点。它们是否有一个更简单的功能可以让咕噜声起作用?
谷歌地图 API v3 谢谢!
http://www.geocodezip.com/scripts/v3_epoly.js
为移植到 v3 的 Google Maps Javascript API v2 编写。 v2 版本的文档
有这两种方法:
这应该有效(如果您包含该脚本并且您的折线变量是“折线”):
var latlng = polyline.GetPointAtDistance(polyline.Distance()*(desired percentage)/100);
当然,如果您的折线长度没有变化,那么每次您想在折线上找到一个点时使用它来计算长度会更有效。
var polylength = polyline.Distance();
var latlng = polylength*(desired percentage)/100);
代码片段:
var directionDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
var polyline = null;
var marker;
var infowindow;
function createMarker(latlng, label, html) {
// alert("createMarker("+latlng+","+label+","+html+","+color+")");
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,
contentString: contentString
});
marker.myname = label;
// gmarkers.push(marker);
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(this.contentString);
infowindow.open(map, marker);
});
return marker;
}
var myLatLng = null;
var lat;
var lng;
var zoom = 2;
var maptype;
function initialize() {
infowindow = new google.maps.InfoWindow();
myLatLng = new google.maps.LatLng(37.422104808, -122.0838851);
maptype = google.maps.MapTypeId.ROADMAP;
// If there are any parameters at eh end of the URL, they will be in location.search
// looking something like "?marker=3"
// skip the first character, we are not interested in the "?"
var query = location.search.substring(1);
// split the rest at each "&" character to give a list of "argname=value" pairs
var pairs = query.split("&");
for (var i = 0; i < pairs.length; i++) {
// break each pair at the first "=" to obtain the argname and value
var pos = pairs[i].indexOf("=");
var argname = pairs[i].substring(0, pos).toLowerCase();
var value = pairs[i].substring(pos + 1);
// process each possible argname - use unescape() if theres any chance of spaces
if (argname == "filename") {
filename = unescape(value);
}
if (argname == "lat") {
lat = parseFloat(value);
}
if (argname == "lng") {
lng = parseFloat(value);
}
if (argname == "start") {
document.getElementById("start").value = decodeURI(value);
}
if (argname == "end") {
document.getElementById("end").value = decodeURI(value);
}
if (argname == "time") {
document.getElementById("time").value = decodeURI(value);
// putMarkerOnRoute(parseFloat(document.getElementById('time').value));
}
if (argname == "zoom") {
zoom = parseInt(value);
}
if (argname == "type") {
// from the v3 documentation 8/24/2010
// HYBRID This map type displays a transparent layer of major streets on satellite images.
// ROADMAP This map type displays a normal street map.
// SATELLITE This map type displays satellite images.
// TERRAIN This map type displays maps with physical features such as terrain and vegetation.
if (value == "m") {
maptype = google.maps.MapTypeId.ROADMAP;
}
if (value == "k") {
maptype = google.maps.MapTypeId.SATELLITE;
}
if (value == "h") {
maptype = google.maps.MapTypeId.HYBRID;
}
if (value == "t") {
maptype = google.maps.MapTypeId.TERRAIN;
}
}
}
if (!isNaN(lat) && !isNaN(lng)) {
myLatLng = new google.maps.LatLng(lat, lng);
}
var myOptions = {
zoom: zoom,
center: myLatLng,
mapTypeId: maptype
};
directionsDisplay = new google.maps.DirectionsRenderer({
suppressMarkers: true
});
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
polyline = new google.maps.Polyline({
path: [],
strokeColor: '#FF0000',
strokeWeight: 3
});
directionsDisplay.setMap(map);
calcRoute();
}
function calcRoute() {
var start = document.getElementById("start").value;
var end = document.getElementById("end").value;
var travelMode = google.maps.DirectionsTravelMode.DRIVING
var request = {
origin: start,
destination: end,
travelMode: travelMode
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
polyline.setPath([]);
var bounds = new google.maps.LatLngBounds();
startLocation = new Object();
endLocation = new Object();
directionsDisplay.setDirections(response);
var route = response.routes[0];
var summaryPanel = document.getElementById("directions_panel");
summaryPanel.innerHTML = "";
// For each route, display summary information.
var path = response.routes[0].overview_path;
var legs = response.routes[0].legs;
for (i = 0; i < legs.length; i++) {
if (i == 0) {
startLocation.latlng = legs[i].start_location;
startLocation.address = legs[i].start_address;
// marker = google.maps.Marker({map:map,position: startLocation.latlng});
// marker = createMarker(legs[i].start_location,"start",legs[i].start_address,"green");
}
endLocation.latlng = legs[i].end_location;
endLocation.address = legs[i].end_address;
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]);
bounds.extend(nextSegment[k]);
}
}
}
polyline.setMap(map);
computeTotalDistance(response);
putMarkerOnRoute(parseFloat(document.getElementById('percent').value));
} else {
alert("directions response " + status);
}
});
}
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;
}
totalDist = totalDist / 1000.
document.getElementById("total").innerHTML = "total distance is: " + totalDist + " km<br>total time is: " + (totalTime / 60).toFixed(2) + " minutes<br>average speed is: " + (totalDist / (totalTime / 3600)).toFixed(2) + " kph";
document.getElementById("totalTime").value = (totalTime / 60.).toFixed(2);
}
function putMarkerOnRoute(percent) {
if (percent > 100) {
percent = 100;
document.getElementById('percent').value = percent;
}
var distance = percent / 100 * totalDist * 1000;
// time = ((percentage/100) * totalTIme/60).toFixed(2);
// alert("Time:"+time+" totalTime:"+totalTime+" totalDist:"+totalDist+" dist:"+distance);
if (!marker) {
marker = createMarker(polyline.GetPointAtDistance(distance), "percent: " + percent, "marker");
} else {
marker.setPosition(polyline.GetPointAtDistance(distance));
marker.setTitle("percent:" + percent);
marker.contentString = "<b>percent: " + percent + "</b><br>distance: " + (distance / 1000).toFixed(2) + " km<br>marker";
google.maps.event.trigger(marker, "click");
}
}
google.maps.event.addDomListener(window, 'load', initialize);
// from epoly_v3.js
// modified to use geometry library for length of line segments
// === 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 {
height: 100%
}
body {
height: 100%;
margin: 0px;
padding: 0px
}
<!-- Replace the value of the key parameter with your own API key. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=geometry"></script>
<div id="tools">
start:
<input type="text" name="start" id="start" value="Hyderabad" /> end:
<input type="text" name="end" id="end" value="Bangalore" />
<input type="submit" onclick="calcRoute();" /><br /> percentage:
<input type="text" name="percent" id="percent" value="0" />
<input type="submit" onclick="putMarkerOnRoute(parseFloat(document.getElementById('percent').value));" /> total time:<input type="text" name="totalTime" id="totalTime" value="0" />
</div>
<div id="map_canvas" style="float:left;width:70%;height:100%;"></div>
<div id="control_panel" style="float:right;width:30%;text-align:left;padding-top:20px">
<div id="directions_panel" style="margin:20px;background-color:#FFEE77;"></div>
<div id="total"></div>
</div>