我在自定义应用程序中使用 MKMapView,并且希望在缩放过程中显示地图比例(卷尺),就像 Apple 的 Maps.app 一样。这可能吗?
如果没有,我会实现自己的地图比例尺,当 MKMapView 的缩放发生变化时,如何获得持续的更新信息?
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
似乎只在缩放开始时调用一次,而
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
仅在缩放结束时调用一次。
Maps.app 地图比例在缩放过程中实时显示和连续更新。
提前致谢。
我遇到了类似的问题,根据用户缩放获取camera.altitude,以显示在标签中。
由于没有“regionISChangingAnimated”等方法,只有WillChange和DidChange,所以我在WillChange处启动一个计时器,并在DidChange处使其无效。计时器调用一个方法 (updateElevationLabel) 来计算相机在地图上方的海拔高度。
但是,由于在调用regionDidChange之前不会计算camera.altitude,因此请使用zoomscale和地图的起始高度(zoomscale = 1.0并不总是等于altitude = 0m,这取决于您在世界的哪个位置)来计算当前高度。在下面的方法中,起始高度是一个浮点数,在加载时和每个区域更改时设置一次。
最后您可以更改海拔高度的格式,例如从 km 到 m 超过一定高度(10'000 米以下)。
对于老式学校:1m = 3.2808399 ft.
-(void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
if (showsElevation) {
//update starting height for the region
MKMapCamera *camera = map.camera;
CLLocationDistance altitude = camera.altitude;
MKZoomScale currentZoomScale = map.bounds.size.width / map.visibleMapRect.size.width;
float factor = 1.0/currentZoomScale;
startingHeight = altitude/factor;
elevationTimer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:@selector(updateElevationLabel)
userInfo:Nil
repeats:YES];
[elevationTimer fire];
}
}
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
[elevationTimer invalidate];
}
-(void)updateElevationLabel {
//1. create the label
if (!elevationLabel) {
elevationLabel = [UILabel new];
[elevationLabel setFrame:CGRectMake(0, 18, 200, 44)];
[elevationLabel setBackgroundColor:[UIColor redColor]];
[self addSubview:elevationLabel];
}
//2. grab the initial starting height (further updated on region changes)
if (startingHeight == 0) {
MKMapCamera *camera = map.camera;
CLLocationDistance altitude = camera.altitude;
MKZoomScale currentZoomScale = map.bounds.size.width / map.visibleMapRect.size.width;
float factor = 1.0/currentZoomScale;
startingHeight = altitude/factor;
}
//3. get current zoom scale and altitude, format changes
MKZoomScale currentZoomScale = map.bounds.size.width / map.visibleMapRect.size.width;
float altitude = startingHeight * (1/currentZoomScale);
if (altitude>10000) {
altitude = altitude/1000;
[elevationLabel setText:[NSString stringWithFormat:@"%.1fkm", altitude]];
} else {
[elevationLabel setText:[NSString stringWithFormat:@"%.0fm", altitude]];
}
}
来自Apple关于MKMapView的regionWillChangeAnimated:方法的文档(强调我的):
每当当前显示的地图区域时都会调用此方法 变化。滚动过程中,该方法可能会被多次调用 报告地图位置的更新。因此,您的实施 该方法应尽可能轻量级,以避免影响 滚动性能。
听起来您应该能够在地图视图滚动时连续使用此方法,这解决了您的部分问题 - 因此,当调用该方法时,请查看(我在这里猜测)地图视图的
region
属性和从中得出你的地图比例尺。
正如您所了解的,方法
func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool)
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool)
当您开始和结束缩放手势时触发。 但是使用委托方法
func mapViewDidChangeVisibleRegion(_ mapView: MKMapView)
当缩放发生变化时,您会获得持续更新。