带有自定义图块的动态谷歌地图可防止重复播放

Chr*_*nch 6 google-maps

我有一个动态磁贴集,我不希望允许在其边界之外进行平移.

下面的代码让我接近,但用户仍然可以在严格边界之外水平滚动,因为它使用地图中心进行比较

var strictBounds = new google.maps.LatLngBounds(
 new google.maps.LatLng(sw_lat, sw_lon), 
 new google.maps.LatLng(ne_lat, ne_lon)
);

google.maps.event.addListener(map, 'drag', function() 
{
  if (strictBounds.contains(map.getCenter())) return;

 // We're out of bounds - Move the map back within the bounds

 var c = map.getCenter(),
     x = c.lng(),
     y = c.lat(),
     maxX = strictBounds.getNorthEast().lng(),
     maxY = strictBounds.getNorthEast().lat(),
     minX = strictBounds.getSouthWest().lng(),
     minY = strictBounds.getSouthWest().lat();

 if (x < minX) x = minX;
 if (x > maxX) x = maxX;
 if (y < minY) y = minY;
 if (y > maxY) y = maxY;

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

怎么了

我想要的是

Tib*_*org 9

为了快速访问,这里是这个解决方案的jsfiddle:http://jsfiddle.net/nYz6k/


假设您对当前检测中心边界的解决方案感到满意,您所要做的就是根据当前地图画布大小限制边界.

你现在得到的结果是,当它完全限制时(即纬度和经度都超过边界角),限制边界的每个角都出现在地图的中心.

解决方案是实际从边界中移除x和y偏移,并且仍然能够检查中心(与其他基于边界的检查解决方案相比,这是最有效的解决方案).

此外,只有在初始化地图和窗口调整大小时才必须限制边界,这意味着当您平移时,除了您已经提供的检查方法之外,没有额外的处理开销.

不要忘记为地图设置maxZoom属性(根据需要调整它),因为在确定的缩放级别之上,限制边界将自己适合视口,并且没有解决方案.

重要!使用'center_changed'而不是'drag',因为'drag'具有滑动行为,当您完成拖动并设置中心时,地图仍然会在平移方向上滑动.


在您实施解决方案之前,我建议您查看Maps API坐标系和投影的工作原理,因为此解决方案很大程度上基于它,如果您想要调整它,了解这些信息会很有用.

https://developers.google.com/maps/documentation/javascript/maptypes并查看自定义地图类型 - >地图坐标部分.


这是你需要做的.首先,您需要实现2种在地理坐标(LatLng)和像素坐标之间进行转换的简短方法.

var fromLatLngToPixel = function (latLng) {
  var point = map.getProjection().fromLatLngToPoint(latLng);
  var zoom = map.getZoom();
  return new google.maps.Point(
    Math.floor(point.x * Math.pow(2, zoom)),
    Math.floor(point.y * Math.pow(2, zoom))
  );
}

var fromPixelToLatLng = function (pixel) {
  var zoom = map.getZoom();
  var point = new google.maps.Point(
    pixel.x / Math.pow(2, zoom),
    pixel.y / Math.pow(2, zoom)
  );
  return map.getProjection().fromPointToLatLng(point);
}
Run Code Online (Sandbox Code Playgroud)

接下来,实现有效限制边界的方法.请注意,您始终必须保留一个存储原始边界的变量,因为每次调整地图画布时,结果边界都会更改.

对于这一点,让我们说originalBounds让你提供sw_lat,sw_long等的界限,shrinkedBounds通过此方法修饰.您可以将其重命名为strictBounds以在您的方法中仍然有效,但这取决于您.这使用jQuery获取canvas对象的宽度和高度.

var shrinkBounds = function () {
  zoom = map.getZoom();

  // The x and y offset will always be half the current map canvas
  // width and height respectively
  xoffset = $('#map_canvas').width() / 2;
  yoffset = $('#map_canvas').height() / 2;

  // Convert the bounds extremities to global pixel coordinates
  var pixswOriginal = fromLatLngToPixel(originalBounds.getSouthWest());
  var pixneOriginal = fromLatLngToPixel(originalBounds.getNorthEast());

  // Shrink the original bounds with the x and y offset
  var pixswShrinked = new google.maps.Point(pixswOriginal.x + xoffset, pixswOriginal.y - yoffset);
  var pixneShrinked = new google.maps.Point(pixneOriginal.x - xoffset, pixneOriginal.y + yoffset);

  // Rebuild the shrinkedBounds object with the modified 
  shrinkedBounds = new google.maps.LatLngBounds(
    fromPixelToLatLng(pixswShrinked),
    fromPixelToLatLng(pixneShrinked));
}
Run Code Online (Sandbox Code Playgroud)

接下来,您所要做的就是调用此方法:

  • 一旦初始化地图.请注意,根据您调用方法的时间,您可能会收到一些奇怪的错误,因为地图可能尚未初始化其所有属性.最好的方法是使用projection_changed事件.

    google.maps.event.addListener(map, 'projection_changed', function (e) {
      shrinkBounds();
    });
    
    Run Code Online (Sandbox Code Playgroud)
  • 每次调整地图画布的大小

     google.maps.event.addListener(map, 'resize', function (e) {
       shrinkBounds();
     });
    
    Run Code Online (Sandbox Code Playgroud)

但最重要的部分是"调整大小"事件永远不会触发地图容器的程序化大小调整,因此每次以编程方式调整画布大小时都必须手动触发它(如果你这样做,但我怀疑你这样做) .

最常见的方法是在调整窗口大小时触发它:

$(window).resize(function () {
  google.maps.event.trigger(map, 'resize');
});
Run Code Online (Sandbox Code Playgroud)

这一切后,你现在可以安全地使用你的方法,但作为一个处理程序"center_changed的"而不是如我前面所提到的"拖拽".


我用完整的工作代码设置了一个jsfiddle.

http://jsfiddle.net/nYz6k/

您可以在左下角看到限制显示的小半标记,它位于边界的SW角落.在NW角落也有一个,但自然你看不到它,因为它显示在位置上方.


jli*_*vni 0

不要使用map.getCenter()作为检查,而是使用map.getBounds()

未经测试,但实现此目的的一个简单方法是检查两个边界的并集是否相同(如果不是,则您的地图边界超出了严格边界):

var union = strictBounds.union(map.getBounds());
if (strictBounds.equals(union)) { //new map bounds is within strict bounds
Run Code Online (Sandbox Code Playgroud)