IPhoneでMapKitを使用しています。ユーザーがズームレベルを変更したとき(マップをズームイン/ズームアウト)を知るにはどうすればよいですか?
mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated;を使用しようとしましたが、マップがドラッグされただけの場合でも呼び出されます。残念ながら、マップをドラッグすると、mapView.region.spanも変更されます...
助けて?
10倍
ズームレベルの計算は非常に簡単です。以下のスニペットを参照してください。 mRectパラメータは、visibleMapRect
インスタンスのMKMapView
プロパティから取得できます。
+ (NSUInteger)zoomLevelForMapRect:(MKMapRect)mRect withMapViewSizeInPixels:(CGSize)viewSizeInPixels
{
NSUInteger zoomLevel = MAXIMUM_ZOOM; // MAXIMUM_ZOOM is 20 with MapKit
MKZoomScale zoomScale = mRect.size.width / viewSizeInPixels.width; //MKZoomScale is just a CGFloat typedef
double zoomExponent = log2(zoomScale);
zoomLevel = (NSUInteger)(MAXIMUM_ZOOM - ceil(zoomExponent));
return zoomLevel;
}
ズームがまったく変更されたかどうかがわかるので、おそらくzoomScale
を計算するステップで停止することができます。
このトピックに関するTroyBrantsの優れたブログ投稿を読んで、このことを理解しました。
http://troybrant.net/blog/2010/01/mkmapview-and-zoom-levels-a-visual-guide/
Swift 3
extension MKMapView {
var zoomLevel: Int {
let maxZoom: Double = 20
let zoomScale = self.visibleMapRect.size.width / Double(self.frame.size.width)
let zoomExponent = log2(zoomScale)
return Int(maxZoom - ceil(zoomExponent))
}
}
私はこれが非常に役立つと感じ、これらの回答に基づいて次のコードを開発しました。
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
{
mapRegion = self.mapView.region;
}
-(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{
MKCoordinateRegion newRegion = self.mapView.region;
NSInteger zFactor;
if ((mapRegion.span.latitudeDelta/newRegion.span.latitudeDelta) > 1.5){
NSLog(@"Zoom in changed");
zFactor = 20;
CustomPlacemark *aO;
MKAnnotationView *aV;
for (aO in self.mapView.annotations) {
aV = [[self mapView] viewForAnnotation:aO];
aV.frame = CGRectMake(aV.frame.Origin.x, aV.frame.Origin.y, aV.frame.size.width+zFactor, aV.frame.size.height+zFactor);
[[[self mapView] viewForAnnotation:aO] setFrame:aV.frame];
}
}
if ((mapRegion.span.latitudeDelta/newRegion.span.latitudeDelta) < 0.75){
NSLog(@"Zoom out");
zFactor = -20;
CustomPlacemark *aO;
MKAnnotationView *aV;
for (aO in self.mapView.annotations) {
aV = [[self mapView] viewForAnnotation:aO];
aV.frame = CGRectMake(aV.frame.Origin.x, aV.frame.Origin.y, aV.frame.size.width+zFactor, aV.frame.size.height+zFactor);
[[[self mapView] viewForAnnotation:aO] setFrame:aV.frame];
}
}
}
次のMKMapViewカテゴリがあり、マップの現在のズームレベルをすばやく取得する方法が含まれています。
@implementation MKMapView (ZoomLevel)
- (NSUInteger) zoomLevel {
MKCoordinateRegion region = self.region;
double centerPixelX = [MKMapView longitudeToPixelSpaceX: region.center.longitude];
double topLeftPixelX = [MKMapView longitudeToPixelSpaceX: region.center.longitude - region.span.longitudeDelta / 2];
double scaledMapWidth = (centerPixelX - topLeftPixelX) * 2;
CGSize mapSizeInPixels = self.bounds.size;
double zoomScale = scaledMapWidth / mapSizeInPixels.width;
double zoomExponent = log(zoomScale) / log(2);
double zoomLevel = 21 - zoomExponent;
return zoomLevel;
}
@end
ズームレベルを取得するには、デリゲートで以下を呼び出して、ズームレベルが変更されたかどうかを確認します。
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
NSUInteger zoomLevel = [mapView zoomLevel];
}
はるかに簡単な答え:
現在のズームレベルの整数を取得する最も簡単な方法は、MapView関数regionDidChangeAnimatedを使用することです。この関数は、ズームのすべての変更を認識し、ズーム率の計算の基礎を提供します。
この関数をMapViewクラスに挿入するだけです(Swift 3.で動作します):
var mapView: MKMapView! = nil
...
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
let zoomWidth = mapView.visibleMapRect.size.width
let zoomFactor = Int(log2(zoomWidth)) - 9
print("...REGION DID CHANGE: ZOOM FACTOR \(zoomFactor)")
}
そして、それからzoomFactor値を取得します。ここで、0はマップにズームインできる最も近いポイントであり、より高い値はすべて遠く離れたズームです... :-)
mapView:regionDidChangeAnimated:
メソッドを聞くことができます。ただし、マップがアニメーション化されている場合でも、ズームレベルが変更されたかどうかはわかりません。
また、マップビューのregion
プロパティをリッスンする必要があります。これには、ズームレベルが変更されたかどうかを計算するために使用できるlatitudeDelta値とlongitudeDelta値が含まれています。
つまり、.hファイル内
@class MyMapViewController {
...
MKCoordinateRegion mapRegion;
}
@end
とあなたの.mファイルで
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
mapRegion = mapView.region;
}
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
newRegion = mapView.region;
if (mapRegion.span.latitudeDelta != newRegion.span.latitudeDelta ||
mapRegion.span.longitudeDelta != newRegion.span.longitudeDelta)
NSLog(@"The zoom has changed");
}
これにより、マップのズームが変更されたかどうかが検出されます。
ただし、地球は湾曲しているため、ズームの変更に注意する必要があります:(マップをスクロールすると、ユーザーがズームしたためではなく、地球の形状だけで緯度デルタと経度デルタがわずかに変化します。検出する必要がある場合があります。デルタの大きな変化とわずかな変化を無視します。
お役に立てば幸いです。
MKMapViewのズームスケールをカウント-Swiftソリューション
MKMapViewの次の拡張機能を作成したので、地図上でズームのスケールを取得できます。解決策は上記と同様ですが、Swiftを使用します。
F.exを除外できるようにするスケールを丸めるための追加の関数scaleWithPrecision(_:Int64)
もあります。 MapViewのズームの変更
extension MKMapView {
var scale: Double {
return self.scaleWithPrecision(1)
}
func scaleWithPrecision(precision: Int64) -> Double {
let mapBoundsWidth = Double(self.bounds.size.width)
let mapRectWidth:Double = self.visibleMapRect.size.width
let scale: Double = round(Double(precision)*mapBoundsWidth/mapRectWidth)/Double(precision)
return scale
}
}