gpt4 book ai didi

google-maps - 带有自定义图 block 的动态谷歌地图可防止重复平移

转载 作者:行者123 更新时间:2023-12-04 14:15:47 24 4
gpt4 key购买 nike

我有一个动态图 block 集,我不想让平移超出其范围。

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

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

What is happening

What I want

最佳答案

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

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

您现在得到的结果是,当完全限制时,限制边界的每个角落都会出现在 map 的中心(即纬度和经度都超过边界角落)。

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

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

不要忘记设置 最大缩放 map 的属性(根据需要对其进行调整),因为在确定的缩放级别之上,限制边界本身将适合视口(viewport),并且没有解决方案。

重要的!使用 'center_changed' 而不是 'drag' 因为 'drag' 具有滑动行为,当您完成拖动并设置中心时, map 仍会沿平移方向滑动。

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

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

这是你需要做的。首先,您需要实现 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);
}

接下来,实现有效限制边界的方法。请注意,您始终必须保留一个存储原始边界的变量,因为每次调整 map Canvas 的大小时,生成的边界都会改变。

为此,假设 原始边界 保持您使用 sw_lat、sw_long 等和 提供的范围收缩边界 通过这种方法修改。您可以将其重命名为 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));
}

接下来,您所要做的就是调用此方法:
  • map 初始化时一次。请注意,根据您调用该方法的时间,您可能会遇到一些奇怪的错误,因为 map 可能尚未初始化它的所有属性。最好的方法是使用 projection_changed 事件。
    google.maps.event.addListener(map, 'projection_changed', function (e) {
    shrinkBounds();
    });
  • 每次调整 map Canvas 大小时
     google.maps.event.addListener(map, 'resize', function (e) {
    shrinkBounds();
    });

  • 但其中最重要的部分是“resize”事件永远不会因 map 容器的编程调整大小而触发,因此每次以编程方式调整 Canvas 大小时都必须手动触发它(如果你这样做,但我怀疑你这样做) .

    最常见的方法是在调整窗口大小时触发它:
    $(window).resize(function () {
    google.maps.event.trigger(map, 'resize');
    });

    毕竟,您现在可以安全地使用您的方法,但作为 'center_changed' 的处理程序,而不是我之前提到的 'drag' 的处理程序。

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

    http://jsfiddle.net/nYz6k/

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

    关于google-maps - 带有自定义图 block 的动态谷歌地图可防止重复平移,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12825040/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com