示例中心
功能在线体验
menu 导航 closed 关闭

Overlay点击选中功能

该示例展示了如何对Overlay进行点击选中操作。
00:00 / 01:00
扫描二维码在手机端体验功能
体验移动端 扫码体验移动端

使用场景

如果需要对自己绘制的Overlay进行点击选中,则可以利用该功能完成。

比如界面上展示了多个用户的运动轨迹,利用该功能可以点选其中一个、或几个用户的轨迹突出展示。

用到产品

iOS 地图 SDK

核心类/接口

接口

说明

版本

SelectableOverlay

---

实现协议,自定义的可选中Overlay

---

---

BOOL isOverlayWithLineWidthContainsPoint(id overlay, double mapPointDistance, MAMapPoint mapPoint);

判断点point是否在Overlay图形内

---

核心难点

使用教程

1、实现对MAOverlay的点击

ClickOverlay文件夹下的代码可以支持实现MAOverlay的点击,包括MAPolygon、MAPolyline、MACircle。

Utility提供如下方法判断点point是否在Overlay图形内:

采用Swift语言构建时可复用Object-C内容。


BOOL isOverlayWithLineWidthContainsPoint(id<MAOverlay> overlay, double mapPointDistance, MAMapPoint mapPoint)

2、其中参数mapPointDistance提供了Overlay的线宽(需换算到MAMapPoint坐标系)。对非封闭图形MAPolyline,若点距MAPolyline的距离小于距离门限,则认为点在图形内。距离门限设置为4倍mapPointDistance。

举个例子,判断点touchLocation是否在selectableOverlay内:

采用Swift语言构建时可复用Object-C内容。


// 把屏幕坐标转换为MAMapPoint坐标.
MAMapPoint mapPoint = MAMapPointForCoordinate([self.mapView convertPoint:touchLocation toCoordinateFromView:self.mapView]);
// Overlay的线宽换算到MAMapPoint坐标系的宽度.
double mapPointDistance = [self mapPointsPerPointInViewAtCurrentZoomLevel] * View.lineWidth;

//判断是否选中了Overlay.
if (isOverlayWithLineWidthContainsPoint(selectableOverlay.overlay, mapPointDistance, mapPoint) )
{
    // ... 
}
核心代码
- (void)mapView:(MAMapView *)mapView didSingleTappedAtCoordinate:(CLLocationCoordinate2D)coordinate
{
    /* 逆序遍历overlay判断单击点是否在overlay响应区域内. */
    [self.mapView.overlays enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id<MAOverlay> overlay, NSUInteger idx, BOOL *stop)
    {
        if ([overlay isKindOfClass:[SelectableOverlay class]])
        {
            SelectableOverlay *selectableOverlay = overlay;

            /* 获取overlay对应的renderer. */
            MAOverlayPathRenderer * renderer = (MAOverlayPathRenderer *)[self.mapView rendererForOverlay:selectableOverlay];

            /* 把屏幕坐标转换为MAMapPoint坐标. */
            MAMapPoint mapPoint = MAMapPointForCoordinate(coordinate);
            /* overlay的线宽换算到MAMapPoint坐标系的宽度. */
            double mapPointDistance = [self mapPointsPerPointInViewAtCurrentZoomLevel] * renderer.lineWidth;

            /* 判断是否选中了overlay. */
            if (isOverlayWithLineWidthContainsPoint(selectableOverlay.overlay, mapPointDistance, mapPoint) )
            {
                /* 设置选中状态. */
                selectableOverlay.selected = !selectableOverlay.isSelected;

                /* 修改view选中颜色. */
                renderer.fillColor   = selectableOverlay.isSelected? selectableOverlay.selectedColor:selectableOverlay.regularColor;
                renderer.strokeColor = selectableOverlay.isSelected? selectableOverlay.selectedColor:selectableOverlay.regularColor;

                /* 修改overlay覆盖的顺序. */
                [self.mapView exchangeOverlayAtIndex:idx withOverlayAtIndex:self.mapView.overlays.count - 1];

                [renderer glRender];

                *stop = YES;
            }
        }
    }];
}
func mapView(_ mapView: MAMapView!, didSingleTappedAt coordinate: CLLocationCoordinate2D) {

    for (index, overlay) in mapView.overlays.enumerated().reversed() {
        if (overlay as AnyObject).isKind(of: SelectableOverlay.self) {
            let selectableOverlay: SelectableOverlay = overlay as! SelectableOverlay;

            let renderer: MAOverlayPathRenderer = self.mapView.renderer(for: selectableOverlay) as! MAOverlayPathRenderer
            let mapPoint = MAMapPointForCoordinate(coordinate)
            let distance = self.mapPointsPerPointInViewAtCurrentZoomLevel()

            // 判断是否选中了overlay
            if isOverlayWithLineWidthContainsPoint(selectableOverlay.overlay, distance, mapPoint) {
                // selected
                selectableOverlay.isSelected = !selectableOverlay.isSelected

                // change color
                renderer.strokeColor = selectableOverlay.isSelected ? selectableOverlay.selectedColor : selectableOverlay.regularColor
                renderer.fillColor = selectableOverlay.isSelected ? selectableOverlay.selectedColor : selectableOverlay.regularColor

                // 修改顺序
                self.mapView.exchangeOverlay(at: UInt(index), withOverlayAt: UInt(self.mapView.overlays.count - 1))
            }
        }
    }
}

详见工程Demo文件夹。

架构

Controllers

<UIViewController>
    ClickOverlayViewController //点击选中overlay

Models

Conform to <MAOverlay>
    SelectableOverlay //自定义可选中的Overlay(记录Overlay选中状态,颜色属性)

Utility

Utility //数学运算(计算点是否包含在Overlay响应区域内)