【问题标题】:Set MKMapView region to center on two annotations将 MKMapView 区域设置为以两个注释为中心
【发布时间】:2010-10-29 14:25:03
【问题描述】:

我正在寻求一些帮助,以根据当前位置注释和我设置的注释完成一些关于在 MKMapView 上设置区域的代码。

我想计算两者之间的距离并设置两者之间的中心,然后缩小以使两者都在视图中。对我来说,它在模拟器中似乎工作正常,但不幸的是 userLocation.coordinate 固定在 Apple HQ 上。当我在设备上进行测试时,我看到了奇怪的行为。如果两个注释在同一纬度上有点水平,它通常会缩小并设置适当的区域,但如果垂直距离较大,则不能正确缩小。

我使用了找到 here 的代码,并进行了一些编辑以满足我的需要:

CLLocationCoordinate2D southWest = mapView.userLocation.coordinate;
CLLocationCoordinate2D northEast = southWest;

southWest.latitude = MIN(southWest.latitude, annotation.coordinate.latitude);
southWest.longitude = MIN(southWest.longitude, annotation.coordinate.longitude);

northEast.latitude = MAX(northEast.latitude, annotation.coordinate.latitude);
northEast.longitude = MAX(northEast.longitude, annotation.coordinate.longitude);

CLLocation *locSouthWest = [[CLLocation alloc] initWithLatitude:southWest.latitude longitude:southWest.longitude];
CLLocation *locNorthEast = [[CLLocation alloc] initWithLatitude:northEast.latitude longitude:northEast.longitude];

// This is a diag distance (if you wanted tighter you could do NE-NW or NE-SE)
CLLocationDistance meters = [locSouthWest distanceFromLocation:locNorthEast];

MKCoordinateRegion region;
region.center.latitude = (southWest.latitude + northEast.latitude) / 2.0;
region.center.longitude = (southWest.longitude + northEast.longitude) / 2.0;
region.span.latitudeDelta = meters / 111319.5;
region.span.longitudeDelta = 0.0;

MKCoordinateRegion savedRegion = [mapView regionThatFits:region];
[mapView setRegion:savedRegion animated:YES];

[locSouthWest release];
[locNorthEast release];

让我困惑的一件事是他说northEast = southWest...

提前感谢任何获得帮助和意见的人:)

【问题讨论】:

    标签: objective-c mkmapview mkannotation


    【解决方案1】:

    对于 iOS7 转发,最好的方法是:

    //from API docs: 
    //- (void)showAnnotations:(NSArray *)annotations animated:(BOOL)animated NS_AVAILABLE(10_9, 7_0);
    [self.mapView showAnnotations:self.mapView.annotations animated:YES];
    

    对于我的个人项目(iOS7 之前),我只是在 MKMapView 类上添加了一个类别来封装“可见区域”功能,用于一个非常常见的操作:将其设置为能够查看当前加载的所有注释MKMapView 实例(这包括您可能放置的尽可能多的图钉,以及用户的位置)。结果是这样的:

    .h 文件

    #import <MapKit/MapKit.h>
    
    @interface MKMapView (Extensions)
    
    -(void)ij_setVisibleRectToFitAllLoadedAnnotationsAnimated:(BOOL)animated;
    -(void)ij_setVisibleRectToFitAnnotations:(NSArray *)annotations animated:(BOOL)animated;
    
    
    @end
    

    .m 文件

    #import "MKMapView+Extensions.h"
    
    @implementation MKMapView (Extensions)
    
    /**
     *  Changes the currently visible portion of the map to a region that best fits all the currently loadded annotations on the map, and it optionally animates the change.
     *
     *  @param animated is the change should be perfomed with an animation.
     */
    -(void)ij_setVisibleRectToFitAllLoadedAnnotationsAnimated:(BOOL)animated
    {
        MKMapView * mapView = self;
    
        NSArray * annotations = mapView.annotations;
    
        [self ij_setVisibleRectToFitAnnotations:annotations animated:animated];
    
    }
    
    
    /**
     *  Changes the currently visible portion of the map to a region that best fits the provided annotations array, and it optionally animates the change.
        All elements from the array must conform to the <MKAnnotation> protocol in order to fetch the coordinates to compute the visible region of the map.
     *
     *  @param annotations an array of elements conforming to the <MKAnnotation> protocol, holding the locations for which the visible portion of the map will be set.
     *  @param animated    wether or not the change should be perfomed with an animation.
     */
    -(void)ij_setVisibleRectToFitAnnotations:(NSArray *)annotations animated:(BOOL)animated
    {
        MKMapView * mapView = self;
    
        MKMapRect r = MKMapRectNull;
        for (id<MKAnnotation> a in annotations) {
            ZAssert([a conformsToProtocol:@protocol(MKAnnotation)], @"ERROR: All elements of the array MUST conform to the MKAnnotation protocol. Element (%@) did not fulfill this requirement", a);
            MKMapPoint p = MKMapPointForCoordinate(a.coordinate);
            //MKMapRectUnion performs the union between 2 rects, returning a bigger rect containing both (or just one if the other is null). here we do it for rects without a size (points)
            r = MKMapRectUnion(r, MKMapRectMake(p.x, p.y, 0, 0));
        }
    
        [mapView setVisibleMapRect:r animated:animated];
    
    }
    
    @end
    

    如您所见,到目前为止,我添加了 2 种方法:一种用于将地图的可见区域设置为适合 MKMapView 实例上所有当前加载的注释的区域,另一种用于将其设置为任何数组的方法的对象。 因此,要设置 mapView 的可见区域,代码将非常简单:

       //the mapView instance  
        [self.mapView ij_setVisibleRectToFitAllLoadedAnnotationsAnimated:animated]; 
    

    希望对你有帮助=)

    【讨论】:

      【解决方案2】:

      不要被前两行吓到,你可以忽略 = 符号的右边,因为它会在下面被覆盖...

      我认为问题就在这里:

      region.span.longitudeDelta = 0.0;
      

      【讨论】:

      • 是的,上面 Aaron 的链接正确计算了增量,并且似乎已经解决了它。只需要对额外边距进行一些调整,但代码很完美!
      【解决方案3】:

      Swift 4 版本Robertibiris 答案:

      mapView.showAnnotations(mapView.annotations, animated: true)
      

      【讨论】:

        【解决方案4】:

        这篇博文可能会为您提供所需的洞察力

        http://codisllc.com/blog/zoom-mkmapview-to-fit-annotations/

        -(void)zoomToFitMapAnnotations:(MKMapView*)mapView
        {
            if([mapView.annotations count] == 0)
                return;
        
            CLLocationCoordinate2D topLeftCoord;
            topLeftCoord.latitude = -90;
            topLeftCoord.longitude = 180;
        
            CLLocationCoordinate2D bottomRightCoord;
            bottomRightCoord.latitude = 90;
            bottomRightCoord.longitude = -180;
        
            for(MapAnnotation* annotation in mapView.annotations)
            {
                topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude);
                topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude);
        
                bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude);
                bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude);
            }
        
            MKCoordinateRegion region;
            region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5;
            region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5;
            region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1; // Add a little extra space on the sides
            region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.1; // Add a little extra space on the sides
        
            region = [mapView regionThatFits:region];
            [mapView setRegion:region animated:YES];
        }
        

        【讨论】:

        猜你喜欢
        • 2013-01-30
        • 1970-01-01
        • 1970-01-01
        • 2011-05-06
        • 1970-01-01
        • 1970-01-01
        • 2013-01-05
        • 1970-01-01
        • 2011-09-04
        相关资源
        最近更新 更多