MapKit 地图使用

代码下载地址:这里写链接内容
github地址:这里写链接内容

一.MKMapView基本使用

MapKit 地图开发需要依赖位置信息,所以需要允许访问用户位置信息,具体设置见前面博客。
MKMapView的其他设置如下:

    //设置用户的跟踪模式-即用户的位置(默认不跟踪)
    [self.mapView setUserTrackingMode:MKUserTrackingModeFollowWithHeading];

    //设置地图的类型
    [self.mapView setMapType:MKMapTypeStandard];

    //如果定位成功
    if ([FixLocation shareFixLoction].placemark) {
        //设置地图的中心点
        [self.mapView setCenterCoordinate:[FixLocation shareFixLoction].coordinate];
    }

    /**
     *  下面两个方法需要一个位置,可以在定位成功之后再设置
     //设置地图的中心点
     [self.mapView setCenterCoordinate:currentLocation.coordinate animated:YES];

     //设置地图的显示范围
     [self.mapView setRegion:MKCoordinateRegionMake(currentLocation.coordinate, MKCoordinateSpanMake(0.1, 0.1)) animated:YES];
     */

二添加标注(大头针)

1.使用 -(void)addAnnotation:(id )annotation 方法,添加标注。标注对象必须实现协议


@protocol MKAnnotation <NSObject>
//地理坐标
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;

@optional
//描述的标题
@property (nonatomic, readonly, copy, nullable) NSString *title;
//描述的副标题
@property (nonatomic, readonly, copy, nullable) NSString *subtitle;

//设置地理坐标的方法
- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate NS_AVAILABLE(10_9, 4_0);

@end

2.在MapView的代理方法- (MKAnnotationView )mapView:(MKMapView )mapView viewForAnnotation:(id)annotation中我们需要返回标注的视图MKAnnotationView对象或者其子类MKPinAnnotationView(可以做从天而降的动画)对象。而其具体实现类似于UITableViewCell,利用重用机制。

    static NSString *identifier = @"MKAnnotationViewID";
    //从缓存池中取出可以循环利用的大头针view
    MKPinAnnotationView *view = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
    if (!view) {
        view = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
        //能否显示大头针描述
        view.canShowCallout = YES;
        //设置大头针描述的偏移量
        [view setCalloutOffset:CGPointMake(-8, -8)];
        //设置大头针描述的左右控件
        [view setLeftCalloutAccessoryView:[UIButton buttonWithType:UIButtonTypeDetailDisclosure]];
        [view setRightCalloutAccessoryView:[UIButton buttonWithType:UIButtonTypeContactAdd]];
        //设置从天而降的动画
        view.animatesDrop = YES;
    }

    view.annotation = annotation;

    return view;

三.自定义标注(大头针)的描述

实现方案是通过自定义标注来替代标注的描述:即在需要显示标注的描述时,再向此位置添加一个标注来偷梁换柱。在MapView的代理方法- (void)mapView:(MKMapView )mapView didSelectAnnotationView:(MKAnnotationView )view中来操作:

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
    //如果是标注视图被选中,那么添加描述类型的标注
    if ([view isKindOfClass:[MainAnnotationView class]]) {
        MainAnnotation *mainAnnotation = (MainAnnotation *)view.annotation;
        [self addDescribeAnnotation:mainAnnotation];
    }
    //如果是描述类型的标注被点击,那么不做任何处理
    else if ([view isKindOfClass:[DescribeAnnotationView class]])
    {
        return;
    }
    //如果点击的是其他类型的标注,那么移除所有描述类型的标注
    else
    {
        [self removeAllDescribeAnnotationView];
        return;
    }
}
/**
 *  添加一个描述类型的大头针
 *
 *  @param annotation MainAnnotation类型的大头针模型
 */
- (void)addDescribeAnnotation:(MainAnnotation *)annotation
{
    //先移除所有的DescribeAnnotationView,模拟系统的一次只能显示一个标注的描述
    [self removeAllDescribeAnnotationView];

    //添加描述类型的标注DescribeAnnotation
    DescribeAnnotation *describeAnnotation = [DescribeAnnotation describeAnnotationWithDic:annotation.infoDic];
    describeAnnotation.coordinate = annotation.coordinate;
    [self.mapView addAnnotation:describeAnnotation];
}
/**
 *  移除所有DescribeAnnotationView
 */
- (void)removeAllDescribeAnnotationView
{
    for (id annotation in self.mapView.annotations) {
        if ([annotation isKindOfClass:[DescribeAnnotation class]]) {
            [self.mapView removeAnnotation:annotation];
        }
    }
}

四.自定义标注(大头针)动画

这个没有什么好说的啊,有需要那么看前面的核心动画。直接上代码。

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    if ([annotation isKindOfClass:[MainAnnotation class]])
    {
        MainAnnotationView *mainAnnotationView = [MainAnnotationView mainAnnotationViewWithMapView:mapView andAnnotation:annotation];

        return mainAnnotationView;
    }
    else if ([annotation isKindOfClass:[DescribeAnnotation class]])
    {
        DescribeAnnotationView *describeAnnotationView = [DescribeAnnotationView describeAnnotationViewWithMapView:mapView andAnnotation:annotation];
        describeAnnotationView.delegate = self;

        //显示标注视图的时候,执行动画。
        [self implementCoreAnnimationWithView:describeAnnotationView.layer andAnnotation:annotation];

        return describeAnnotationView;
    }
    else
    {
        return nil;
    }
}
/**
 *  执行核心动画
 *
 *  @param layer      所需动画的CALayer
 *  @param annotation 为了确定动画位置所需的MKAnnotation对象
 */
- (void)implementCoreAnnimationWithView:(CALayer *)layer andAnnotation:(id<MKAnnotation>)annotation
{
    //创建动画对象
    CAKeyframeAnimation *animation = [[CAKeyframeAnimation alloc] init];
    //设置动画属性
    //        animation.keyPath = @"transform.scale";
    //        animation.values = @[@(1),@(1.5),@(0.5),@(1.3),@(0.7),@(1.1),@(0.9),@(1)];

    animation.keyPath = @"position.y";
    CGFloat beginValue = [self.mapView convertCoordinate:annotation.coordinate toPointToView:self.mapView].y;
    animation.values = @[@(beginValue),@(beginValue - 30),@(beginValue + 30),@(beginValue + 20),@(beginValue - 20),@(beginValue + 10),@(beginValue - 10),@(beginValue)];

    animation.duration = 0.5;
    animation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
    //为CALayer添加动画
    [layer addAnimation:animation forKey:nil];
}

五.导航

1.导航需要使用MKDirections来计算路径,而MKDirections需要一个方向请求对象MKDirectionsRequest,MKDirectionsRequest设置好起点和终点。
2.计算完成之后会返回一个方向响应对象MKDirectionsResponse,此对象中一个路径(MKRoute)数组routes,然后在MapView中添加路径中的遮罩MKPolyline。
3.在MapView的代理方法- (MKOverlayRenderer )mapView:(MKMapView )mapView rendererForOverlay:(id)overlay中,我们需要返回一个遮罩的渲染器对象MKOverlayRenderer。此时只有返回它的子类MKPolylineRenderer才能设置颜色,才能可见。

    //创建请求
    MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
    //设置起点和终点
    [request setSource:[[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithPlacemark:sourcePlacemark]]];
    [request setDestination:[[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithPlacemark:self.endPlaceMark]]];

    //创建方向对象
    MKDirections *directions = [[MKDirections alloc] initWithRequest:request];

    //计算路线
    [directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            [self showAlertControllerTitle:nil withMessge:@"对不起,没有为您找到合适的路线!" andCancelTitle:nil];
        }
        else
        {
            //添加两颗大头针
            [self addAnnotation:sourcePlacemark.location.coordinate withTitle:@"出发地" andSubTitle:sourcePlacemark.name];
            [self addAnnotation:self.endPlaceMark.location.coordinate withTitle:@"目的地" andSubTitle:self.endPlaceMark.name];

            //先遍历所有的路线移除
            for (id<MKOverlay> overlay in self.mapView.overlays) {
                [self.mapView removeOverlay:overlay];
            }

            //遍历所有路线
            for (MKRoute *route in response.routes) {
                //添加遮罩
                [self.mapView addOverlay:route.polyline];
            }

            //设置地图的显示范围
            if (isChange) {
                CLLocationCoordinate2D startCoordinate = sourcePlacemark.location.coordinate;
                CLLocationCoordinate2D endCoordinate = self.endPlaceMark.location.coordinate;
                CLLocationCoordinate2D centerCoordinate = CLLocationCoordinate2DMake((startCoordinate.latitude + endCoordinate.latitude)/2, (startCoordinate.longitude + endCoordinate.longitude)/2);

                CGFloat proportion = (Screen_Height - 64 - 49 - 44)/Screen_Height;
                CLLocationDegrees latitudeDelta = fabs(startCoordinate.latitude - endCoordinate.latitude)/proportion;
                CLLocationDegrees longitudeDelta = fabs(startCoordinate.longitude - endCoordinate.longitude)/proportion;
                MKCoordinateSpan coordinateSpan = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
                [self.mapView setRegion:MKCoordinateRegionMake(centerCoordinate, coordinateSpan) animated:YES];
            }
        }
    }];
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
{
    MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
    renderer.strokeColor = [UIColor greenColor];

    return renderer;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值