在地图视图的可见矩形内显示MKMapViewAnnotations [英] Display MKMapViewAnnotations within a map view's visible rect

查看:199
本文介绍了在地图视图的可见矩形内显示MKMapViewAnnotations的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在路径样式的视差表视图标题中显示一个MKMapView。要创建效果,mapView边界大于用户可见的区域。我需要设置地图视图区域,以便所有地图的注释都包含在MKMapView的可见直角中。什么是最好的方法?





为了清楚起见,编辑以下是一个用例。 mapView大小为320×380.可见区域由rect(0.0,20.0,320.0,100.0)定义。我需要设置区域,使所有注释出现在mapView内的这个rec​​t中。

解决方案

设置地图区域,以便所有注释都包含在 MKMapView 可以三步完成。输入是 mapView annotationsFrame


  1. 计算包含所有注释的 MKMapRect mapRect

  2. mapView.bounds annotationsFrame 中计算填充插值。

  3. 在地图视图中调用 -setVisibleMapRect:edgePadding:animated:

是一个测试的屏幕截图。红色重叠显示 annotationsFrame





这是代码。 当心:简单的方法是将其添加到代码中,并且不对边缘案例进行测试,例如传递具有相同坐标的n个注释,或者具有注释到目前为止,地图必须被放大太多,或坐标跨越地图的边缘,经度为+/- 180度。



<$ p $动画(BOOL)动画
{
如果(_mapView.annotations.count< 2) )返回


//步骤1:制作包含所有注释的MKMapRect

NSArray * annotations = _mapView.annotations;

id< MKAnnotation> firstAnnotation = [annotations objectAtIndex:0];
MKMapPoint minPoint = MKMapPointForCoordinate(firstAnnotation.coordinate);
MKMapPoint maxPoint = minPoint;

for(id< MKAnnotation>注解注释){
MKMapPoint point = MKMapPointForCoordinate(annotation.coordinate);
if(point.x< minPoint.x)minPoint.x = point.x;
if(point.y< minPoint.y)minPoint.y = point.y;
if(point.x> maxPoint.x)maxPoint.x = point.x;
if(point.y> maxPoint.y)maxPoint.y = point.y;
}

MKMapRect mapRect = MKMapRectMake(minPoint.x,minPoint.y,maxPoint.x - minPoint.x,maxPoint.y - minPoint.y);


//步骤2:计算边缘填充

UIEdgeInsets edgePadding = UIEdgeInsetsMake(
CGRectGetMinY(annotationsFrame),
CGRectGetMinX(annotationsFrame ),
CGRectGetMaxY(mapBounds) - CGRectGetMaxY(annotationsFrame),
CGRectGetMaxX(mapBounds) - CGRectGetMaxX(annotationsFrame)
);


//步骤3:设置地图rect

[mapView setVisibleMapRect:mapRect edgePadding:edgePadding animated:animated];
}

如果你去一个完美的位置(和谁不),这里有三件事要考虑:


  1. 代码保证所有坐标都在 annotationsFrame ,但注释本身可能在外面。为了防止这种情况,只需使用更多的填充。例如,如果您的注释为20x20,并以坐标为中心,请在所有方面使用10个以上的填充。

  2. 在iOS 7下方,地图未缩放到完美的缩放比例,但是下一个瓷砖尺寸(两个电源)。所以在注释的周围会有更多的空间,如屏幕截图所示。

  3. 在iOS 7中,地图视图不仅可以完美放大,还可以自动关注状态栏。要使计算正确,您需要从iOS 7顶部的填充中减去状态栏的高度。


I'm displaying an MKMapView inside a Path-style parallax table view header. To create the effect, the mapView bounds is larger than the area visible to the user. I need to set the map view region such that all the map's annotations are contained within the visible rect of MKMapView. What's the best way to do this?

Edit for clarity: Here's a use-case. The mapView size is 320 x 380. The visible area, however, is defined by the rect (0.0, 20.0, 320.0, 100.0). I need to set the region such that all the annotations appear in this rect within the mapView.

解决方案

Setting the map region so that all annotations are contained in a certain part of an MKMapView can be done in three steps. Input are the mapView and the annotationsFrame.

  1. Calculate an MKMapRect mapRect that contains all annotations.
  2. Calculate the padding insets from mapView.bounds and annotationsFrame.
  3. Call -setVisibleMapRect:edgePadding:animated: on the map view.

Below is a screen shot of a test. The red overlay shows the annotationsFrame.

Here is the code. Beware: It's all in one method to simplify adding it to your code, and it is not tested for edge cases like passing in n annotations with the same coordinate, or having the annotations so far apart that the map would have to get zoomed out too much, or having coordinates that span the edge of the map at +/-180 degrees longitude.

- (void)zoomAnnotationsOnMapView:(MKMapView *)mapView toFrame:(CGRect)annotationsFrame animated:(BOOL)animated
{
    if (_mapView.annotations.count < 2) return;


    // Step 1: make an MKMapRect that contains all the annotations

    NSArray *annotations = _mapView.annotations;

    id <MKAnnotation> firstAnnotation = [annotations objectAtIndex:0];
    MKMapPoint minPoint = MKMapPointForCoordinate(firstAnnotation.coordinate);
    MKMapPoint maxPoint = minPoint;

    for (id <MKAnnotation> annotation in annotations) {
        MKMapPoint point = MKMapPointForCoordinate(annotation.coordinate);
        if (point.x < minPoint.x) minPoint.x = point.x;
        if (point.y < minPoint.y) minPoint.y = point.y;
        if (point.x > maxPoint.x) maxPoint.x = point.x;
        if (point.y > maxPoint.y) maxPoint.y = point.y;
    }

    MKMapRect mapRect = MKMapRectMake(minPoint.x, minPoint.y, maxPoint.x - minPoint.x, maxPoint.y - minPoint.y);


    // Step 2: Calculate the edge padding

    UIEdgeInsets edgePadding = UIEdgeInsetsMake(
        CGRectGetMinY(annotationsFrame),
        CGRectGetMinX(annotationsFrame),
        CGRectGetMaxY(mapBounds) - CGRectGetMaxY(annotationsFrame),
        CGRectGetMaxX(mapBounds) - CGRectGetMaxX(annotationsFrame)
    );


    // Step 3: Set the map rect

    [mapView setVisibleMapRect:mapRect edgePadding:edgePadding animated:animated];
}

If you go for a perfect placement (and who doesn't), here are three things to consider:

  1. The code assures that all the coordinates are in the annotationsFrame, but the annotations themselves may be outside. To prevent that, simply use more padding. For example, if your annotations are 20x20 and centered on the coordinate, use 10 more padding on all sides.
  2. Below iOS 7, the map was not zooming to the perfect zoom scale, but to the next tile size (power of two). So there will be more space around the annotations than needed, just as shown on the screenshot.
  3. On iOS 7, the map view will not only zoom perfectly, but automatically care about the status bar. To make the calculation correct, you need to subtract the status bar height from the top padding on iOS 7.

这篇关于在地图视图的可见矩形内显示MKMapViewAnnotations的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆