从最近的标记向用户定义的位置绘制方向

时间:2017-04-18 20:05:17

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

目标:

  • 显示带有一些标记的地图(来自数组或文件)
  • 让用户搜索地点/地址
  • 在地图上标记地点
  • 确定最接近地点的标记
  • 画&显示从标记到地方的方向
  • 如果执行新搜索,请更新路线

我想我很亲近。我从地图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);
		   }
	    });
	}
&#13;
#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; }
&#13;
<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>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

有很多问题,因为它是从网上制作出来的。这里要注意的主要事情是我已经将需求更新/拆分为可读函数(尽可能多)。我没有通过initMap作为回调,但这应该不是问题。没有尝试验证或优化代码。只是小修复。

  1. 我们设置了地图,
  2. 设置初始数据,
  3. 设置控件,最后
  4. 致电FindClosest
  5. &#13;
    &#13;
    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();
    &#13;
    #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;
    }
    &#13;
    <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>
    &#13;
    &#13;
    &#13;

    告诉我们。