iOS 解锁自定义高德地图的基础姿势

后续文章来了,点聚合用了四叉树数据结构,轨迹抽稀用了道格拉斯-普克算法
1、高德地图maker点聚合以及周边推荐
2、iOS 地图海量轨迹抽稀处理 道格拉斯-普克算法(Douglas–Peucker algorithm)
3、iOS高德地图内存优化之——单例地图

本篇内容包括了高德地图自定义大头针自动布局及其动画、自定义UserLocation过程中遇到的问题。因篇幅有限,后续会追加运动轨迹等内容。

自定义大头针

高德地图高度自定义使用场景:

  1. 共享单车类应用

  2. 跑步运动类应用

集成方案:

项目需要集成地图,权衡下选择了高德地图,高德提供的API更友好,工单解答也能解决大多数开发问题。
关于地图的集成直接参考官方文档高德地图API,步骤很简单。重点讲开发过程中遇到的坑以及解决方法。

实现功能

  1. 地图的初始化,我直接加在SB上了,但在项目里因为频繁用到地图,导致内存暴增,所以我选择了用单例创建,这里只给示范
 self.mapView.delegate                 = self;
 self.mapView.userTrackingMode         = MAUserTrackingModeFollow;
 self.mapView.showsUserLocation        = YES;
/**自定义当前位置,给了一张空图 后面会在地图的代理方法
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id<MAAnnotation>)annotation
里单独处理
*/
 MAUserLocationRepresentation *r   = [[MAUserLocationRepresentation alloc] init];
 r.image = [UIImage imageNamed:@"none"];
 [self.mapView updateUserLocationRepresentation:r];

2.实现MAMapViewDelegate

/**
这个方法只要用户设备方向发生变化就会触发 当然适合处理指北针和当前位置的旋转啦
*/
- (void)mapView:(MAMapView *)mapView didUpdateUserLocation:(MAUserLocation *)userLocation updatingLocation:(BOOL)updatingLocation
{
    if (!updatingLocation && self.userLocationAnnotationView != nil)
    {
        [UIView animateWithDuration:0.1 animations:^{
            double degreeS = userLocation.heading.magneticHeading;
            self.northBtn.transform = CGAffineTransformMakeRotation(-degreeS * M_PI / 180.f );//指北针旋转
            double degree = userLocation.heading.trueHeading - self.mapView.rotationDegree;
            self.userLocationAnnotationView.imageView.transform = CGAffineTransformMakeRotation(degree * M_PI / 180.f );//当前位置旋转
        }];
    }
}

接下来是往地图上添加大头针,CustomInTurnAnnotationView继承MAAnnotationView单独一个view类,
CustomInTurnAnnotationModel里存放数据

- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id<MAAnnotation>)annotation
{
    if ([annotation isKindOfClass:[MAUserLocation class]])
    {//当前位置
        static NSString *userLocationStyleReuseIndetifier = @"userLocationStyleReuseIndetifier";
        MAAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:userLocationStyleReuseIndetifier];
        if (annotationView == nil)
        {
            annotationView    = [[MAAnnotationView alloc] initWithAnnotation:annotation
                                                             reuseIdentifier:userLocationStyleReuseIndetifier];
        }
        annotationView.image  = [UIImage imageNamed:@"icon_dqd2_b"];
        annotationView.zIndex = 100;//可以控制图层显示问题 谁的值大 谁在最上层
        self.userLocationAnnotationView = annotationView;
        return annotationView;
    }else if ([annotation isKindOfClass:[MAPointAnnotation class]])
    {//多个大头针
        CustomInTurnAnnotationModel *cusAnnotation = (CustomInTurnAnnotationModel *)annotation;
        static NSString *pointReuseIndentifier = @"pointReuseIndentifier";
        CustomInTurnAnnotationView *annotationView = (CustomInTurnAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndentifier];
        if (annotationView == nil)
        {
            annotationView = [[CustomInTurnAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndentifier];
        }
        //配置模型数据
        annotationView.annotation = cusAnnotation;
        annotationView.zIndex = 10;
        return annotationView;
    }
    return nil;
}

显示在地图上的数据是我用当前定位随机出来的,大致效果如下


喏 效果图
  1. 看一下自定义MAAnnotationView里的处理
    重写了- (void)setAnnotation:(id<MAAnnotation>)annotation方法
- (void)setAnnotation:(id<MAAnnotation>)annotation
{
    [super setAnnotation:annotation];
    CustomInTurnAnnotationModel *ann = (CustomInTurnAnnotationModel *)self.annotation;
    if (ann)
    {
        [self setupAnnotation:ann];
    }
}

- (void)setupAnnotation:(CustomInTurnAnnotationModel *)ann
{
    float width = ann.scoreWid;//这个view的大小是model返回的 地图缩放大小可以变化
    float scale = width/35;
    self.bounds            = CGRectMake(0.f, 0.f, width, width);
    self.backPic.frame = CGRectMake(2*scale, 0, width - 4*scale, width);
    self.nameLabel.frame = CGRectMake(0,
                                      0,
                                      CGRectGetWidth(self.backPic.frame),
                                      CGRectGetHeight(self.backPic.frame) - 10*scale);
    
    self.scorePic.frame = CGRectMake(6*scale,
                                     3*scale,
                                     CGRectGetWidth(self.backPic.frame) - 12*scale,
                                     CGRectGetHeight(self.backPic.frame) - 16*scale);

    self.centerOffset      = CGPointMake(0 , -(width/2 - 5));
    UIImage *imageCicle = [UIImage imageNamed:@"running_point_icon_db_red"];// running_point_icon_db_grex
    if (ann.isSel)
    {
        imageCicle  = [UIImage imageNamed:@"running_point_icon_db_grex"];
    }
    if (ann.isRadius==1)
    {//开始动画
        [self.layer removeAnimationForKey:@"topbottom"];
        [self.layer addAnimation:self.animation forKey:@"topbottom"];
    }else
    {//结束动画
        [self.layer removeAnimationForKey:@"topbottom"];
    }
    
    self.nameLabel.text               = [NSString stringWithFormat:@"%@",ann.titleStr];
    
    self.scorePic.image               = imageCicle;
    
    [self.backPic bringSubviewToFront:self.nameLabel];
    
}

大头针跳动动画是给layer加的很简单的基础动画

- (CAKeyframeAnimation *)animation
{
    if (!_animation)
    {
        CGFloat duration = 0.8f;
        CGFloat height = 10.f;
        _animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.y"];
        CGFloat currentTy = self.transform.ty;
        _animation.duration = duration;
        _animation.values = @[@(currentTy), @(currentTy - height), @(currentTy)];
        _animation.keyTimes = @[ @(0), @(0.5), @(0.8) ];
        _animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        _animation.repeatCount = CGFLOAT_MAX;
    }
    return _animation;
}

大头针的大小根据地图缩放在这里处理

- (void)mapView:(MAMapView *)mapView mapDidZoomByUser:(BOOL)wasUserAction
{
    if (wasUserAction) {
        [self zoomData];//这里改变model数据就可以了
    }
}

地图的zoomlevel变小,大头针是不是变小了!当然也可以做点聚合,我这里只是改变了大头针的尺寸,点聚合可以从减少点的个数下手,后续会出文章讲点聚合。

屏幕快照 2017-12-07 12.02.29.png

好啦,时间有限今天先到这儿吧,附上GitHub YLCustomMapView地址,下载后用终端pod install一下 要下载高德API。

以上。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容