Android 在 LatLngBounds 构建器上设置最大缩放级别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20571951/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 03:03:59  来源:igfitidea点击:

Set a max zoom level on LatLngBounds builder

androidandroid-maps-v2zooming

提问by Alin

I haven't found an answer in my search, there are a few answers on SO but they didn't work for me.

我在搜索中没有找到答案,SO 上有一些答案,但它们对我不起作用。

I have 2 markers on the map and I am using LatLngBounds builder in order to let the camera zoom to the right zoom level to include them both. Everything works as expected aside one thing, when the 2 markers are really close to each other, the map is very very zoomed and well, it doesn't make any sense to have this level of zooming.

我在地图上有 2 个标记,我正在使用 LatLngBounds 构建器,以便让相机缩放到正确的缩放级别以包含它们。除了一件事之外,一切都按预期工作,当 2 个标记彼此非常接近时,地图会非常非常缩放,而且这种级别的缩放没有任何意义。

LatLngBounds.Builder builder = new LatLngBounds.Builder();
builder.include(firstMarker.getPosition());
builder.include(secondMarker.getPosition());
LatLngBounds bounds = builder.build();

CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, markerPadding);

Is there a way to force a certain level of zoom, after which the camera won't zoom ? This would avoid having the map too zoomed in/out. Basically I am using 15.0f as level of zoom. If the points are too far away I want the zoom to fit them both. If points are getting close I don't want the zoom level to go beyond 15.0f.

有没有办法强制一定程度的变焦,之后相机就不会变焦?这将避免地图过度放大/缩小。基本上我使用 15.0f 作为缩放级别。如果点太远,我希望缩放适合它们。如果点越来越接近,我不希望缩放级别超过 15.0f。

回答by user2808624

I have a similar case, where I want at least a map diagonal of 2 kilometers. Therefore I just add two additional points to the builder: the first 1 km north-west of the center of the original bounds and the second 1 km south-east of the center. If these are inside the bounds, they do not change anything. If they are outside of the original bounds, they increase the bounds to a meaningful size.

我有一个类似的案例,我想要至少 2 公里的地图对角线。因此,我只向构建器添加了两个额外的点:原始边界中心西北方向的第一个 1 公里和中心东南方向的第二个 1 公里。如果这些在边界内,它们不会改变任何东西。如果它们在原始边界之外,则将边界增加到有意义的大小。

Here is a full code example:

这是一个完整的代码示例:

public LatLngBounds createBoundsWithMinDiagonal(MarkerOptions firstMarker, MarkerOptions secondMarker) {
    LatLngBounds.Builder builder = new LatLngBounds.Builder();
    builder.include(firstMarker.getPosition());
    builder.include(secondMarker.getPosition());

    LatLngBounds tmpBounds = builder.build();
    /** Add 2 points 1000m northEast and southWest of the center.
     * They increase the bounds only, if they are not already larger
     * than this. 
     * 1000m on the diagonal translates into about 709m to each direction. */
    LatLng center = tmpBounds.getCenter();
    LatLng northEast = move(center, 709, 709);
    LatLng southWest = move(center, -709, -709);
    builder.include(southWest);
    builder.include(northEast);
    return builder.build();     
}

private static final double EARTHRADIUS = 6366198;
/**
 * Create a new LatLng which lies toNorth meters north and toEast meters
 * east of startLL
 */
private static LatLng move(LatLng startLL, double toNorth, double toEast) {
    double lonDiff = meterToLongitude(toEast, startLL.latitude);
    double latDiff = meterToLatitude(toNorth);
    return new LatLng(startLL.latitude + latDiff, startLL.longitude
            + lonDiff);
}

private static double meterToLongitude(double meterToEast, double latitude) {
    double latArc = Math.toRadians(latitude);
    double radius = Math.cos(latArc) * EARTHRADIUS;
    double rad = meterToEast / radius;
    return Math.toDegrees(rad);
}


private static double meterToLatitude(double meterToNorth) {
    double rad = meterToNorth / EARTHRADIUS;
    return Math.toDegrees(rad);
}

回答by dvdrlee

I implemented this solution according to the answer by user2808624, but using the SphericalUtilfrom the Android Maps Utility Libraryto do the calculations.

我根据user2808624答案实现这一解决方案,但使用SphericalUtilAndroid地图实用程序库做计算。

final double HEADING_NORTH_EAST = 45;
final double HEADING_SOUTH_WEST = 225;
LatLng center = tmpBounds.getCenter();
LatLng northEast = SphericalUtil.computeOffset(center, 709, HEADING_NORTH_EAST);
LatLng southWest = SphericalUtil.computeOffset(center, 709, HEADING_SOUTH_WEST);

回答by Bj?rn Kechel

Coming late but maybe someone has the same issue I had: I received bounds from a Place, not from a LatLngBounds.Builder:

来晚了,但也许有人和我有同样的问题:我收到了一个地方的边界,而不是一个 LatLngBounds.Builder:

I used Location.distanceBetween(...) to find out if the bounds were too small, and then use a minimum zoom level with the center of the bounds:

我使用 Location.distanceBetween(...) 来确定边界是否太小,然后使用边界中心的最小缩放级别:

if (areBoundsTooSmall(bounds, 300)) {
    mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(bounds.getCenter(), 17));
} else {
    mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 20));
}

The check method is:

检查方法是:

private boolean areBoundsTooSmall(LatLngBounds bounds, int minDistanceInMeter) {
    float[] result = new float[1];
    Location.distanceBetween(bounds.southwest.latitude, bounds.southwest.longitude, bounds.northeast.latitude, bounds.northeast.longitude, result);
    return result[0] < minDistanceInMeter;
}

I used min zoom level 17 and padding 20 for bounds that are too small, too small is definded here by min distance in meter 300. You can adjust the numbers as you need.

对于太小的边界,我使用了最小缩放级别 17 和填充 20,太小在这里由米 300 中的最小距离定义。您可以根据需要调整数字。

回答by Marc

Here is a much shorter version based on user2808624's answer.

这是基于user2808624答案的更短的版本。

        LatLngBounds bounds = builder.build();
        LatLng center = bounds.getCenter();
        builder.include(new LatLng(center.latitude-0.001f,center.longitude-0.001f));
        builder.include(new LatLng(center.latitude+0.001f,center.longitude+0.001f));
        bounds = builder.build();

Its a bit sloppy, but you can use 0.001 to zoom no less than a city block, 0.01 for no less than a city view. Only advantage is its only 4 extra lines of code.

有点马虎,但是你可以用0.001缩放不低于一个城市街区,0.01缩放不低于一个城市景观。唯一的优势是它只有 4 行额外的代码。

回答by user2150941

It is just simple:

这很简单:

LatLngBounds.Builder latlngBuilder = new LatLngBounds.Builder();

LatLng sydney1 = new LatLng(57.149651, -2.099075);

LatLng sydney2 = new LatLng(51.621441, -3.943646);

latlngBuilder.include(sydney1);
latlngBuilder.include(sydney2);

googlemap.animateCamera(CameraUpdateFactory.newLatLngBounds(latlngBuilder.build(), 100));

回答by malinjir

Google has added an api for limiting max/min zoom levels.

谷歌添加了一个用于限制最大/最小缩放级别的 api。

GoogleMap.setMaxZoomPreference()
GoogleMap.setMinZoomPreference()

回答by Paul Brewczynski

Quick fix is:

快速修复是:

gMap.setOnMapLoadedCallback(this);
CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, padding);
gMap.setMaxZoomPreference(10);
gMap.animateCamera(cu);


@Override
public void onMapLoaded() {
    gMap.resetMinMaxZoomPreference();
}

Beware that it could halt zoom until map is fully reloaded. But as a quick fix it works.

请注意,在完全重新加载地图之前,它可能会停止缩放。但作为一个快速修复它的工作原理。

回答by GLee

Have you considered making a map fragment that is hidden, and using that to determine your zoom/bounds? It's obviously not the best computationally, but it's probably the easiest/most accurate solution. For instance, it's complex to make a mathematical solution that works near the poles and across 0 degrees longitude (if you care). If you use a map, that's all built in already. You could also obviously use this solution on your existing map, but the user would see a bounce.

您是否考虑过制作一个隐藏的地图片段,并使用它来确定您的缩放/边界?它显然不是最好的计算方法,但它可能是最简单/最准确的解决方案。例如,制定一个在极点附近和 0 度经度范围内工作的数学解决方案很复杂(如果你关心的话)。如果你使用地图,那一切都已经内置了。您显然也可以在现有地图上使用此解决方案,但用户会看到反弹。

Here's how you'd do it:

这是你的方法:

  1. Go to the bounds as you've defined above
  2. Get the zoom using map.getCameraPosition().zoom.
  3. If zoom > 15 zoom out to 15 using CameraUpdateFactory.zoomTo(15)
  1. 去到你上面定义的界限
  2. 使用 map.getCameraPosition().zoom 获取缩放。
  3. 如果 zoom > 15 使用 CameraUpdateFactory.zoomTo(15) 缩小到 15

回答by Supriya

Following from the answers by user2808624 and dvdrlee, I wrote an extension in Kotlin:

根据 user2808624 和 dvdrlee 的回答,我在 Kotlin 中编写了一个扩展:

fun LatLngBounds.Builder.createBoundsWithZoomMaintained(bounds: LatLngBounds) : LatLngBounds  {
    val HEADING_NORTH_EAST = 45.0   //NorthEast angle
    val HEADING_SOUTH_WEST = 215.0  //SouthWest angle
    val center = bounds.center
    val northEast = SphericalUtil.computeOffset(center, 709.0, HEADING_NORTH_EAST)  //1000 metres on the diagonal translates to 709 metres on either side.
    val southWest = SphericalUtil.computeOffset(center, 709.0, HEADING_SOUTH_WEST)
    this.include(northEast).include(southWest)
    return this.build()
}

This would typically be in your Utils or Extensions file, and then you can use it from anywhere simply like this:

这通常在您的 Utils 或 Extensions 文件中,然后您可以像这样从任何地方使用它:

var bounds = builder.build()  //To include all your existing points.
bounds = builder.createBoundsWithZoomMaintained(bounds)  //Updated bounds.
mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 10)) 

回答by MaciejGórski

There is no way to limit zoom levels as of 4.0.30, but you may track this issue.

从 4.0.30 开始,无法限制缩放级别,但您可以跟踪此问题

The easy way would be to force zoom level like on this video: http://www.youtube.com/watch?v=-nCZ37HdheY
Basically they are calling animateCamerawhen certain zoom level is reached.

简单的方法是像这个视频一样强制缩放级别:http: //www.youtube.com/watch?v=
-nCZ37HdheY 基本上他们在animateCamera达到某个缩放级别时调用。

That would look a bit weird, because you then have 2 animations that are not started by the user.

这看起来有点奇怪,因为你有 2 个不是由用户启动的动画。

The hard way would be doing the math yourself. Try working with CameraUpdateFactory.newLatLngZoomwith LatLngas a center between these points and your max zoom when you detect points are close to each other.

困难的方法是自己做数学。试着用工作CameraUpdateFactory.newLatLngZoomLatLng这些点和你的最大变焦之间的中心,当你检测点接近对方。