在MKMapView中平滑跟随用户的位置

时间:2011-02-17 15:24:12

标签: objective-c cocoa-touch mkmapview

我想像谷歌地图一样关注用户的蓝点。这意味着当位置发生变化时,地图(或它的中心)应该顺利地跟随它。但是当我使用委托的标准方式时:

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
    [map setCenterCoordinate:map.userLocation.coordinate animated:YES];
}

mapview.userLocation上的keyvalue观察者然后移动地图非常“波涛汹涌”,即使我使用animated参数,它也会快速“跳转”到新位置。

此外,我认为蓝点本身并不像原生谷歌地图应用程序那样流畅,并且经常跳转到新位置而不是移动到那里。

感谢您的帮助。

3 个答案:

答案 0 :(得分:3)

'hi Jak

我也试图解决这个问题,但看起来MKMapView可能会在更新之间使用一些奇特的东西来预测下一个位置并使运动更加平滑。

如果你看看他们处理罗盘的方式,他们会进行大量的过滤,因为原始罗盘数据并不十分稳定,因此它们非常光滑和平滑。

此外,请注意跟踪时您可以缩放但不能平移。即使滚动关闭,我也无法在我的应用程序中复制此功能,如果您将手指放大,它仍会在您缩放时滚动。

我猜他们不会暴露一切只是为了保持领先于我们:) d

答案 1 :(得分:1)

我使用CLLocationManager委托更新方法来获取每秒的当前位置,保存前一个位置并在这些位置之间进行插值。这是一个更多的努力,但t使跟踪更顺畅。这是我的代码:

#define zoomSpan MKCoordinateSpanMake(0.001f, 0.001f)

@property (strong, nonatomic) CLLocation *lastLocation;
@property (strong, nonatomic) MKMapView *mapView;
@property (strong, nonatomic) CLLocationManager *locationManager;

...

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    CLLocation *currentLocation = locations[locations.count - 1];
    // Set to last location, for faster setting to correct position
    [self.mapView setRegion:MKCoordinateRegionMake(self.lastLocation.coordinate, zoomSpan) animated:NO];

    // Locations in-between coordinates for smooth tracking
    CLLocationDegrees deltaLat = currentLocation.coordinate.latitude - self.lastLocation.coordinate.latitude;
    CLLocationDegrees deltaLon = currentLocation.coordinate.longitude - self.lastLocation.coordinate.longitude;
    NSArray *locationsArray = @[[[CLLocation alloc] initWithLatitude:(self.lastLocation.coordinate.latitude + deltaLat * 0.2)
                                                           longitude:(self.lastLocation.coordinate.longitude + deltaLon * 0.2)],
                                [[CLLocation alloc] initWithLatitude:(self.lastLocation.coordinate.latitude + deltaLat * 0.4)
                                                           longitude:(self.lastLocation.coordinate.longitude + deltaLon * 0.4)],
                                [[CLLocation alloc] initWithLatitude:(self.lastLocation.coordinate.latitude + deltaLat * 0.6)
                                                           longitude:(self.lastLocation.coordinate.longitude + deltaLon * 0.6)],
                                [[CLLocation alloc] initWithLatitude:(self.lastLocation.coordinate.latitude + deltaLat * 0.8)
                                                           longitude:(self.lastLocation.coordinate.longitude + deltaLon * 0.8)],
                                currentLocation];

    float timer = 0;
    for (CLLocation *nextLocation in locationsArray) {
        [self performSelector:@selector(updateMapCenterLocation:) withObject:nextLocation afterDelay:timer];
        timer += 0.2;
    }
    self.lastLocation = currentLocation;
}

- (void)updateMapCenterLocation:(CLLocation *)location
{
    [self.mapView setRegion:MKCoordinateRegionMake(location.coordinate, zoomSpan) animated:YES];
}

确保您正在使用此类的类(通常是包含地图视图的视图控制器)设置为CLLocationManager的委托并实施CLLocationManagerDelegate协议。

其他一些评论:

  • 此代码的行为类似于MKUserTracking,但这不支持自定义设置缩放级别。在开始跟踪时似乎有一个错误重置缩放级别,因此这种解决方法。
  • zoomSpan目前已修复,但您也可以将当前区域的范围与self.mapView.region.span一起使用。

答案 2 :(得分:0)

你也可以试试这个:

- (void)adjustRegion:(CLLocation*)location {
    MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(location.coordinate, 150.0, 150.0);
    MKCoordinateRegion adjustedRegion = [self.mapView regionThatFits:viewRegion];
    [self.mapView setRegion:adjustedRegion animated:YES];
}
相关问题