【问题标题】:Smooth following of user's location in MKMapView在 MKMapView 中平滑跟踪用户的位置
【发布时间】:2011-02-17 15:24:11
【问题描述】:

我想以与 Google 地图相同的方式关注用户的蓝点。这意味着当位置发生变化时,地图(或它的中心)应该平滑地跟随它。但是当我对委托使用标准方式时:

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

mapview.userLocation 上的键值观察者然后地图的移动非常“不稳定”,即使我使用animated 参数,它也会迅速“跳转”到新位置。

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

感谢您的帮助。

【问题讨论】:

  • iOS 5 在跟踪模式中添加了此功能。终于!

标签: objective-c cocoa-touch mkmapview


【解决方案1】:

'嗨杰克

我也尝试过解决这个问题,但看起来 MKMapView 可能在更新之间使用了一些花哨的东西来预测下一个位置并使移动更平滑。

如果您查看他们处理指南针的方式,他们会进行大量过滤,因为原始指南针数据不是非常稳定,因此它们非常流畅。

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

我想他们不会为了抢在我们前面而暴露一切 :) D

【讨论】:

  • 好吧,我得出了同样的结论。 ;o) 地图应用程序必须使用一些我们不能使用的私有方法。我还尝试将setCenterCoordinate:animated: 放到 UIView 动画中,但没有任何效果。
【解决方案2】:

我使用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 协议。

一些额外的 cmets:

  • 此代码的行为类似于MKUserTracking,但不支持自定义设置缩放级别。开始跟踪时重置缩放级别似乎存在错误,因此采用了此解决方法。
  • zoomSpan 目前是固定的,但您也可以将当前区域的跨度与 self.mapView.region.span 一起使用。

【讨论】:

    【解决方案3】:

    你也可以试试这个:

    - (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];
    }
    

    【讨论】:

    • @ShivanRaptor 哦,那是我保存了一些参数的单例类。只需复制并粘贴该行。对不起,我会编辑我的答案。
    • @Lego 不会强制用户使用您定义的缩放级别吗? (而不是让他们自定义定义)
    • @RonLugge 好吧,当然你可以通过听具体的委托方法来动态设置缩放级别,mmmmmmh 我认为是'mapView:regionDidChangeAnimated:'。
    猜你喜欢
    • 2013-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-18
    • 1970-01-01
    • 2016-03-09
    相关资源
    最近更新 更多