【问题标题】:MKMapView zoom to fit annotations while locking centerMKMapView 在锁定中心时缩放以适应注释
【发布时间】:2015-07-08 23:16:27
【问题描述】:

我正在尝试缩放以适应地图上的注释,同时锁定中心并提供一些插图。

- (void)fitAnnotations:(NSArray *)annotations edgeInsets:(UIEdgeInsets)insets
{
    CLLocationCoordinate2D originalCenter = self.centerCoordinate;
    MKMapRect mapRect = MKMapRectNull;

    for (id<MKAnnotation> annotation in annotations) {
        MKMapPoint p = MKMapPointForCoordinate([annotation coordinate]);
        mapRect = MKMapRectUnion(mapRect, MKMapRectMake(p.x, p.y, 0, 0));
    }

    mapRect = [self mapRectThatFits:mapRect edgePadding:insets];
    MKCoordinateRegion mapRegion = MKCoordinateRegionForMapRect(mapRect);

    // we now try to go back to the original center, while increasing the span by neccessary amount
    MKCoordinateSpan centeringDelta = MKCoordinateSpanMake(fabs(mapRegion.center.latitude - originalCenter.latitude), fabs(mapRegion.center.longitude - originalCenter.longitude));
    mapRegion.center = originalCenter;
    mapRegion.span.latitudeDelta += centeringDelta.latitudeDelta * 2.0;
    mapRegion.span.longitudeDelta += centeringDelta.longitudeDelta * 2.0;
    mapRegion = [self regionThatFits:mapRegion];
    [self setRegion:mapRegion animated:YES];
}

此处代码的第一部分按预期工作:它在尊重插图的同时缩放以适应。但是,它会移动中心。

之后我尝试重新调整中心,但失败了。我不确定我关于重新居中的数学是否正确。

【问题讨论】:

  • 您是否尝试过使用MKCoordinateRegionMake 创建新的地图区域?这将允许您传入centerCoordinatespan
  • @rmp 是的,但是当您移动中心时,您确保适合的一些注释现在超出了范围。
  • 你应该可以在原来的中心通过而不是移动它
  • 如果 (0,0) 上有注释并且我将中心移动 (0, -5),那么顶部注释现在将位于 (0, -5)。这是我要避免的。
  • 如果你将新计算的spancenterCoordinate 一起传递,MKCoordinateRegionMake 应该处理好这个

标签: ios mkmapview


【解决方案1】:

计算适合注释的边界图矩形的代码的第一部分是可以的。

只需要校正那个“最小”的地图矩形,使“锁定”的中心实际上在中心。

我认为,主要问题是问题中的代码正在调整跨度,以便在调用 mapRectThatFits: 后重新居中区域并考虑插入(它本身已经给出了稍微修改的版本纠正你实际要求的)。

相反,您的代码应该只计算它想要然后最终调用setVisibleMapRect:edgePadding:animated:的实际最小矩形,并让地图视图找出“矩形”适合”和插图。

请尝试以下方法:

- (void)fitAnnotations:(NSArray *)annotations edgeInsets:(UIEdgeInsets)insets
{
    MKMapPoint centerMapPoint = MKMapPointForCoordinate(originalCenter);

    //--- First create minimal bounding map rect to tightly fit annotations...
    MKMapRect minimalMapRect = MKMapRectNull;

    for (id<MKAnnotation> annotation in annotations) {
        MKMapPoint annMapPoint = MKMapPointForCoordinate(annotation.coordinate);
        minimalMapRect = MKMapRectUnion(minimalMapRect, MKMapRectMake(annMapPoint.x, annMapPoint.y, 0, 0));
    }


    //--- Now create adjusted map rect so center coordinate is in the center...

    //distance of desired center from minimal left edge...
    double centerXOffset = centerMapPoint.x - minimalMapRect.origin.x;

    //raw amount width needs to be adjusted to get center in center...
    //negative/positive indicates whether center is in left/right half
    double widthOffset = 2.0 * centerXOffset - minimalMapRect.size.width;

    //add absolute value of raw width offset to minimal width...
    double adjustedWidth = minimalMapRect.size.width + fabs(widthOffset);

    //distance of desired center from minimal top edge...
    double centerYOffset = centerMapPoint.y - minimalMapRect.origin.y;

    //raw amount height needs to be adjusted to get center in center...
    //negative/positive indicates whether center is in top/bottom half
    double heightOffset = 2.0 * centerYOffset - minimalMapRect.size.height;

    //add absolute value of raw height offset to minimal height...
    double adjustedHeight = minimalMapRect.size.height + fabs(heightOffset);

    //adjust origin if necessary (if center is in top/left half)...
    MKMapPoint adjustedOrigin = minimalMapRect.origin;
    if ((centerXOffset / minimalMapRect.size.width) < 0.5)
    {
        adjustedOrigin.x = adjustedOrigin.x + widthOffset;
    }
    if ((centerYOffset / minimalMapRect.size.height) < 0.5)
    {
        adjustedOrigin.y = adjustedOrigin.y + heightOffset;
    }

    //create adjusted MKMapRect...
    MKMapRect adjustedMapRect = MKMapRectMake(adjustedOrigin.x, adjustedOrigin.y, adjustedWidth, adjustedHeight);


    //--- Apply the adjusted map rect with insets to map view...
    [mapView setVisibleMapRect:adjustedMapRect edgePadding:insets animated:YES];
}

【讨论】:

  • 然而问题是setVisibleMapRect:edgePadding 使用插图会改变原来的中心,这样矩形就会被这些插图移动。我尝试了这段代码,每次调用它时,中心都会发生变化,但是,所有注释都适合屏幕。中心向北移动,而注释向南移动,因此地图缩小了,但两者仍然可见。应该发生的是中心保持固定并且地图缩小/缩小以适应合适的注释。
【解决方案2】:

尝试类似的方法,使用计算出的 mapRect 通过 MKCoordinateRegionMake 方法使用 originalCenter 创建新区域

MKCoordinateRegion mapRegion = MKCoordinateRegionForMapRect(mapRect);
mapRegion = MKCoordinateRegionMake(originalCenter, mapRegion.span);
mapView.region = mapRegion;

【讨论】:

  • 这不起作用。计算矩形以适合所有注释,直到边缘。当您通过 delta 将中心重新对齐到不同的坐标时,这意味着您将整个矩形移动该 delta,这意味着它可能会排除拟合的注释。
  • 我相信你计算的 mapRect 不正确,你需要得到离中心最远的点的距离,并用它来设置你的跨度。
【解决方案3】:

试试这个。

MKMapPoint center = MKMapPointForCoordinate(self.mapView.centerCoordinate);

double maxX = 0;
double maxY = 0;
for (MKPointAnnotation *a in self.mapView.annotations)
{
    MKMapPoint p = MKMapPointForCoordinate(a.coordinate);
    double deltaX = fabs(center.x - p.x);
    double deltaY = fabs(center.y - p.y);
    maxX = MAX(maxX, deltaX);
    maxY = MAX(maxY, deltaY);
}


MKMapRect rect = MKMapRectMake(center.x - maxX, center.y - maxY, maxX * 2, maxY * 2);
rect = [self.mapView mapRectThatFits:rect edgePadding:UIEdgeInsetsMake(20, 20, 20, 20)];

[self.mapView setVisibleMapRect:rect animated:1];

【讨论】:

  • 任何时候你做mapRectThatFits:rect edgePadding:,中心都会被忽略。这行不通。
【解决方案4】:

@moby 我正在考虑一种不同的方法。像您已经做的那样获取地图中心位置怎么样。现在计算从该中心坐标到每个注释的距离,直到找到最长的注释(比如 'requiredDistance' )。 使用以下代码获取一个新的地图矩形,其中所有注释都绘制在同一中心:

    MKCircle *circleLine = [MKCircle circleWithCenterCoordinate:self.centerCoordinate radius:requiredDistance];
    [self.mapView setVisibleMapRect:circleLine.boundingMapRect];

来到你的插图,你想要应用的任何插图都应该应用于你的“requiredDistance”变量,这样你的“requiredDistance”变量的值总是大于或等于你的中心坐标和你的中心坐标之间的距离最长的注释,以确保所有注释始终可见。

【讨论】:

  • 如何将插图应用到 requiredDistance?这正是我们在这里想要弄清楚的。
猜你喜欢
  • 2011-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-22
  • 2010-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多