javascript - 从最近的标记绘制到用户定义地点的方向

标签 javascript google-maps google-maps-api-3

目标:

  • 显示带有一些标记的 map (来自数组或文件)
  • 让用户搜索地点/地址
  • 在 map 上标记该地点
  • 确定哪个标记距离该地点最近
  • 绘制并显示从标记到该地点的路线
  • 如果执行新的搜索,请更新说明

我想我已经很接近了。我从 map API 文档和 Stack Overflow 上的其他问题中拼凑了一些代码。我已经正确标记了搜索的位置并确定了最近的标记,但在更新方向标记和绘制路径时遇到了困难。

onChangeHandler 或应该触发它的监听器是否有问题?

This example from Google Maps API Documentation这是我与听众一起寻找最后一部分的地方,以更新和绘制新的方向。

最终我打算添加 another Google Maps API sample 上所示的步骤

	function initMap() {

		var map;
		var myOptions = {
			zoom: 14,
			center: {lat: 40.7484, lng: -73.9857},
			scrollwheel: false,
			mapTypeId: 'roadmap'
		};

		// map for search & directions
		map = new google.maps.Map(document.getElementById('map'), myOptions);

		// create initial origin marker
		// to-do: error if not defined
		var markerA = new google.maps.Marker({
			position: {lat: 40.7484, lng: -73.9857},
			map: map,
		});

		// create array of locations and assign values
		var locs = [];
		locs[0] = ['Location 1 Name', '40.73297438','-73.97860823'];
		locs[1] = ['Location 2 Name', '40.72824765','-73.98219971'];
		locs[2] = ['Location 3 Name', '40.73181838','-73.97871015'];

		var infowindow = new google.maps.InfoWindow;
		var loc, i;
		var locations = [];

		// create markers for each loc and place them on map
		for (i = 0; i < locs.length; i++) {
			loc = new google.maps.Marker({
				position: new google.maps.LatLng(locs[i][1], locs[i][2]),
				map: map
			});

			google.maps.event.addListener(loc, 'click', (function(loc, i)  {
				return function() {
					infowindow.setContent(locs[i][0]);
					infowindow.open(map, loc);
				}
			})(loc, i));
			locations.push(loc.position);
		}

		// Create the search box and link it to the UI element.
		var input = document.getElementById('pac-input');
		var searchBox = new google.maps.places.SearchBox(input);
		map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);

		// Bias the SearchBox results towards current map's viewport.
		map.addListener('bounds_changed', function () {
			searchBox.setBounds(map.getBounds());
		});

		var markers = [];
		// Listen for the event fired when the user selects a prediction and 
		// retrieve more details for that place.
		searchBox.addListener('places_changed', function () {
			var places = searchBox.getPlaces();

			if (places.length == 0) {
				return;
			}

			// Clear out the old markers.
			markers.forEach(function (marker) {
				marker.setMap(null);
			});
			markers = [];

			// For each place, get the icon, name and location.
			var bounds = new google.maps.LatLngBounds();
			places.forEach(function (place) {
				if (!place.geometry) {
					console.log("Returned place contains no geometry");
					return;
				}
				var icon = {
					url: place.icon,
					size: new google.maps.Size(71, 71),
					origin: new google.maps.Point(0, 0),
					anchor: new google.maps.Point(17, 34),
					scaledSize: new google.maps.Size(25, 25)
				};

				// update the origin, markerA, and add to map
				markerA.setPosition(place.geometry.location);
				markerA.setIcon(icon);
				markerA.setTitle(place.name);
				markers.push(markerA);

				if (place.geometry.viewport) {
					// Only geocodes have viewport.
					bounds.union(place.geometry.viewport);
				} else {
					bounds.extend(place.geometry.location);
				}

				});
			map.fitBounds(bounds);
			map.setOptions({
				zoom: 17
			});
		});

		var pointA = markerA.getPosition();
		var markerB;

		findClosest(pointA, locations);

		// improved garage search to determine closest location
		function findClosest(pointA, locations) {
			var closestDistance = Number.MAX_SAFE_INTEGER;
			var closest;
			for (i = 0; i < locations.length; i++) {
				var distance = google.maps.geometry.spherical.computeDistanceBetween(pointA, locations[i]);
				if (distance < closestDistance) {
					closestDistance = distance;
					closest = locations[i];
				}
			}
			markerB = closest;
			// alert(closest);
		}


		var directionsService = new google.maps.DirectionsService;
		var directionsDisplay = new google.maps.DirectionsRenderer({
			map: map
		});

		var pointB = markerB;

		calculateAndDisplayRoute(directionsService, directionsDisplay, pointA, pointB, map);

		var onChangeHandler = function() {
			calculateAndDisplayRoute(directionsService, directionsDisplay, pointA, pointB, map);
		};
		map.addListener('change', onChangeHandler);

	}

	function calculateAndDisplayRoute(directionsService, directionsDisplay, pointA, pointB, map) {
	    directionsService.route({
		   origin: pointA,
		   destination: pointB,
		   travelMode: google.maps.TravelMode.WALKING
	    }, function (response, status) {
		   if (status == google.maps.DirectionsStatus.OK) {
			  directionsDisplay.setDirections(response);
		   } else {
			  window.alert('Could not load directions due to ' + status);
		   }
	    });
	}
#pac-input {
  background-color: #ffffff;
  font-family: Roboto;
  font-size: 15px;
  font-weight: 300;
  margin-left: 12px;
  margin-top: 9px;
  padding: 5px 11px 5px 13px;
  text-overflow: ellipsis;
  width: 400px;
}
#map { height: 475px; }
<input type="text" id="pac-input" class="controls" placeholder="Where are you headed?" /></p>
<div id="map">&nbsp;</div>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyC8MQrdVaz8JKiUnSU0usHzGRQGrI_x3DQ&amp;callback=initMap&amp;libraries=geometry,places" async="" defer="defer" type="text/javascript"></script>

最佳答案

鉴于它是从网络上编写的,因此存在多个问题。这里要注意的主要事情是我已将需求更新/拆分为可读的函数(尽可能多)。我没有将 initMap 作为回调传递,但这应该不是问题。没有尝试验证或优化代码。只是一些小修复。

  1. 我们设置了 map ,
  2. 设置初始数据,
  3. 设置控件,最后
  4. 调用FindClosest

var map;
var locs = [];
var markers = [];
var headToPoint = {};
var input = document.getElementById('pac-input');
var searchBox = {};
var directionsService = new google.maps.DirectionsService();
var directionsDisplay = {};

var initMap = function() {

  var myOptions = {
    zoom: 14,
    center: {
      lat: 40.7484,
      lng: -73.9857
    },
    scrollwheel: false,
    mapTypeId: 'roadmap'
  };

  map = new google.maps.Map(document.getElementById('map'), myOptions);
  directionsDisplay = new google.maps.DirectionsRenderer({
    map: map
  });

  AddInitialMarkers();
  SetupInputsToMap();
  FindClosestDirection();
}

function AddInitialMarkers() {

  headToPoint = new google.maps.Marker({
    position: {
      lat: 40.7484,
      lng: -73.9857
    },
    map: map,
  });

  locs[0] = ['Location 1 Name', '40.73297438', '-73.97860823'];
  locs[1] = ['Location 2 Name', '40.72824765', '-73.98219971'];
  locs[2] = ['Location 3 Name', '40.73181838', '-73.97871015'];

  var infowindow = new google.maps.InfoWindow;
  var loc;
  for (i = 0; i < locs.length; i++) {
    loc = new google.maps.Marker({
      position: new google.maps.LatLng(locs[i][1], locs[i][2]),
      map: map
    });

    google.maps.event.addListener(loc, 'click', (function(loc, i) {
      return function() {
        infowindow.setContent(locs[i][0]);
        infowindow.open(map, loc);
      }
    })(loc, i));
    markers.push(loc)
  }
}

function SetupInputsToMap() {
  searchBox = new google.maps.places.SearchBox(input);
  map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
  map.addListener('bounds_changed', function() {
    searchBox.setBounds(map.getBounds());
  });
  searchBox.addListener('places_changed', new_place_selected);
}

function new_place_selected() {

  var places = searchBox.getPlaces();
  if (places.length == 0) {
    return;
  }
  // For each place, get the icon, name and location.
  var bounds = new google.maps.LatLngBounds();
  places.forEach(function(place) {
    if (!place.geometry) {
      console.log("Returned place contains no geometry");
      return;
    }
    var icon = {
      url: place.icon,
      size: new google.maps.Size(71, 71),
      origin: new google.maps.Point(0, 0),
      anchor: new google.maps.Point(17, 34),
      scaledSize: new google.maps.Size(25, 25)
    };

    headToPoint.setPosition(place.geometry.location);
    headToPoint.setIcon(icon);
    headToPoint.setTitle(place.name);
    markers.push(headToPoint);

    if (place.geometry.viewport) {
      // Only geocodes have viewport.
      bounds.union(place.geometry.viewport);
    } else {
      bounds.extend(place.geometry.location);
    }

  });
  map.fitBounds(bounds);
  map.setOptions({
    zoom: 17
  });
  FindClosestDirection();
}

var FindClosestDirection = function() {

  var closestDistance = Number.MAX_SAFE_INTEGER;
  var closest;

  for (i = 0; i < markers.length; i++) {
    if (markers[i].position !== headToPoint.getPosition()) {
      var distance = google.maps.geometry.spherical.computeDistanceBetween(headToPoint.getPosition(), markers[i].position);
      if (distance < closestDistance) {
        closestDistance = distance;
        closest = markers[i];
      }
    }
  }
  calculateAndDisplayRoute(directionsService, directionsDisplay, headToPoint.getPosition(), closest.position);

}

function calculateAndDisplayRoute(directionsService, directionsDisplay, pointA, pointB) {
  directionsService.route({
    origin: pointA,
    destination: pointB,
    travelMode: 'WALKING'
  }, function(response, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      directionsDisplay.setDirections(response);
    } else {
      window.alert('Could not load directions due to ' + status);
    }
  });
}
initMap();
#pac-input {
  background-color: #ffffff;
  font-family: Roboto;
  font-size: 15px;
  font-weight: 300;
  margin-left: 12px;
  margin-top: 9px;
  padding: 5px 11px 5px 13px;
  text-overflow: ellipsis;
  width: 400px;
}

#map {
  height: 475px;
}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyC8MQrdVaz8JKiUnSU0usHzGRQGrI_x3DQ&amp;libraries=geometry,places" type="text/javascript"></script>

<input type="text" id="pac-input" class="controls" placeholder="Where are you headed?" />
<div id="map">&nbsp;</div>

请告诉我们。

关于javascript - 从最近的标记绘制到用户定义地点的方向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43481245/

相关文章:

javascript - PayPal 结帐与 JS SDK 按钮集成 - "Invalid sdk meta"问题

javascript - react 路由器: Create 'Link to' paths from objects

javascript - Google Maps API 中无法加载两个方向

google-maps - 创建地理边界框的简单 map 界面?

javascript - 两个坐标之间带有箭头的动画线 Google Maps Javascript

javascript - 如何禁用 php 中的日期数组

javascript - 如何获取在javascript中点击的li的索引

java - map : check wether a point is on polyline or not

javascript - 带有 MarkerClustererer 的 Google map v3 无法与 createmarker 一起使用

javascript - 使用 Directions_changed 获取新拖动方向的 LatLng