功能:
1、用户定位追踪
2、自定义用户当前位置大头针
3、添加和移除附近停车场大头针
4、跳动动画
注意事项:
1、项目使用需进行二次封装
2、用前请配置高德地图AppKey
实现过程
一、添加地图
- (void)creatMapView {
_mapView = [[MAMapView alloc]initWithFrame:self.view.bounds];
_mapView.delegate = self;
_mapView.showsCompass = NO;
_mapView.showsScale = NO;
_mapView.rotateEnabled = NO;
_mapView.showsUserLocation = YES;
_mapView.userTrackingMode = MAUserTrackingModeFollow;
_mapView.customizeUserLocationAccuracyCircleRepresentation = YES;
[_mapView setZoomLevel:15.1 animated:NO];
[self.view addSubview:_mapView];
}
如下两句开启定位追踪功能
_mapView.showsUserLocation = YES;
_mapView.userTrackingMode = MAUserTrackingModeFollow;
如下代码,隐藏高德SDK默认小蓝点,自定义用户头像为当前位置
_mapView.customizeUserLocationAccuracyCircleRepresentation = YES;
二、屏幕中间添加一个“针”
1、添加屏幕中间位置的“针”
- (void)setUpCenterAnnotationView {
//添加地图中间图标
UIImage *image = [UIImage imageNamed:@"position"];
float origin_X = (self.mapView.frame.size.width - image.size.width)*0.5;
float origin_y = self.mapView.frame.size.height*0.5 - image.size.height;
centerAnnotaionView = [[UIImageView alloc]initWithFrame:CGRectMake(origin_X, origin_y, image.size.width, image.size.height)];
centerAnnotaionView.image = image;
centerAnnotaionView.contentMode = UIViewContentModeScaleAspectFill;
[self.mapView addSubview:centerAnnotaionView];
}
2、给iamgeView添加跳动动画,每次请求高德地图附近停车场的时候,添加一个跳动动画,效果还是挺漂亮的。
//跳动动画
- (void)centerAnnotaionAnimation {
UIImage *centerAnnotationImage = [UIImage imageNamed:@"position"];
float origin_x = (self.view.frame.size.width - centerAnnotationImage.size.width)*0.5;
float origin_y = self.mapView.frame.size.height*0.5 - centerAnnotationImage.size.height*2+10;
//组动画
CAKeyframeAnimation *anima1 = [CAKeyframeAnimation animationWithKeyPath:@"position"];
NSValue *value0 = [NSValue valueWithCGPoint:CGPointMake(origin_x+centerAnnotationImage.size.width/2, origin_y+centerAnnotationImage.size.height+10)];
NSValue *value1 = [NSValue valueWithCGPoint:CGPointMake(origin_x+centerAnnotationImage.size.width/2, origin_y-30+centerAnnotationImage.size.height+10)];
NSValue *value2 = [NSValue valueWithCGPoint:CGPointMake(origin_x+centerAnnotationImage.size.width/2, origin_y+centerAnnotationImage.size.height+10)];
anima1.values = [NSArray arrayWithObjects:value0,value1,value2, nil];
//组动画
CAAnimationGroup *groupAnimation = [CAAnimationGroup animation];
groupAnimation.animations = [NSArray arrayWithObjects:anima1, nil];
groupAnimation.duration = 0.5f;
groupAnimation.fillMode = kCAFillModeForwards;
groupAnimation.removedOnCompletion = NO;
[centerAnnotaionView.layer addAnimation:groupAnimation forKey:@"groupAnimation"];
}
三、地图定位回调代理
1、设置_mapView.showsUserLocation = YES;用户位置或者设备方向更新后,会调用如下函数
/**
* @brief 位置或者设备方向更新后,会调用此函数
* @param mapView 地图View
* @param userLocation 用户定位信息(包括位置与设备方向等数据)
* @param updatingLocation 标示是否是location数据更新, YES:location数据更新 NO:heading数据更新
*/
- (void)mapView:(MAMapView *)mapView didUpdateUserLocation:(MAUserLocation *)userLocation updatingLocation:(BOOL)updatingLocation;
2、在此方法里面我们可以时时的获取到用户当前位置信息,即使没有网络,也会有GPS定位,将维度回调回来
#pragma mark MAMapViewDelegate
- (void)mapView:(MAMapView *)mapView didUpdateUserLocation:(MAUserLocation *)userLocation updatingLocation:(BOOL)updatingLocation {
NSLog(@"%d",updatingLocation);
NSLog(@"位置更新");
NSLog(@"当前位置:%f,%f",userLocation.location.coordinate.latitude,userLocation.location.coordinate.longitude);
if (!userLocation.location || !(userLocation.location.coordinate.latitude>0)) {
return;
}
if (!_currentLocation)
{ //第一次进入地图移动地图至用户当前位置
_mapView.userTrackingMode = MAUserTrackingModeFollow;
[self centerAnnotaionAnimation];
[self POIAroundSearchRequest:[AMapGeoPoint locationWithLatitude:userLocation.location.coordinate.latitude longitude:userLocation.location.coordinate.longitude]];
}
_currentLocation = userLocation.location;
}
(1)在该方法中_currentLocation是一个全局的属性,用来保存用户当前位置的经纬度,如果项目中其他地方要用用户经纬度可以直接拿去用;
(2)如下代码是首次进入地图将地图移动至用户当前位置
_mapView.userTrackingMode = MAUserTrackingModeFollow;
(3)如下调屏幕中间的“针”,跳动动画,动画的方法我们上面已经写好了。
[self centerAnnotaionAnimation];
(4)如下是写的一个发起poi检索的方法,往下我们会看到。
[self POIAroundSearchRequest:[AMapGeoPoint locationWithLatitude:userLocation.location.coordinate.latitude longitude:userLocation.location.coordinate.longitude]];
注意啦,注意啦:到这里大家可以尝试一下,给(3)和(4)两行不同功能的代码写一个queue,异步处理这两个方法看看和这样处理有什么区别,我也是心血来潮,尝试了一下,大家也可以试试,一边做动画,一边请求高德地图附近停车场信息。
四、地图其他代理方法
直接上代码把,看看注释。- removeStopAnnotaion方法是自己写的一个移除地图上所有大头针的方法,往下我们会看到。
1、用户操作地图的代理
/**
* @brief 地图将要发生移动时调用此接口
*/
- (void)mapView:(MAMapView *)mapView mapWillMoveByUser:(BOOL)wasUserAction {
if (wasUserAction) {
//地图将要移动时,移除地图上所有附近停车场的大头针
[self removeStopAnnotaion];
}
}
/**
* @brief 地图移动结束后调用此接口
*/
- (void)mapView:(MAMapView *)mapView mapDidMoveByUser:(BOOL)wasUserAction {
if (wasUserAction)
{
NSLog(@"滑动地图结束");
//地图滑动结束后,用当前用户位置发起POI检索
[self POIAroundSearchRequest:[AMapGeoPoint locationWithLatitude:mapView.centerCoordinate.latitude longitude:mapView.centerCoordinate.longitude]];
}
}
/**
* @brief 地图将要发生缩放时调用此接口
*/
- (void)mapView:(MAMapView *)mapView mapWillZoomByUser:(BOOL)wasUserAction {
if (wasUserAction) {
[self removeStopAnnotaion];
}
}
/**
* @brief 地图缩放结束后调用此接口
*/
- (void)mapView:(MAMapView *)mapView mapDidZoomByUser:(BOOL)wasUserAction {
NSLog(@"地图缩放结束");
if (wasUserAction) {
[self POIAroundSearchRequest:[AMapGeoPoint locationWithLatitude:mapView.centerCoordinate.latitude longitude:mapView.centerCoordinate.longitude]];
}
}
wasUserAction是指用户操作时的回调,如果wasUserAction是NO,则不做任何处理,高德地图加载过程中用户不操作也会调用如上这些方法,所以这个字段可以说明是不是用户操作。
2、添加大头针的代理
当添加大头针的时候就会执行该代理,生成大头针视图。
/**
* @brief 根据anntation生成对应的View
*/
- (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.canShowCallout = NO;
annotationView.image = [UIImage imageNamed:@"heardImg_passenger_default"];
annotationView.frame = CGRectMake(0, 0, 26, 26);
annotationView.contentMode = UIViewContentModeScaleToFill;
annotationView.layer.masksToBounds = YES;
return annotationView;
}
//停车场位置大头针
else if ([annotation isKindOfClass:[MAPointAnnotation class]]) {
static NSString *stopCarReuseIndetifier = @"stopCarReuseIndetifier";
MAAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:stopCarReuseIndetifier];
if (annotationView == nil)
{
annotationView = [[MAAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:stopCarReuseIndetifier];
}
annotationView.canShowCallout = YES;
UIImage *image = [UIImage imageNamed:@"centerAnnotation"];
annotationView.image = image;
annotationView.frame = CGRectMake(0, 0, image.size.width, image.size.height);
annotationView.contentMode = UIViewContentModeScaleToFill;
annotationView.layer.masksToBounds = YES;
annotationView.centerOffset = CGPointMake(0, -0.5*image.size.height);
return annotationView;
}
return nil;
}
五、自定义的一些私有方法
1、移除地图上所有的停车场大头针的方法
要注意同时访问self.dataSource,会造成数据错乱,有些大头针移除不掉的问题。所以需要先创建一个数组接收需要移除的大头针,self.dataSource只存储最新需要显示的大头针数据。
//移除地图上所有的停车场大头针
- (void)removeStopAnnotaion {
[UIView animateWithDuration:.5 animations:^{
//用一个数组去接收需要移除的大头针
NSMutableArray *removeAnnotations = [[NSMutableArray alloc]init];
//除了当前位置的大头针,其余的都需要移除
[removeAnnotations addObjectsFromArray:self.mapView.annotations];
[removeAnnotations removeObject:self.mapView.userLocation];
//移除需要移除的大头针
[self.mapView removeAnnotations:removeAnnotations];
} completion:^(BOOL finished) {
[self centerAnnotaionAnimation];
}];
}
2、发起poi检索的方法
//发起poi检索
- (void)POIAroundSearchRequest:(AMapGeoPoint *)point {
//取消所有未回调的请求,防止多次叠加请求,防止造成数据源错乱
[self.searchAPI cancelAllRequests];
//地图移动结束,请求高德地图附近停车场信息
AMapPOIAroundSearchRequest *request = [[AMapPOIAroundSearchRequest alloc]init];
request.keywords = @"停车库";
request.radius = 3000;
request.location = point;
/*发起搜索*/
[self.searchAPI AMapPOIAroundSearch:request];
}
self.searchAPI是一个全局的高德地图POI搜索类
3、跳动动画
屏幕中间“针”的跳动动画,上面已说过了。
六、高德地图POI检索回调
#pragma mark AMapSearchDelegate
/**
* @brief POI查询回调函数
*/
- (void)onPOISearchDone:(AMapPOISearchBaseRequest *)request response:(AMapPOISearchResponse *)response
{
if (response.pois.count == 0) {
NSLog(@"暂无停车场信息");
return;
}
//清空数据源
[self.dataSource removeAllObjects];
for (AMapPOI *poi in response.pois) {
NSLog(@"%@",poi.name);
NSLog(@"%@",poi.address);
MAPointAnnotation *anotation = [[MAPointAnnotation alloc]init];
anotation.title = poi.name;
anotation.subtitle = poi.address;
anotation.coordinate = CLLocationCoordinate2DMake(poi.location.latitude, poi.location.longitude);
[self.dataSource addObject:anotation];
}
//添加附近车库大头针
[self.mapView addAnnotations:self.dataSource];
}
self.dataSource是一个全局的可变数组,用户存储数据源,有了数据源我们可以做我们想做的操作。
通过此数据源你也可以将附近的停车场信息显示在一个tableView上,提供用户选择,大多数项目多有这样做的,都是大同小异,只要有了数据,其他只是展示数据、刷新数据了。
最后附上效果图和github地址大家可以克隆下来看看,有不多的地方请多多指教。
此外提醒大家看demo的时候不要忘了配置自己的AppKey哦,这玩意我就不给你提供了。
网友评论