4

当一个人触摸 MKPolylineView 时,有什么方法可以显示标注?我试图添加一个 UITapGestureRecognizer 并在选择器中显示某个坐标的标注。但没有用。有什么建议吗?

以下是我尝试的方法

 - (MKOverlayView *)mapView:(MKMapView *)mapa viewForOverlay:(id <MKOverlay>)overlay
        self.polylineView = [[MKPolylineView alloc] initWithPolyline: self.polyline];
        self.polylineView.strokeColor = [UIColor blackColor];
        self.polylineView.lineWidth = 5.0;
        self.polylineView.alpha = 0.7;
        UITapGestureRecognizer *touchOnView = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(addBubble:)];
        [touchOnView setNumberOfTapsRequired:1];
        [touchOnView setNumberOfTouchesRequired:1];
        [self.polylineView addGestureRecognizer:touchOnView];
4

1 回答 1

8

非常有趣的问题 - 我什至从未想过将手势识别器放在地图叠加层上。通过一些实验,我已经验证可以检测到MKPolylineView. 正如您所发现的,点击手势不适用于地图叠加层。因此,我将点击手势放在MKMapView而不是放在MKPolylineView. 然后处理水龙头:

- (void)handleTapGesture:(UIGestureRecognizer*)gestureRecognizer
{
    if (measureLine != nil)
    {
        UIView* hitView = [self.polylineView hitTest:[gestureRecognizer locationInView:self.polylineView] withEvent:nil];
    }
}

hitView如果您的水龙头在 外面,则为零MKPolylineView,或者self.polylineView如果水龙头在里面,则为零。

但是,这可能不像您希望的那样表现。对于水平和垂直线,它完美地工作,因为底层视图的大小与线的大小大致相同。但是对于 45 度线,底层视图必须比线大得多,因为它是轴对齐边界框 (AABB)。如果您考虑 45 度线,仅使用水平线和垂直线将其包围,您最终会得到一个很大的区域 - 比您想要检测到的水龙头大得多。

例如

--------
|    / |
|   /  |
|  /   |
| /    |
|/     |
--------

但是使用敲击手势或点击测试总是会导致识别这些 AABB 内的敲击。因此,无论您尝试将手势附加到何处 - 例如,您尝试将手势附加到MKPolylineViewMKMapView,您都会得到虚假的结果。对于较长的线,问题会变得更糟 - 如果您想象一条线从地图视图的右上角到左下角,那么您需要将其包围的 AABB 将覆盖地图视图的整个区域,这意味着点击左上角或右下角将被解释为点击MKPolylineView.

为了解决这个问题,我建议采用以下方法:

  • 在地图视图上使用点击手势识别器
  • 在您处理水龙头的方法中:
    • 将屏幕点击位置转换为地图坐标
    • 循环遍历每条折线(除非您只有 1 条)
    • 对于折线中的每个点,取将该点连接到下一个点的线段,并计算地图坐标与这条线的距离。使用三角函数来计算。
      • 如果距离非常接近此段,则停止检查其余段并处理您想要显示的任何标注等
      • 如果距离不近,则移动到下一个点以及将其连接到下一个点的线段

无论多段线的长度或它们的角度如何,这种方法都可以保证工作。没有 AABB 的担忧。缺点是所有这些距离计算可能在计算上很昂贵 - 因此,如果您的折线由大量点组成,或者如果您有大量折线,那么您可能无法进行所有这些计算在不阻止 UI 响应的情况下,这意味着您需要将其移动到后台线程中。如果您只有几条折线,和/或它们由几个点组成,那么您会没事的。

于 2012-04-19T14:32:06.603 回答