私の検索で答えが見つかりませんでした。SOにいくつかの答えがありますが、それらは私にはうまくいきませんでした。
マップ上に2つのマーカーがあり、カメラを適切なズームレベルにズームして両方を含めるためにLatLngBounds Builderを使用しています。 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);
一定レベルのズームを強制する方法はありますが、その後、カメラはズームしませんか?これにより、地図の拡大/縮小が回避されます。基本的に、ズームレベルとして15.0fを使用しています。ポイントが遠すぎる場合は、ズームを両方に合わせたいです。ポイントが近づいている場合、ズームレベルが15.0fを超えないようにします。
同様のケースがあり、少なくとも2キロメートルの対角線マップが必要です。したがって、ビルダーに2つの追加ポイントを追加するだけです。最初の境界の中心から北西に最初の1 km、中心から南東に2番目の地点です。これらが境界内にある場合、何も変更されません。元の境界の外側にある場合は、境界を意味のあるサイズに増やします。
完全なコード例を次に示します。
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);
}
User2808624の回答に従ってこのソリューションを実装しましたが、計算を行うために Android Maps Utility Library の SphericalUtil を使用しました。
final double HEADING_NORTH_EAST = 45;
final double HEADING_SOUTH_WEST = 215;
LatLng center = tmpBounds.getCenter();
LatLng norhtEast = SphericalUtil.computeOffset(center, 709,HEADING_NORTH_EAST);
LatLng southWest = SphericalUtil.computeOffset(center, 709,HEADING_SOUTH_WEST );
ser2808624 の answer に基づいたはるかに短いバージョンを次に示します。
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();
少しずさんですが、0.001で都市ブロック以上、0.01で都市ビュー以上にズームできます。唯一の利点は、コードが4行だけ追加されることです。
遅くなりますが、誰かが私と同じ問題を抱えている可能性があります:LatLngBounds.Builderではなく、Placeから境界を受け取りました:
Location.distanceBetween(...)を使用して、境界が小さすぎるかどうかを確認し、境界の中心で最小ズームレベルを使用します。
if (areBoundsTooSmall(bounds, 300)) {
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(bounds.getCenter(), 17));
} else {
mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 20));
}
チェック方法は次のとおりです。
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;
}
最小ズームレベル17とパディング20を使用して、境界が小さすぎます。小さすぎると、メーター300の最小距離で決まります。必要に応じて数値を調整できます。
Googleは、最大/最小ズームレベルを制限するためのAPIを追加しました。
GoogleMap.setMaxZoomPreference()
GoogleMap.setMinZoomPreference()
簡単です:
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));
非表示のマップフラグメントを作成し、それを使用してズーム/境界を決定することを検討しましたか?これは明らかに計算上では最良ではありませんが、おそらく最も簡単で最も正確なソリューションです。たとえば、極の近くで経度0度で動作する数学的なソリューションを作成するのは複雑です(気になる場合)。マップを使用する場合、それはすでにすべて組み込まれています。既存のマップでこのソリューションを使用することもできますが、ユーザーにはバウンスが表示されます。
方法は次のとおりです。
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()
}
これは通常、UtilsまたはExtensionsファイルにあり、次のようにどこからでも使用できます。
var bounds = builder.build() //To include all your existing points.
bounds = builder.createBoundsWithZoomMaintained(bounds) //Updated bounds.
mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 10))
クイックフィックスは:
gMap.setOnMapLoadedCallback(this);
CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, padding);
gMap.setMaxZoomPreference(10);
gMap.animateCamera(cu);
@Override
public void onMapLoaded() {
gMap.resetMinMaxZoomPreference();
}
マップが完全にリロードされるまでズームを停止できることに注意してください。しかし、簡単な修正として機能します。
4.0.30の時点でズームレベルを制限する方法はありませんが、 この問題 を追跡できます。
簡単な方法は、このビデオのようにズームレベルを強制することです。 http://www.youtube.com/watch?v=-nCZ37HdheY
基本的に、特定のズームレベルに到達すると、animateCamera
を呼び出します。
ユーザーが開始していない2つのアニメーションがあるため、これは少し奇妙に見えます。
難しい方法は、自分で計算することです。 CameraUpdateFactory.newLatLngZoom
は、これらのポイント間の中心としてLatLng
を使用し、ポイントが互いに近接していることを検出した場合の最大ズーム。