地图与定位(六)高德地图服务二

1. 覆盖物 Overlay

Overlay 称为多点覆盖物,它包括:折线、多边形(凹和凸)、圆、大地曲线、图片覆盖物以及自定义覆盖物这5种类型。同样也是采用数据与View分离的原则,其中:

  • Overlay 对象,通过实现 协议,定义数据。现有的Overlay对象有:MAPolyline 、 MAPolygon、 MACircle、MAGroundOverlay、以及 MATileOverlay。
  • Overlay 视图,通过继承 MAOverlayView,用于在地图显示 Overlay。以上Overlay对应的View对象有:MAPolylineView、MAPolygoneView、MACircleView、MAGroundOverlayView 以及 MATileOverlayView。

在地图上添加一个 Overlay 的步骤如下:

  • 定义一个 overlay 对象;
  • 定义一个 overlayView 对象;
  • 实现 mapView:viewForOverlay: 代理方法;
  • 使用 MAMapView 的 addOverlay:方法添加。

1.1 折线

折线类为 MAPolyline,由一组经纬度坐标组成,并以有序序列形式建立一系列的线段。iOS SDK支持在3D矢量地图上绘制带箭头或有纹理等样式的折线,同时可设置折线端点和连接点的类型,以满足各种绘制线的场景。
在地图添加折线的步骤如下:

  • 构造折线数据对象
  • 实现协议中的mapView:viewForOverlay:回调函数,设置折线的样式。

示例代码:

#import "ViewController.h"
#import 

@interface ViewController ()<MAMapViewDelegate>
{
    MAMapView *_mapView;// 地图视图
}
@end

@implementation ViewController

-(void) viewDidLoad {
    //构造折线数据对象
    CLLocationCoordinate2D commonPolylineCoords[4];
    commonPolylineCoords[0].latitude = 39.832136;
    commonPolylineCoords[0].longitude = 116.34095;

    commonPolylineCoords[1].latitude = 39.832136;
    commonPolylineCoords[1].longitude = 116.42095;

    commonPolylineCoords[2].latitude = 39.902136;
    commonPolylineCoords[2].longitude = 116.42095;

    commonPolylineCoords[3].latitude = 39.902136;
    commonPolylineCoords[3].longitude = 116.44095;

    //构造折线对象
    MAPolyline *commonPolyline = [MAPolyline polylineWithCoordinates:commonPolylineCoords count:4];

    //在地图上添加折线对象
    [_mapView addOverlay: commonPolyline];
}

// 添加覆盖物视图
- (MAOverlayView *)mapView:(MAMapView *)mapView viewForOverlay:(id )overlay {
    if ([overlay isKindOfClass:[MAPolyline class]])
    {
        // 初始化折线视图
        MAPolylineView *polylineView = [[MAPolylineView alloc] initWithPolyline:overlay];

        // 设置折线视图属性
        polylineView.lineWidth = 10.f;
        polylineView.strokeColor = [UIColor colorWithRed:0 green:0 blue:1 alpha:0.6];
        polylineView.lineJoin = kCGLineJoinRound;//连接类型
        polylineView.lineCap = kCGLineCapRound;//端点类型

        return polylineView;
    }
    return nil;
}

@end

在上面的回调函数中,调用 MAPolylineView 的 loadStrokeTextureImage 方法可以设置折线的纹理图片(仅3D矢量地图支持)。

注意:纹理图片必须是正方形,宽高是2的整数幂,如64*64,否则无效;若设置了纹理图片,设置线颜色、连接类型和端点类型将无效,目前仅支持设置折线纹理。

设置纹理图片的代码如下:

[polylineView loadStrokeTextureImage:[UIImage imageNamed:@"arrowTexture"]];

1.2 多边形

多边形类为MAPolygon,与MAPolyline类似,包括有序序列的一系列坐标,但是多边形包含有内部区域。在地图添加多边形的步骤如下:

  • 修改ViewController.m文件,在viewDidLoad方法中构造多边形的数据对象(一组经纬度坐标点)。
  • 实现协议中的的mapView:viewForOverlay:回调函数,设置多边形的样式。

示例代码:

-(void) loadRect {
    //构造多边形数据对象
    CLLocationCoordinate2D coordinates[4];
    coordinates[0].latitude = 39.810892;
    coordinates[0].longitude = 116.233413;

    coordinates[1].latitude = 39.816600;
    coordinates[1].longitude = 116.331842;

    coordinates[2].latitude = 39.762187;
    coordinates[2].longitude = 116.357932;

    coordinates[3].latitude = 39.733653;
    coordinates[3].longitude = 116.278255;

    MAPolygon *polygon = [MAPolygon polygonWithCoordinates:coordinates count:4];

    //在地图上添加多边形对象
    [_mapView addOverlay: polygon];
}

- (MAOverlayView *)mapView:(MAMapView *)mapView viewForOverlay:(id )overlay {
    if ([overlay isKindOfClass:[MAPolygon class]])
    {
        MAPolygonView *polygonView = [[MAPolygonView alloc] initWithPolygon:overlay];

        polygonView.lineWidth = 5.f;
        polygonView.strokeColor = [UIColor colorWithRed:0.6 green:0.6 blue:0.6 alpha:0.8];
        polygonView.fillColor = [UIColor colorWithRed:0.77 green:0.88 blue:0.94 alpha:0.8];
        polygonView.lineJoin = kCGLineJoinRound;//连接类型
        return polygonView;
    }
    return nil;
}

1.3 圆

圆类为MACircle,圆对象由中心点(经纬度)和半径(米)构成。
在地图绘制圆的步骤如下:

  • 根据中心点和半径构造圆对象。
  • 实现协议中的mapView:viewForOverlay:回调函数,设置圆的样式。

示例代码:

-(void) loadCircle{
    //构造圆
    MACircle *circle = [MACircle circleWithCenterCoordinate:CLLocationCoordinate2DMake(39.952136, 116.50095) radius:5000];

    //在地图上添加圆
    [_mapView addOverlay: circle];
}

- (MAOverlayView *)mapView:(MAMapView *)mapView viewForOverlay:(id )overlay {
    if ([overlay isKindOfClass:[MACircle class]])
    {
        MACircleView *circleView = [[MACircleView alloc] initWithCircle:overlay];

        circleView.lineWidth = 5.f;
        circleView.strokeColor = [UIColor colorWithRed:0.6 green:0.6 blue:0.6 alpha:0.8];
        circleView.fillColor = [UIColor colorWithRed:1.0 green:0.8 blue:0.0 alpha:0.8];

        return circleView;
    }
    return nil;
}

1.4 大地曲线

大地曲线类为MAGeodesicPolyline,继承自MAPolyline。在地图添加大地曲线的步骤如下:

  • 修改ViewController.m文件,在viewDidLoad方法中构造折大地曲线数据对象(一组经纬度坐标点或地图投影点),
  • 实现协议中的mapView:rendererForOverlay:回调函数,设置曲线的样式。

示例代码:

- (void) loadGeodesicPolyline {

    CLLocationCoordinate2D geodesicCoords[2];
    geodesicCoords[0].latitude = 39.905151;
    geodesicCoords[0].longitude = 116.401726;

    geodesicCoords[1].latitude = 38.905151;
    geodesicCoords[1].longitude = 70.401726;

    //构造大地曲线对象
    MAGeodesicPolyline *geodesicPolyline = [MAGeodesicPolyline polylineWithCoordinates:geodesicCoords count:2];

    [_mapView addOverlay:geodesicPolyline];
}

- (MAOverlayRenderer *)mapView:(MAMapView *)mapView rendererForOverlay:(id )overlay
{
    if ([overlay isKindOfClass:[MAGeodesicPolyline class]])
    {
        MAPolylineRenderer *polylineRenderer = [[MAPolylineRenderer alloc] initWithPolyline:overlay];

        polylineRenderer.lineWidth    = 4.f;
        polylineRenderer.strokeColor  = [UIColor colorWithRed:0 green:0 blue:1 alpha:1];

        return polylineRenderer;
    }
    return nil;
}

1.5 图片覆盖物

图片覆盖物类为MAGroundOverlay,可完成将一张图片以合适的大小贴在地图指定的位置上的功能。
添加图片覆盖物的步骤如下:

  • 根据范围和图片构造图片覆盖物。
  • 实现协议中的mapView:viewForOverlay:回调函数,以在地图上显示图片覆盖物。

代码示例:

- (void)loadGroundOverlay {

    MACoordinateBounds coordinateBounds = MACoordinateBoundsMake(CLLocationCoordinate2DMake(39.939577, 116.388331),CLLocationCoordinate2DMake(39.935029, 116.384377));

    MAGroundOverlay *groundOverlay = [MAGroundOverlay groundOverlayWithBounds:coordinateBounds icon:[UIImage imageNamed:@"category_3"]];

    [_mapView addOverlay:groundOverlay];
    _mapView.visibleMapRect = groundOverlay.boundingMapRect;
}

- (MAOverlayView *)mapView:(MAMapView *)mapView viewForOverlay:(id )overlay
{
    if ([overlay isKindOfClass:[MAGroundOverlay class]])
    {
        MAGroundOverlayView *groundOverlayView = [[MAGroundOverlayView alloc] initWithGroundOverlay:overlay];

        return groundOverlayView;
    }
    return nil;
}

1.6 自定义图层

通过自定义图层可对基础底层地图添加额外的特性,如:某个商场的室内信息、某个景区的详情等等。自定义图层类是MATileOverlay,它定义了能添加到基础底层地图的图片集合。

添加自定义图层的前提是使用球面墨卡托投影生成了相应的瓦片,并按照生成的格式部署在服务器上。在地图上显示自定义图层的步骤如下:

  • 根据URL模版(即指向相关图层图片的URL)创建MATileOverlay对象。
  • 设置MATileOverlay的可见最大/最小Zoom值。
  • 设定MATileOverlay的可渲染区域。
  • 将MATileOverlay对象添加到MAMapView中。
  • 构造2层的对应的MATileOverlay对象,并添加到地图上。
  • 实现MAMapViewDelegate的mapView:viewForOverlay:函数,在瓦片显示在地图View上。

示例代码:


#define TileOverlayViewControllerCoordinate CLLocationCoordinate2DMake(39.910695, 116.372830)
- (void)loadTileOverlay {

    _mapView.centerCoordinate = TileOverlayViewControllerCoordinate;
    _mapView.zoomLevel = 19;

    [_mapView addOverlay:[self constructTileOverlayWithFloor:2]];
}

- (MATileOverlay *)constructTileOverlayWithFloor:(NSInteger)floor {
    /* 构建tileOverlay的URL模版. */
    NSString *URLTemplate = [NSString stringWithFormat: @"http://sdkdemo.amap.com:8080/tileserver/Tile?x={x}&y={y}&z={z}&f=%ld", (long)floor];

    MATileOverlay *tileOverlay = [[MATileOverlay alloc] initWithURLTemplate:URLTemplate];

    tileOverlay.minimumZ = 18; //设置可见最小Zoom值
    tileOverlay.maximumZ = 20; //设置可见最大Zoom值

    tileOverlay.boundingMapRect = MAMapRectForCoordinateRegion(MACoordinateRegionMakeWithDistance(TileOverlayViewControllerCoordinate, 200, 200)); //设置可渲染区域


    return tileOverlay;
}

- (MAOverlayView *)mapView:(MAMapView *)mapView viewForOverlay:(id )overlay {
    if ([overlay isKindOfClass:[MATileOverlay class]]) {
        MATileOverlayView *tileOverlayView = [[MATileOverlayView alloc] initWithTileOverlay:overlay];

        return tileOverlayView;
    }

    return nil;
}

1.7 热力图图层

热力图图层是以颜色变化展现分布情况的图层。高德地图iOS SDK自V2.6.0版本提供了热力图图层的绘制功能,开发者可利用自有数据(入学热力图、人流热力图等等),创建可用于指导您决策的热力图。在地图上添加热力图的步骤如下:

  • 构造MAHeatMapTileOverlay 对象。
  • 配置热力图图层的参数。
  • data——数据数组,数组中是 MAHeatMapNode 对象(包含:点坐标和权重值)。
  • radius——半径,默认值为 12ps。
  • opacity——透明度,默认值为 0.6。
  • gradient——渐变色对象。
  • 将MAHeatMapTileOverlay添加到MAMapView中。
  • 实现MAMapViewDelegate的mapView:viewForOverlay:函数,在地图上显示热力图图层。

示例代码:

- (void)loadHeatMapTileOverlay {

    //构造热力图图层对象
    MAHeatMapTileOverlay  *heatMapTileOverlay = [[MAHeatMapTileOverlay alloc] init];

    //构造热力图数据,从locations.json中读取经纬度
    NSMutableArray* data = [NSMutableArray array];

    NSData *jsdata = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"heatMapData" ofType:@"json"]];


    if (jsdata)
    {
        NSArray *dicArray = [NSJSONSerialization JSONObjectWithData:jsdata options:NSJSONReadingAllowFragments error:nil];


        for (NSDictionary *dic in dicArray)
        {
            MAHeatMapNode *node = [[MAHeatMapNode alloc] init];
            CLLocationCoordinate2D coordinate;
            coordinate.latitude = [dic[@"lat"] doubleValue];
            coordinate.longitude = [dic[@"lng"] doubleValue];
            node.coordinate = coordinate;


            node.intensity = 1;//设置权重
            [data addObject:node];
        }
    }
    heatMapTileOverlay.data = data;

    //构造渐变色对象
    MAHeatMapGradient *gradient = [[MAHeatMapGradient alloc] initWithColor:@[[UIColor blueColor],[UIColor greenColor], [UIColor redColor]] andWithStartPoints:@[@(0.2),@(0.5),@(0.9)]];
    heatMapTileOverlay.gradient = gradient;

    //将热力图添加到地图上
    [_mapView addOverlay: heatMapTileOverlay];
}
- (MAOverlayView *)mapView:(MAMapView *)mapView viewForOverlay:(id )overlay
{
    if ([overlay isKindOfClass:[MATileOverlay class]])
    {
        MATileOverlayView *tileOverlayView = [[MATileOverlayView alloc] initWithTileOverlay:overlay];

        return tileOverlayView;
    }

    return nil;
}

2. 地图控件

地图控件可帮您直观的了解当前的地图的状态,iOS SDK提供“地图Logo”、“指南针”和“比例尺”三种地图控件。

iOS SDK默认的Logo为“高德地图”字样,显示在地图的左下方。地图Logo不能移除,但可通过MAMapView.logoCenter属性来调整Logo的显示位置。

2.2 指南针

指南针默认是开启状态,显示在地图的右上角。通过MAMapView的showsCompass属性用来控制指南针的可见性。compassOrigin属性可改变指南针的显示位置。

2.3 比例尺
比例尺表示地图上两点间距离与实际与之对应的两点距离的比,在不同的缩放级别下,比例尺代表的长度也是不同的。在iOS SDK中,比例尺默认显示在地图的左上角。MAMapView的showScale属性用来控制比例尺的可见性,scaleOrigin属性用来改变比例尺的显示位置。

示例代码:

#import "ViewController.h"
#import 

@interface ViewController ()<MAMapViewDelegate>
{
    MAMapView *_mapView;// 地图视图
}
@end

@implementation ViewController

-(void) viewDidLoad {

    // 初始化地图
    _mapView = [[MAMapView alloc] initWithFrame:self.view.bounds];
    _mapView.delegate = self;
    [self.view addSubview:_mapView];

    // 设置logo位置
    _mapView.logoCenter = CGPointMake(self.view.frame.size.width -100, self.view.frame.size.height -100);


    // 指南针
    _mapView.showsCompass= YES; // 设置成NO表示关闭指南针;YES表示显示指南针
    _mapView.compassOrigin= CGPointMake(_mapView.compassOrigin.x, 100); //设置指南针位置

    // 比例尺
    _mapView.showsScale= YES;  //设置成NO表示不显示比例尺;YES表示显示比例尺
    _mapView.scaleOrigin= CGPointMake(_mapView.scaleOrigin.x, 100);  //设置比例尺位置
}

@end

3. 地图手势

iOS SDK支持丰富的地图交互手势功能,通过代码也可以实现对应的手势功能。手势功能默认都是开启的,可通过代码将其禁用。

3.1 缩放手势

缩放手势可改变地图的缩放级别,地图响应的手势如下:

  • 双击地图可以使缩放级别增加1 (放大)
  • 两个手指捏/拉伸

通过MAMapView的scrollEnabled属性可以禁用或启用缩放手势。禁用缩放手势不会影响用户使用地图上的缩放控制按钮。地图的缩放级别的范围是[3-19],调用MAMapView的setZoomLevel方法设置地图的缩放级别,用来缩放地图。

3.2 平移(滑动)手势

用户可以用手指拖动地图四处滚动(平移)或用手指滑动地图(动画效果)。通过 MAMapView的scrollEnabled属性可以禁用或开启平移(滑动)手势。地图平移时,缩放级别不变,可通过改变地图的中心点来移动地图,

3.3 旋转手势(3D)

用户可以用两个手指在地图上转动,可以旋转3D矢量地图。通过调用类MAMapView的rotateEnabled属性禁用或开启旋转手势。旋转角度的范围是[0.f 360.f],以逆时针为正向。调用MAMapView的setRotationDegree方法设置地图的旋转角度。

3.4 倾斜手势(3D)

用户可以在地图上放置两个手指,移动它们一起向下或向上去增加或减小倾斜角。通过MAMapView的rotateCameraEnabled属性禁用或启用倾斜手势。倾斜角度范围为[0.f, 45.f],调用MAMapView的setCameraDegree方法设置地图的倾斜角度。

4. 地图截屏

iOS SDK支持对选定的屏幕地图区域(CGRect)进行截屏,截取的内容包括:地图、地图覆盖物、弹出气泡。使用 MAMapView 中的 takeSnapshotInRect 方法进行截屏,该方法返回UIImage对象。

注意:地图截屏功能依赖于地图显示,即:只有内容先显示在地图上,才能进行截屏。

5. 离线地图(3D)

该功能为用户提供了WIFI方式下载离线地图数据,离线地图数据以 MAOfflineItem 为单位进行下载。离线数据项 MAOfflineItem 包含城市编码、城市名称、数据状态等离线地图数据包的基本信息,是离线数据省信息(MAOfflineProvince)和离线数据城市信息(MAOfflineCity)的基类。
离线数据城市信息(MAOfflineCity)又派生出三个子类,

  • 全国概要图(MAOfflineItemNationWide)
  • 直辖市(MAOfflineItemMunicipality)
  • 普通城市(MAOfflineItemCommonCity)。

5.1 获取离线数据项

示例代码:

- (void)setupCities {
    self.sectionTitles = @[@"全国", @"直辖市", @"省份"];

    self.cities = [MAOfflineMap sharedOfflineMap].cities;//普通城市和直辖市
    self.provinces = [MAOfflineMap sharedOfflineMap].provinces;//省
    self.municipalities = [MAOfflineMap sharedOfflineMap].municipalities;//直辖市
}

- (MAOfflineItem *)itemForIndexPath:(NSIndexPath *)indexPath {
    MAOfflineItem *item = nil;
    switch (indexPath.section) {
        case 0:{
            item = [MAOfflineMap sharedOfflineMap].nationWide;//全国概要图
            break;
        } case 1:{
            item = self.municipalities[indexPath.row];//直辖市
            break;
        } case 2:{
            item = nil;
            break;
        } default:{
            MAOfflineProvince *pro = self.provinces[indexPath.section - self.sectionTitles.count];
            if (indexPath.row == 0) {
                item = pro; //整个省
            } else {
                item = pro.cities[indexPath.row - 1]; //市
            }
            break;
        }
    }
    return item;
}

5.2 下载某个离线地图数据项(参数 MAOfflineItem)

示例代码:

- (void)download:(MAOfflineItem *)item
{
    if (item == nil || item.itemStatus == MAOfflineItemStatusInstalled)
    {
        return;
    }

    NSLog(@"download :%@", item.name);

    [[MAOfflineMap sharedOfflineMap] downloadItem:item shouldContinueWhenAppEntersBackground:YES downloadBlock:^(MAOfflineMapDownloadStatus downloadStatus, id info) {

        /* Manipulations to your application’s user interface must occur on the main thread. */
        dispatch_async(dispatch_get_main_queue(), ^{

            if (downloadStatus == MAOfflineMapDownloadStatusWaiting)
            {
                NSLog(@"状态为: %@", @"等待下载");
            }
            else if(downloadStatus == MAOfflineMapDownloadStatusStart)
            {
                NSLog(@"状态为: %@", @"开始下载");
            }
            else if(downloadStatus == MAOfflineMapDownloadStatusProgress)
            {
                NSLog(@"状态为: %@", @"正在下载");
            }
            else if(downloadStatus == MAOfflineMapDownloadStatusCancelled) {
                NSLog(@"状态为: %@", @"取消下载");
            }
            else if(downloadStatus == MAOfflineMapDownloadStatusCompleted) {
                NSLog(@"状态为: %@", @"下载完成");
            }
            else if(downloadStatus == MAOfflineMapDownloadStatusUnzip) {
                NSLog(@"状态为: %@", @"下载完成,正在解压缩");
            }
            else if(downloadStatus == MAOfflineMapDownloadStatusError) {
                NSLog(@"状态为: %@", @"下载错误");
            }
            else if(downloadStatus == MAOfflineMapDownloadStatusFinished) {
                NSLog(@"状态为: %@", @"全部完成");
                [self.mapView reloadMap];              //激活离线地图
            }
        });
    }];
}

5.3 暂停某个离线数据项(参数 MAOfflineItem)

示例代码:


- (void)pause:(MAOfflineItem *)item {
    NSLog(@"pause :%@", item.name);

    [[MAOfflineMap sharedOfflineMap] pauseItem:item];
        //暂停所有离线地图下载的函数为 :
    [[MAOfflineMap sharedOfflineMap] cancelAll];
}

6. 室内外一体化(3D)

支持商场、火车站、机场等大型室内建筑的室内外一体化地图显示。支持通过楼层控件进行自由切换室内对应楼层,显示室内精细化地图。通过MAMapView类的showsIndoorMap接口设置是否显示室内地图,默认状态为开启:_mapView.showsIndoorMap = YES;

在开启显示室内地图之后,可通过实现代理方法获取室内地图取楼层变化,
示例代码:

/**
 *  室内地图信息发生变化的回调
 *  @param mapView            地图View
 *  @param indoorBuilding     室内地图信息
 */
- (void)mapview:(MAMapView *)mapView didIndoorBuildingValueChanged:(MAIndoorBuilding *)indoorBuilding
{
    MAIndoorBuilding *indoorInfo = indoorBuilding;
    NSLog(@"floorName = %@",indoorBuilding.floorName);        //楼层名
    NSLog(@"floor = %d",indoorBuilding.floor);                //楼层数
    NSLog(@"buildingName = %@",indoorBuilding.buildingName);  //楼块名(中文名)
    NSLog(@"poiID = %@",indoorBuilding.poiID);                //楼块ID
    NSLog(@"numberOfFloor = %d",indoorBuilding.numberOfFloor);//楼层总数
}

你可能感兴趣的:(地图和定位)