Google Maps API V3:限制地图边界

Eka*_*ara 11 google-maps google-maps-api-3

我正在尝试设置界限,您可以使用Google Maps API V3拖动地图这是V2 http://econym.org.uk/gmap/example_range.htm的解决方案,效果非常好.

然而,使用API​​ V3并不是那么好:当你使用相同的checkbounds()函数时,当你到达边界时地图会抽搐,而map.setCenter()会改变地图的中心.

怎么解决?API V3的解决方案是什么?

小智 19

我有同样的问题,但这应该排除它(它是相同的功能,听取的事件从'移动'或'拖'变为'中心变换',就像一个魅力!:

google.maps.event.addListener(map,'center_changed',function() { checkBounds(); });

function checkBounds() {    
    if(! allowedBounds.contains(map.getCenter())) {
      var C = map.getCenter();
      var X = C.lng();
      var Y = C.lat();

      var AmaxX = allowedBounds.getNorthEast().lng();
      var AmaxY = allowedBounds.getNorthEast().lat();
      var AminX = allowedBounds.getSouthWest().lng();
      var AminY = allowedBounds.getSouthWest().lat();

      if (X < AminX) {X = AminX;}
      if (X > AmaxX) {X = AmaxX;}
      if (Y < AminY) {Y = AminY;}
      if (Y > AmaxY) {Y = AmaxY;}

      map.setCenter(new google.maps.LatLng(Y,X));
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 什么是`allowedBounds`设置为? (5认同)

小智 6

如果地图调整大小或放大/缩小,您可能还需要考虑环绕坐标,曲线扭曲和居中到边界尺寸.如果您的边界占据整个地图的很大一部分(例如像大陆一样),则尤其需要这样做.

然而,checkBounds()的问题之一是它没有考虑到接近北极/南极的纬度值,这些纬度值具有非线性失真,这使得限制界限准确(我使用近似幻数在所有情况下都不起作用的乘数).通过右边,您应该首先将边界转换为线性2d世界坐标,以查看它在世界坐标方面离边界的距离,而不是将世界坐标中的实际目标中心点映射到目标实际纬度位置.对于经度值,这似乎不是很多问题,并且线性剪切方法看起来足够准确,主要问题是经度坐标的包装,这在下面的代码中(稍微说明).

// Persitant variables
var allowedBounds;  // assign something here
var lastValidCenter;  // initialize this using map.getCenter()   

function checkBounds() {  // when bounds changes due to resizing or zooming in/out

    var currentBounds = map.getBounds();
    if (currentBounds == null) return;

      var allowed_ne_lng = allowedBounds.getNorthEast().lng();
      var allowed_ne_lat = allowedBounds.getNorthEast().lat();
      var allowed_sw_lng = allowedBounds.getSouthWest().lng();
      var allowed_sw_lat = allowedBounds.getSouthWest().lat();

    var wrap;
    var cc = map.getCenter();
    var centerH = false;
    var centerV = false;

    // Check horizontal wraps and offsets
    if ( currentBounds.toSpan().lng() > allowedBounds.toSpan().lng() ) {
        centerH = true;
    }
    else {  // test positive and negative wrap respectively
        wrap = currentBounds.getNorthEast().lng() < cc.lng();
        var current_ne_lng = !wrap ?   currentBounds.getNorthEast().lng()  : allowed_ne_lng +(currentBounds.getNorthEast().lng() + 180 )  + (180 - allowed_ne_lng);
        wrap = currentBounds.getSouthWest().lng() > cc.lng();
        var current_sw_lng = !wrap ?  currentBounds.getSouthWest().lng() : allowed_sw_lng - (180-currentBounds.getSouthWest().lng()) - (allowed_sw_lng+180);
    }


    // Check vertical wraps and offsets
    if ( currentBounds.toSpan().lat() > allowedBounds.toSpan().lat() ) {
        centerV = true;
    }
    else { // test positive and negative wrap respectively
    wrap = currentBounds.getNorthEast().lat()   < cc.lat();    if (wrap) { alert("WRAp detected top") } // else alert("no wrap:"+currentBounds); wrap = false;
      var current_ne_lat =  !wrap ? currentBounds.getNorthEast().lat()  : allowed_ne_lat + (currentBounds.getNorthEast().lat() +90) + (90 - allowed_ne_lat);
      wrap = currentBounds.getSouthWest().lat() > cc.lat();  if (wrap) { alert("WRAp detected btm") } //alert("no wrap:"+currentBounds);
      var current_sw_lat = !wrap ?  currentBounds.getSouthWest().lat() : allowed_sw_lat - (90-currentBounds.getSouthWest().lat()) - (allowed_sw_lat+90);
    }


      // Finalise positions
      var centerX = cc.lng();
      var centerY = cc.lat();
     if (!centerH) {
        if (current_ne_lng > allowed_ne_lng) centerX -= current_ne_lng-allowed_ne_lng;
        if (current_sw_lng < allowed_sw_lng) centerX += allowed_sw_lng-current_sw_lng;
     }
     else {
         centerX = allowedBounds.getCenter().lng();
     }

     if (!centerV) {
       if (current_ne_lat > allowed_ne_lat) {
           centerY -= (current_ne_lat-allowed_ne_lat) * 3;  // approximation magic numbeer. Adjust as u see fit, or use a more accruate pixel measurement.
       }
       if (current_sw_lat < allowed_sw_lat) {
           centerY += (allowed_sw_lat-current_sw_lat)*2.8;  // approximation magic number
       }
     }
     else {
        centerY = allowedBounds.getCenter().lat();
     }
     map.setCenter(lastValidCenter = new google.maps.LatLng(centerY,centerX));
}



function limitBound(bound) // Occurs during dragging, pass allowedBounds to this function in most cases. Requires persistant 'lastValidCenter=map.getCenter()' var reference.
     {
        var mapBounds = map.getBounds();

         if (   mapBounds.getNorthEast().lng() >=  mapBounds.getSouthWest().lng() && mapBounds.getNorthEast().lat()  >= mapBounds.getSouthWest().lat()  // ensure no left/right, top/bottom wrapping
            && bound.getNorthEast().lat() > mapBounds.getNorthEast().lat()  // top
            && bound.getNorthEast().lng() > mapBounds.getNorthEast().lng() // right
            && bound.getSouthWest().lat() < mapBounds.getSouthWest().lat() // bottom
            && bound.getSouthWest().lng() < mapBounds.getSouthWest().lng()) // left
            {
                lastValidCenter=map.getCenter();  // valid case, set up new valid center location
            }

        //   if (bound.contains(map.getCenter()))
        // {
                map.panTo(lastValidCenter);
             //  }

         }



// Google map listeners

google.maps.event.addListener(map, 'zoom_changed', function() {
    //var zoom = map.getZoom();
    checkBounds();
});

google.maps.event.addListener(map, "bounds_changed", function() {

    checkBounds();
});

google.maps.event.addListener(map, 'center_changed', function() {
      limitBound(allowedBounds);
}); 
Run Code Online (Sandbox Code Playgroud)

ps对于checkBounds(),要从地图中心获取正确的2d世界坐标,给定2个lat/lng值,请使用map.getProjection().fromLatLngToPoint().比较2个点,找到它们之间的线性差异,并使用map.getProjection().fromPointToLatLng()将世界坐标的差异映射回lat/lng.这将为您提供lat/lng单位的精确剪辑偏移.