Gad*_*ady 5 javascript google-maps google-maps-api-3
我正在寻找一种纯粹的(或尽可能纯的)Google Maps JavaScript API V3解决方案,以便为我的Google地图应用添加驱动时多边形功能.
基本上工作流程是用户单击地图上的标记或点,并在标记/点周围生成多边形,指示您可以在任何方向上在5分钟内驾驶的区域.
我不确定是否有可能将其作为纯粹的Google Maps API解决方案来实现,因为它需要使用随机路由向Directions Service发出太多电话,然后任何不在时间阈值范围内的电话都会被丢弃.不确定这是否可行或者最好的方法是什么.可能有必要为此使用一些后端处理,但我想首先排除所有其他选项,但欢迎后端解决方案的任何示例.
非常感谢任何帮助,建议或示例.以下是我遇到的一些示例,但它们要么不是纯Google Maps API解决方案,要么不使用驱动时间:
Google Maps Utility Library示例 - 在您点击的点周围绘制1,2和3分钟的驱动时间多边形,但它使用Esri的示例地理处理服务来运行计算并生成多边形几何体,因此这对我来说不起作用要求.
30英里的方向 - 它是一个纯粹的Google Maps API解决方案,使用Directions API并绘制一个漂亮的多边形,但它不需要将驱动时间计算在内,只需要距离点30英里即可.
Mapnificent - 似乎是一个纯粹的Google Maps API解决方案,他们有一个API,但他们正在处理从公共交通数据中提取的公共交通时间,而不是交通时间.因此,当您增加时间时"打开"的区域表示您可以在指定时间内从公共交通点开始.我想要这个,但有驾驶时间而不是过境时间.
你所说的“ 30 英里方向”是我的混搭,尽管它很旧并且是用 V2 API 编写的。您可以使用与 mashup 相同的原理,即围绕起点计算一个圆并将其点作为目的地,然后对于每条路线,当达到所需的行驶时间时将其切断。
原始链接已失效(下面的代码片段)
在该示例中,函数shortAndShow() 切断了超过30 英里的路线部分。由于 30 英里目标圈具有直线半径,因此不太可能到达,因为道路有弯道,因此您在到达蓝色圆圈边缘之前就到达了 30 英里。您可以执行相同的操作,但根据行驶时间而不是距离来切断路线。
性能将取决于您设置可能的目标点的沿圆周的间隔(以度为单位)。每 1 度的尝试将比每 10 度的尝试多 10 倍的请求(默认为 30 度)。
代码片段:
var map;
var container;
var zoom = 9;
var centerPoint = new google.maps.LatLng(35.149534, -90.04898);
var dirService = new google.maps.DirectionsService();
var centerMarker;
var circleMarkers = Array();
var circlePoints = Array();
var drivePolyPoints = Array();
var searchPolygon, drivePolygon;
var distToDrive = 30; // miles
var pointInterval = 30;
var searchPoints = [];
var polyline;
var polylines = [];
var redIcon8 = "https://maps.gstatic.com/intl/en_us/mapfiles/markers2/measle.png";
function initialize() {
map = new google.maps.Map(
document.getElementById("map_canvas"), {
center: centerPoint,
zoom: 9,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
google.maps.event.addListener(map, "click", mapClick);
}
google.maps.event.addDomListener(window, "load", initialize);
function mapClick(evt) {
// map.clearOverlays();
circleMarkers = Array();
if (!centerMarker) {
centerMarker = new google.maps.Marker({
position: evt.latLng,
map: map
});
} else {
centerMarker.setMap(null);
centerMarker.setPosition(evt.latLng);
}
centerMarker.setMap(map);
searchPoints = getCirclePoints(evt.latLng, distToDrive);
drivePolyPoints = Array();
getDirections();
}
function getCirclePoints(center, radius) {
var bounds = new google.maps.LatLngBounds();
var circlePoints = Array();
var searchPoints = Array();
with(Math) {
var rLat = (radius / 3963.189) * (180 / PI); // miles
var rLng = rLat / cos(center.lat() * (PI / 180));
for (var a = 0; a < 361; a++) {
var aRad = a * (PI / 180);
var x = center.lng() + (rLng * cos(aRad));
var y = center.lat() + (rLat * sin(aRad));
var point = new google.maps.LatLng(parseFloat(y), parseFloat(x), true);
bounds.extend(point);
circlePoints.push(point);
if (a % pointInterval == 0) {
searchPoints.push(point);
}
}
}
searchPolygon = new google.maps.Polygon({
paths: circlePoints,
strokeColor: '#0000ff',
strokeWeight: 1,
strokeOpacity: 1,
fillColor: '#0000ff',
fillOpacity: 0.2
});
searchPolygon.setMap(map);
map.fitBounds(bounds);
return searchPoints;
}
function getDirections() {
if (!searchPoints.length) {
return;
}
var to = searchPoints.shift();
var request = {
origin: centerMarker.getPosition(),
destination: to,
travelMode: google.maps.TravelMode.DRIVING
};
dirService.route(request, function(result, status) {
if (status == google.maps.DirectionsStatus.OK) {
var distance = parseInt(result.routes[0].legs[0].distance.value / 1609);
var duration = parseFloat(result.routes[0].legs[0].duration.value / 3600).toFixed(2);
var path = result.routes[0].overview_path;
var legs = result.routes[0].legs;
if (polyline && polyline.setPath) {
polyline.setPath([]);
} else {
polyline = new google.maps.Polyline({
path: [],
// map: map,
strokeColor: "#FF0000",
strokeOpacity: 1
});
}
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]);
// bounds.extend(nextSegment[k]);
}
}
}
// polyline.setMap(map);
shortenAndShow(polyline);
getDirections();
} else {
console.log("Directions request failed, status=" + status + " [from:" + request.origin + " to:" + request.destination + "]");
getDirections();
}
});
}
function shortenAndShow(polyline) {
var distToDriveM = distToDrive * 1609;
var dist = 0;
var cutoffIndex = 0;
var copyPoints = Array();
for (var n = 0; n < polyline.getPath().getLength() - 1; n++) {
dist += google.maps.geometry.spherical.computeDistanceBetween(polyline.getPath().getAt(n), polyline.getPath().getAt(n + 1));
//GLog.write(dist + ' - ' + distToDriveM);
if (dist < distToDriveM) {
copyPoints.push(polyline.getPath().getAt(n));
} else {
break;
}
}
var lastPoint = copyPoints[copyPoints.length - 1];
var newLine = new google.maps.Polyline({
path: copyPoints,
strokeColor: '#ff0000',
strokeWeight: 2,
strokeOpacity: 1
});
newLine.setMap(map);
polylines.push(newLine);
drivePolyPoints.push(lastPoint);
addBorderMarker(lastPoint, dist)
if (drivePolyPoints.length > 3) {
if (drivePolygon) {
drivePolygon.setMap(null);
}
drivePolygon = new google.maps.Polygon({
paths: drivePolyPoints,
strokeColor: '#00ff00',
strokeWeight: 1,
strokeOpacity: 1,
fillColor: '#00ff00',
fillOpacity: 0.4
});
drivePolygon.setMap(map);
}
}
function addBorderMarker(pt, d) {
var str = pt.lat().toFixed(6) + ',' + pt.lng().toFixed(6) + ' - Driving Distance: ' + (d / 1609).toFixed(2) + ' miles';
var marker = new google.maps.Marker({
position: pt,
icon: redIcon8,
title: str
});
circleMarkers.push(marker);
marker.setMap(map);
}
function clearOverlays() {
for (var i = 0; i < circleMarkers.length; i++) {
circleMarkers[i].setMap(null);
}
circleMarkers = [];
for (var i = 0; i < circlePoints.length; i++) {
circlePoints[i].setMap(null);
}
circlePoints = [];
for (var i = 0; i < polylines.length; i++) {
polylines[i].setMap(null);
}
polylines = [];
if (searchPolygon && searchPolygon.setMap) searchPolygon.setMap(null);
if (drivePolygon && drivePolygon.setMap) drivePolygon.setMap(null);
if (centerMarker && centerMarker.setMap) centerMarker.setMap(null);
}Run Code Online (Sandbox Code Playgroud)
html,
body,
#map_canvas {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}Run Code Online (Sandbox Code Playgroud)
<a href="#" onclick="clearOverlays();">Clear</a> |
<a href="#" onclick="pointInterval=30;clearOverlays();">interval 30 (default)</a> |
<a href="#" onclick="pointInterval=20;clearOverlays();">interval 20</a> |
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry"></script>
<div id="map_canvas"></div>Run Code Online (Sandbox Code Playgroud)