【问题标题】:Using google street view with a marker, how do I point the POV at a marker?使用带有标记的谷歌街景,如何将 POV 指向标记?
【发布时间】:2011-03-13 00:32:04
【问题描述】:

我有一个简单的街景,可以显示给定地址的街景:

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);
    }
});

如您所见,我在街景中添加了地址标记。我的问题是,街景指向北方,而标记指向南方。对于非特定地址,如何指定街景应指向该地址的标记,而不是默认指向北方?

【问题讨论】:

    标签: google-maps google-maps-api-3 google-maps-markers google-street-view


    【解决方案1】:

    查看this sample。即使它适用于 V2,您也可以重用代码。基本上,您需要调用 computeAngle(markerLatLng, streetviewPanoLatLng),并将街景全景的 yaw 设置为返回值。

    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;
     }
    

    【讨论】:

    【解决方案2】:

    这样做的原因是街景 POV 默认情况下是拍摄图像时卡车所面对的方向(见图)。您需要获取卡车的位置和房屋的位置,并计算从第一个位置到第二个位置的“航向”,然后将您的街景位置设置为您刚刚计算的航向的卡车的位置

    // 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 {
            ...
            }
    

    使用街景的另一个技巧/陷阱是,您需要通过不断增加距离重复调用getPanoramaByLocation 来获取距离您的地址位置最近的街景,直到您成功或达到某个最大距离。我使用以下代码解决了这个问题:

    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);
                }
            });
        }
    

    【讨论】:

      【解决方案3】:

      基于您的代码的简单示例:

      1. 获取要查看的位置(使用地理编码器)
      2. 获取StreetViewPanorama 的位置(在其状态发生变化后使用getLocation() 方法,替代方法是使用getPosition() 方法的结果)。
      3. 使用geometry library 的computeHeading 方法计算从相机到地址的航向。
      4. 使用 setPov() 方法设置该标题。
      5. 延迟,以便标记移动到正确的位置(删除它会使标记留在左上角)。如果不使用标记,则不需要。
      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

      工作代码sn-p:

      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&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></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>

      【讨论】:

      • 谢谢,这主要对我有用,除了 geometry.spherical.computeHeading 的两个参数都需要是 LatLng 的实例。 myStreetView.getLocation().latLng 返回一个 LatLng 实例,但您还需要从您的位置创建一个新实例 new google.maps.LatLng(results[0].geometry.location)
      • results[0].geometry.location 也已经是google.maps.LatLng 对象
      • 是的,你是对的,如果你使用地理编码器库来获取它返回一个 LatLng 的位置。当我写该评论时,我直接点击了地理编码 API 端点,但后来切换到使用地理编码器。
      • 答案是使用地理编码器库,而不是网络服务。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-23
      • 2010-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多