Using google street view with a marker, how do I p

2020-06-16 09:02发布

问题:

I have a simple street view working to show me a street view given an address:

var geocoder = new google.maps.Geocoder();
var address = "344 Laguna Dr, Milpitas, CA  95035";
geocoder.geocode( { 'address': address}, 
    function(results, status) {
        //alert (results);
    if (status == google.maps.GeocoderStatus.OK) {
        //alert(results[0].geometry.location);
        myStreetView = new google.maps.StreetViewPanorama(document.getElementById("map_canvas"));
        myStreetView.setPosition(results[0].geometry.location);
        var marker = new google.maps.Marker({
            position: results[0].geometry.location, 
            map: myStreetView, 
            title:address
        });
        //alert ("yay");
    } else {
        alert("Geocode was not successful for the following reason: " + status);
    }
});

As you can see, I add a marker for the address onto the street view. My question is, the street view is pointing north, and the marker is to the south. For a non-specific address, how do I designate that the street view should point at the marker for the address instead of pointing north by default?

回答1:

The reason for this is that the street view POV is, by default the direction the truck was facing when the image was shot (go figure). You need to get the location of the truck and the location of the house and calculate a "heading" from the first location to the second, then set your street-view location to that of the truck with the heading you just calculated:

// adrloc=target address
// svwloc=street-view truck location
svwService.getPanoramaByLocation(adrloc,svwdst,function(dta,sts) {
    if(sts==google.maps.StreetViewStatus.OK) {
        var svwloc=dta.location.latLng;
        var svwhdg=google.maps.geometry.spherical.computeHeading(svwloc,adrloc);
        var svwmap=avwMap.getStreetView();
        svwmap.setPosition(svwloc);
        svwmap.setPov({ heading: svwhdg, pitch: 0 });
        svwMarker=new google.maps.Marker({ map:svwmap, position: adrloc });
        svwmap.setVisible(true);
        }
    else {
        ...
        }

Another trick/trap using street view is that you need to obtain the closest street view to your address location by repeatedly calling getPanoramaByLocation with an increasing distance until you are either successful or reach some maximum distance. I solve this using this code:

var SVW_MAX=100; // maximum street-view distance in meters
var SVW_INC=10;  // increment street-view distance in meters
var svwService=new google.maps.StreetViewService(); // street view service
var svwMarker=null; // street view marker

// NOTE: avwMap is the aerial view map, code not shown
...
resolveStreetView(avwMap.getCenter(),SVW_INC); 
...

var resolveStreetView=function(adrloc,svwdst) {
    svwService.getPanoramaByLocation(adrloc,svwdst,function(dta,sts) {
        if(sts==google.maps.StreetViewStatus.OK) {
            var svwloc=dta.location.latLng;
            var svwhdg=google.maps.geometry.spherical.computeHeading(svwloc,adrloc);
            var svwmap=avwMap.getStreetView();
            svwmap.setPosition(svwloc);
            svwmap.setPov({ heading: svwhdg, pitch: 0 });
            svwMarker=new google.maps.Marker({ map:svwmap, position: adrloc });
            svwmap.setVisible(true);
            }
        else if(svwdst<SVW_MAX) {
            resolveStreetView(adrloc,svwdst+SVW_INC);
            }
        });
    }


回答2:

Check out this sample. Even though its for V2, you can reuse the code. Basically, you'll need to call computeAngle(markerLatLng, streetviewPanoLatLng), and set the Street View pano's yaw to the returned value.

function computeAngle(endLatLng, startLatLng) {
  var DEGREE_PER_RADIAN = 57.2957795;
  var RADIAN_PER_DEGREE = 0.017453;

  var dlat = endLatLng.lat() - startLatLng.lat();
  var dlng = endLatLng.lng() - startLatLng.lng();
  // We multiply dlng with cos(endLat), since the two points are very closeby,
  // so we assume their cos values are approximately equal.
  var yaw = Math.atan2(dlng * Math.cos(endLatLng.lat() * RADIAN_PER_DEGREE), dlat)
         * DEGREE_PER_RADIAN;
  return wrapAngle(yaw);
}

function wrapAngle(angle) {
  if (angle >= 360) {
    angle -= 360;
  } else if (angle < 0) {
    angle += 360;
  }
  return angle;
 }


回答3:

Simple example based off your code:

  1. get the location to look at (using the geocoder)
  2. get the location of the StreetViewPanorama (using the getLocation() method once its status has changed, alternative would be to use the results of the getPosition() method).
  3. use the computeHeading method of the geometry library to compute the heading from the camera to the address.
  4. set that heading using the setPov() method.
  5. delay so the marker goes to the correct place (removing this leaves the marker in the upper left hand corner). Not needed if not using markers.
function geocodeAddress() {
  var address = "344 Laguna Dr, Milpitas, CA  95035";
  geocoder.geocode({
    'address': address
  }, function(results, status) {
    //alert (results);
    if (status == google.maps.GeocoderStatus.OK) {
      //alert(results[0].geometry.location);
      myStreetView = new google.maps.StreetViewPanorama(document.getElementById("map_canvas"));
      myStreetView.setPosition(results[0].geometry.location);
      google.maps.event.addListenerOnce(myStreetView, 'status_changed', function() {
        var heading = google.maps.geometry.spherical.computeHeading(myStreetView.getLocation().latLng, results[0].geometry.location);
        myStreetView.setPov({
          heading: heading,
          pitch: 0
        });
        setTimeout(function() {
          marker = new google.maps.Marker({
            position: results[0].geometry.location,
            map: myStreetView,
            title: address
          });
          if (marker && marker.setMap) marker.setMap(myStreetView);
        }, 500);
      });

    } else {
      alert("Geocode was not successful for the following reason: " + status);
    }
  });
  google.maps.event.addDomListener(document.getElementById('geoBtn'), 'click', geocodeAddress);
}

working fiddle

working code snippet:

var geocoder = new google.maps.Geocoder();
var myStreetView = null;
var marker = null;

function geocodeAddress() {
  // var address = "344 Laguna Dr, Milpitas, CA  95035";
  var address = document.getElementById('address').value;
  geocoder.geocode({
    'address': address
  }, function(results, status) {
    //alert (results);
    if (status == google.maps.GeocoderStatus.OK) {
      //alert(results[0].geometry.location);
      myStreetView = new google.maps.StreetViewPanorama(document.getElementById("map_canvas"));
      myStreetView.setPosition(results[0].geometry.location);
      google.maps.event.addListenerOnce(myStreetView, 'status_changed', function() {
        var heading = google.maps.geometry.spherical.computeHeading(myStreetView.getLocation().latLng, results[0].geometry.location);
        myStreetView.setPov({
          heading: heading,
          pitch: 0
        });
        setTimeout(function() {
          marker = new google.maps.Marker({
            position: results[0].geometry.location,
            map: myStreetView,
            title: address
          });
          if (marker && marker.setMap) marker.setMap(myStreetView);
        }, 500);
      });

    } else {
      alert("Geocode was not successful for the following reason: " + status);
    }
  });
  google.maps.event.addDomListener(document.getElementById('geoBtn'), 'click', geocodeAddress);
}
google.maps.event.addDomListener(window, 'load', geocodeAddress);
html,
body,
#map_canvas {
  height: 100%;
  width: 100%;
}
<script src="http://maps.google.com/maps/api/js?libraries=geometry"></script>
<input id="address" type="text" value="344 Laguna Dr, Milpitas, CA  95035" />
<input id="geoBtn" type="button" value="Go" />
<div id="map_canvas"></div>