No2地图 MapKit框架

一 地图基本使用

  • 设置地图类型
   MKMapTypeStandard = 0,  // 标准
   MKMapTypeSatellite,     // 卫星
   MKMapTypeHybrid,        // 混合(标准+卫星)
   MKMapTypeSatelliteFlyover NS_ENUM_AVAILABLE(10_11, 9_0), // 3D立体卫星
   MKMapTypeHybridFlyover NS_ENUM_AVAILABLE(10_11, 9_0), // 3D立体混合
  • 设置地图的其他属性(操作项)
    • 注意:设置对应的属性时,注意该属性是从哪个系统版本开始引入的,做好不同系统版本的适配
 // 是否可以缩放
 self.customMapView.zoomEnabled = NO;
 // 是否可以滚动
 self.customMapView.scrollEnabled = NO;
 // 是否可以旋转
 self.customMapView.rotateEnabled = NO;
 // 是否显示3D
 self.customMapView.pitchEnabled = NO;
  • 设置地图其它属性(显示项)
// 是否显示指南针
self.customMapView.showsCompass = YES;
// 是否显示比例尺
self.customMapView.showsScale = YES;
// 是否显示交通
self.customMapView.showsTraffic = YES;
// 是否显示建筑物
self.customMapView.showsBuildings = YES;
  • 设置地图显示用户位置( 需要请求用户授权 )

    • 效果: 会在地图上显示一个蓝色圆点(大头针),标示用户当前所在位置, 地图不会跟着用户移动而移动
    • 代码: self.customMapView.showsUserLocation = YES;
  • 设置地图的用户追踪模式( 需要请求用户授权 )

    • 效果: 会在地图上显示一个蓝色圆点(大头针),标示用户当前所在位置, 地图会跟着用户移动而移动, 而且自动放大地图到合适比例
    • 1>创建CLLocationManager对象请求授权

      -(CLLocationManager *)locationM
      {
      if (!_locationM) {
       _locationM = [[CLLocationManager alloc] init];
          if ([_locationM respondsToSelector:@selector(requestAlwaysAuthorization)])   {
          [_locationM requestAlwaysAuthorization]; 
               }     
                    }
      return _locationM;
      }
    • 2>设置地图的用户追踪模式

      • (注意:设置此属性会使用到用户的位置隐私,所以需要请求用户授权,否则没有效果)
        MKUserTrackingModeNone = 0  // 不跟随
        MKUserTrackingModeFollow  // 跟随用户位置
        MKUserTrackingModeFollowWithHeading  // 跟随用户位置,并跟随用户方向
        //  显示用户位置
        [self locationM];
        self.customMapView.userTrackingMode = MKUserTrackingModeFollowWithHeading;  

二 地图的中级使用

  • 查看当前用户位置信息
    • 1>设置地图代理,并实现代理方法,在代理方法中获取用户当前位置(注意:iOS8.0之后要请求授权!!)
    • 2>将地图显示中心调整为用户当前所在位置(iOS8.0之前,地图不会自动移动到用户所在位置)
    • 3>调整当前地图显示的区域(可使用对应代理方法查看当前地图跨度,然后调整到合适跨度即可)
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
    /**
    MKUserLocation : 被称作“大头针模型”,本质就是一个数据模型,遵循了大头针要遵循的协议(MKAnnotation)
    location:  用户当前所在位置信息(CLLocation对象)
    title:     大头针标注要显示的标题(NSString对象)
    subtitle:  大头针标注要显示的子标题(NSString对象)
    */
 // 根据用户当前位置的经纬度,设置地图显示中心
   CLLocationCoordinate2D center = userLocation.location.coordinate;
            /**
                存在弊端:地图显示比例过大,无法调整
                解决方案:直接使用对应的调整地图“显示区域”的API
             */
  // 移动地图的中心,显示用户的当前位置
  // [mapView setCenterCoordinate:userLocation.coordinate animated:YES];
/**
    MKCoordinateSpan 跨度解释:
    latitudeDelta:纬度跨度,因为南北纬各90度,所以此值的范围是(0---180);此值表示,整个地图视图宽度,显示多大跨度
    longitudeDelta:经度跨度,因为东西经各180度,所以此值范围是(0---360):此值表示,整个地图视图高度,显示多大跨度
注意:地图视图显示,不会更改地图的比例,会以地图视图高度或宽度较小的那个为基准,按比例调整
 */
 // 设置区域跨度 
  MKCoordinateSpan span = MKCoordinateSpanMake(0.1, 0.1);
 // 创建一个区域
  MKCoordinateRegion region = MKCoordinateRegionMake(userLocation.coordinate, span);
 // 设置地图显示区域
  [mapView setRegion:region animated:YES];
        }

// 当地图区域(跨度)改变时调用
-(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
 NSLog(@"%f---%f", mapView.region.span.latitudeDelta, mapView.region.span.longitudeDelta);
}

三 大头针基本使用

  • 在地图上操作大头针,实际上是控制大头针数据模型
    • 添加大头针就是添加大头针数据模型
    • 删除大头针就是删除大头针数据模型
  • 添加一个/多个大头针
    • 自定义大头针模型(需要遵循MKAnnotation协议)
    • 创建自定义大头针模型,并添加到地图上
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
// 如果我们仅仅添加大头针数据模型,地图上会自动添加系统默认的大头针视图
XMGAnnotation *annotation = [[XMGAnnotation alloc] init];
//  设置经纬度
//  annotation.coordinate = self.mapView.centerCoordinate;
    // 1. 获取当前点的位置
    UITouch *touch = [touches anyObject];
    CGPoint point = [touch locationInView:self.mapView];
    // 把点转换成对应的经纬度
    CLLocationCoordinate2D coordinate = [self.mapView convertPoint:point toCoordinateFromView:self.mapView];
    // TODO:使用反地理编码,获取对应大头针的所在的位置信息,通过标注显示出来
    annotation.coordinate = coordinate;
    annotation.title = @"XXX";
    annotation.subtitle = @"xxx";

    // 添加单个大头针
    [self.mapView addAnnotation:annotation];
    // 添加多个大头针
    //    [self.mapView addAnnotations:@[]];
}
  • 移除一个/多个大头针
 // 获取地图上所有的大头针数据模型
 NSArray *annotations = self.mapView.annotations; 
 // 移除大头针
 [self.mapView removeAnnotations:annotations];

四 自定义大头针

  • 模拟系统大头针实现方案,并对系统大头针进行部分自定义

实现:弹出标注, 修改大头针颜色, 设置大头针从天而降, 设置大头针可以被拖拽

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
 {
 if ([annotation isKindOfClass:[MKUserLocation class]]) {
    return nil;
 }
// 如果此方法返回nil, 就会使用系统自带的大头针视图
// 模拟下,返回nil,系统的解决方案
    static NSString *pinId = @"pinID";
    MKPinAnnotationView *pinView = ( MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:pinId];
// 如果从缓存池取出的大头针视图为空, 就创建
  if (pinView == nil) {
    pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pinId];
    }
// 重新设置数据模型 (一定要记得!!!), 为了防止循环利用时, 数据混乱
   pinView.annotation = annotation;
// 是否显示标注(弹窗)
   pinView.canShowCallout = YES;
// 设置大头针颜色
    pinView.pinColor = MKPinAnnotationColorPurple;
// 设置大头针是否有下落动画
    pinView.animatesDrop = YES;
    return pinView;
}
  • 自定义大头针
    • 大头针图标,大头针标注,左侧视图,右侧视图,详情视图,等;
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
 if ([annotation isKindOfClass:[MKUserLocation class]]) {
  return nil;
        }
/**  自定义大头针-------*/
    static NSString *pinId = @"pinID";  // 设置循环利用标识 
    MKAnnotationView *annoView = [mapView dequeueReusableAnnotationViewWithIdentifier:pinId];
     if (annoView == nil) {
    annoView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pinId];
            }
    annoView.annotation = annotation;
    // 1. 设置大头针图片
    annoView.image = [UIImage imageNamed:@"category_5"];
    // 2. 设置弹框
    annoView.canShowCallout = YES;
      // 2.1 设置大头针偏移量
     //  customView.centerOffset = CGPointMake(100, -100);
      // 2.2 设置弹框的偏移量
     //  customView.calloutOffset = CGPointMake(100, 100);
    // 3. 自定义弹框
     // 3.1 设置弹框左侧的视图
     UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"huba.jpeg"]];
    imageView.bounds = CGRectMake(0, 0, 44, 44);
    annoView.leftCalloutAccessoryView = imageView;
    imageView.userInteractionEnabled  = YES;
     // 3.2 设置弹框右侧视图
     UIImageView *imageView2 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"eason.jpg"]];
    imageView2.bounds = CGRectMake(0, 0, 44, 44);
    annoView.rightCalloutAccessoryView = imageView2;
     // 3.3 设置弹框的详情视图(一定要注意,对应的版本)
    annoView.detailCalloutAccessoryView = [UISwitch new];
     // 设置大头针视图可以被拖拽
   annoView.draggable = YES;
   return annoView;
}
  • 选中,和取消选中大头针时的代理方法
// 点击标注
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
    NSLog(@"点击标注");
}
// 选中大头针
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
    NSLog(@"选中大头针");
}
// 取消选中大头针
-(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
    NSLog(@"取消选中大头针");
}

五 利用系统App导航

// 根据两个地标对象进行调用系统导航
- (void)beginNavWithBeginPlacemark:(CLPlacemark *)beginPlacemark andEndPlacemark:(CLPlacemark *)endPlacemark
{
// 根据 CLPlacemark 地标对象创建 MKPlacemark 地标对象
   MKPlacemark *itemP1 = [[MKPlacemark alloc] initWithPlacemark:beginPlacemark];
   MKMapItem *item1 = [[MKMapItem alloc] initWithPlacemark:itemP1];

// 地图终点地标对象
   MKPlacemark *itemP2 = [[MKPlacemark alloc] initWithPlacemark:endPlacemark];
   MKMapItem *item2 = [[MKMapItem alloc] initWithPlacemark:itemP2];

NSDictionary *launchDic = @{

// 设置导航模式参数           MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving,
// 设置地图类型              MKLaunchOptionsMapTypeKey : @(MKMapTypeHybridFlyover),
// 设置是否显示交通            MKLaunchOptionsShowsTrafficKey : @(YES),                               
                                };
// 根据 MKMapItem 数组 和 启动参数字典 来调用系统地图进行导航
[MKMapItem openMapsWithItems:@[item1, item2] launchOptions:launchDic];
  • 数字版街景地图
  CLLocationCoordinate2D center = CLLocationCoordinate2DMake(23.132931, 113.375924);
  MKMapCamera *camera = [MKMapCamera cameraLookingAtCenterCoordinate:center fromEyeCoordinate:CLLocationCoordinate2DMake(center.latitude + 0.001, center.longitude + 0.001) eyeAltitude:1];
  self.mapView.camera = camera;
  • 地图快照截图
// 截图附加选项
   MKMapSnapshotOptions *options = [[MKMapSnapshotOptions alloc] init];
// 设置截图区域(在地图上的区域,作用在地图)
   options.region = self.mapView.region;
//    options.mapRect = self.mapView.visibleMapRect;

// 设置截图后的图片大小(作用在输出图像)
   options.size = self.mapView.frame.size;
// 设置截图后的图片比例(默认是屏幕比例, 作用在输出图像)
   options.scale = [[UIScreen mainScreen] scale];

    MKMapSnapshotter *snapshotter = [[MKMapSnapshotter alloc] initWithOptions:options];
    [snapshotter startWithCompletionHandler:^(MKMapSnapshot * _Nullable snapshot, NSError * _Nullable error) {
        if (error) {
            NSLog(@"截图错误:%@",error.localizedDescription);
        }else
        {
            // 设置屏幕上图片显示
            self.snapshootImageView.image = snapshot.image;
            // 将图片保存到指定路径(此处是桌面路径,需要根据个人电脑不同进行修改)
            NSData *data = UIImagePNGRepresentation(snapshot.image);
            [data writeToFile:@"/Users/yonghuming/Desktop/snap.png" atomically:YES];
        }
    }];

六 获取导航路线信息

// 根据两个地标,向苹果服务器请求对应的行走路线信息
- (void)directionsWithBeginPlackmark:(CLPlacemark *)beginP andEndPlacemark:(CLPlacemark *)endP
{

    // 创建请求
    MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];

    // 设置开始地标
    MKPlacemark *beginMP = [[MKPlacemark alloc] initWithPlacemark:beginP];
    request.source = [[MKMapItem alloc] initWithPlacemark:beginMP];

    // 设置结束地标
    MKPlacemark *endMP = [[MKPlacemark alloc] initWithPlacemark:endP];
    request.destination = [[MKMapItem alloc] initWithPlacemark:endMP];


    // 根据请求,获取实际路线信息
    MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
    [directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse * _Nullable response, NSError * _Nullable error) {
        /** 
         MKDirectionsResponse对象解析
            source :开始位置
            destination :结束位置
            routes : 路线信息 (MKRoute对象)

         MKRoute对象解析
            name : 路的名称
            advisoryNotices : 注意警告信息
            distance : 路线长度(实际物理距离,单位是m)
            polyline : 路线对应的在地图上的几何线路(由很多点组成,可绘制在地图上)
            steps : 多个行走步骤组成的数组(例如“前方路口左转”,“保持直行”等等, MKRouteStep 对象)

        MKRouteStep对象解析
            instructions : 步骤说明(例如“前方路口左转”,“保持直行”等等)
            transportType : 通过方式(驾车,步行等)
            polyline : 路线对应的在地图上的几何线路(由很多点组成,可绘制在地图上)
    注意:MKRoute是一整条长路;MKRouteStep是这条长路中的每一截;    
         */
     [response.routes enumerateObjectsUsingBlock:^(MKRoute * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            NSLog(@"%@--", obj.name);
      [obj.steps enumerateObjectsUsingBlock:^(MKRouteStep * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            NSLog(@"%@", obj.instructions);
            }];
        }];

    }];

}

七 绘制导航路线

  • 路线也是一个覆盖层,理论指导:在地图上操作覆盖层,其实操作的是覆盖层的数据模型

    • 添加覆盖层:在地图上添加覆盖层数据模型
    • 删除覆盖层:在地图上移除覆盖层数据模型
  • 创建线路覆盖层模型,并添加到地图上

// 绘制线路
- (void)drawMapLine:(id <MKOverlay>)overlay
{
    /**
    注意:这里不像添加大头针那样,只要我们添加了大头针模型,默认就会在地图上添加系统的大头针视图
添加覆盖层,需要我们实现对应的代理方法,在代理方法中返回对应的覆盖层
     */
    [self.mapView addOverlay:overlay];

         /** 补充测试:添加一个圆形覆盖层 */
//    MKCircle *circle = [MKCircle circleWithCenterCoordinate:self.mapView.centerCoordinate radius:1000000];
//    [self.mapView addOverlay:circle];
}
  • 利用地图的代理方法,返回对应的图层渲染
-(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{
// 创建折线渲染对象
if ([overlay isKindOfClass:[MKPolyline class]]) {
    MKPolylineRenderer *lineRenderer = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
        // 设置线宽
        lineRenderer.lineWidth = 6;
        // 设置线颜色
        lineRenderer.strokeColor = [UIColor redColor];
        return lineRenderer;
        }
// 创建圆形区域渲染对象
//    if ([overlay isKindOfClass:[MKCircle class]]) {
//        MKCircleRenderer *circleRender = [[MKCircleRenderer alloc] initWithOverlay:overlay];
//        circleRender.fillColor = [UIColor cyanColor];
//        circleRender.alpha = 0.6;
//        return circleRender;
//    }
        return nil;

        } 

八 集成百度地图

  1. 下载百度地图SDK
  2. 按照说明进行配置(务必按照提示,一步一步配置)
  3. 集成百度地图,直接使用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值