我有一个动态磁贴集,我不希望允许在其边界之外进行平移。
下面的代码让我接近,但是用户仍然可以在严格边界之外水平滚动,因为它使用地图中心进行比较
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));
});
答案 0 :(得分:9)
为了快速访问,以下是此解决方案的jsfiddle:http://jsfiddle.net/nYz6k/
假设您对目前检测中心边界的解决方案感到满意,您所要做的就是根据当前地图画布大小限制边界。
您现在得到的结果是,当限制范围的每个角落完全限制时(即纬度和经度都超过边界角落),它会出现在地图的中心。
解决方案是实际从边界中移除x和y偏移量,并且仍能够检查中心(与其他基于边界的检查解决方案相比,这是最有效的解决方案)。
此外,只有在初始化地图和窗口调整大小时才必须限制边界,这意味着当您平移时,除了您已经提供的检查方法之外,没有额外的处理开销。
不要忘记为地图设置 maxZoom 属性(根据需要进行调整),因为在确定的缩放级别之上,限制边界本身适合视口,并且在那里&#39对此没有解决方案。
重要!使用&#39; center_changed&#39;而不是'拖'&#39;因为&#39;拖延&#39;具有滑动行为,当您完成拖动并设置中心时,地图仍然会在平移方向上滑动。
在您实施解决方案之前,我建议您查看Maps API坐标系统和投影的工作原理,因为此解决方案很大程度上基于它,如果您想要调整它,那么了解它是有用的这个信息。
https://developers.google.com/maps/documentation/javascript/maptypes并查看自定义地图类型 - &gt;地图坐标部分。
这是您需要做的事情。首先,您需要实现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);
}
接下来,实现有效限制边界的方法。请注意,您始终必须保留一个存储原始边界的变量,因为每次调整地图画布时,结果边界都会发生变化。
为此,让我们说 originalBounds 保持您使用sw_lat,sw_long等提供的界限,并且 shrinkedBounds 会被此方法修改。您可以将其重命名为strictBounds以在您的方法中仍然有效,但这取决于您。这使用jQuery来获取画布对象的宽度和高度。
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));
}
接下来,您所要做的就是调用此方法:
一次。请注意,根据您调用方法的时间,您可能会收到一些奇怪的错误,因为地图可能尚未初始化其所有属性。最好的方法是使用projection_changed事件。
google.maps.event.addListener(map, 'projection_changed', function (e) {
shrinkBounds();
});
每次调整地图画布的大小
google.maps.event.addListener(map, 'resize', function (e) {
shrinkBounds();
});
但最重要的部分是“调整大小”。对于地图容器的程序化大小调整永远不会触发事件,因此每次以编程方式调整画布大小时都必须手动触发它(如果这样做,但我怀疑你这样做。)
最常见的方法是在调整窗口大小时触发它:
$(window).resize(function () {
google.maps.event.trigger(map, 'resize');
});
完成所有这些后,您现在可以安全地使用您的方法,但作为&#39; center_changed&#39;的处理程序。而不是为了拖延&#39;正如我之前提到的那样。
我使用完整的工作代码设置了一个jsfiddle。
您可以在左下角看到限制显示的小半标记,它位于边界的SW角落。在NW角落也有一个,但自然你无法看到它,因为它显示在位置上方。
答案 1 :(得分:0)
不使用map.getCenter()作为检查,而是使用map.getBounds()
未经测试,但实现此目的的一种简单方法是检查两个边界的并集是否相同(如果不是,则地图边界超出严格边界):
var union = strictBounds.union(map.getBounds());
if (strictBounds.equals(union)) { //new map bounds is within strict bounds
答案 2 :(得分:0)
上面的Tiborg版本是目前为止最好的版本... 我注意到当缩放级别和宽度/高度大于原始边界时发生的错误
我修改了他的代码并添加了一个矩形来查看它的实际效果。
var buildBounds = function(sw, ne) {
var swY = sw.lat();
var swX = sw.lng();
var neY = ne.lat();
var neX = ne.lng();
if (swY > neY) {
var cY = (swY + neY) / 2;
swY = cY;
neY = cY;
}
if (swX > neX) {
var cX = (swX + neX) / 2;
swX = cX;
neX = cX;
}
return new google.maps.LatLngBounds(
new google.maps.LatLng(swY, swX),
new google.maps.LatLng(neY, neX));
}