iOS 百度地图在房地产项目中的应用
Posted xj_love
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS 百度地图在房地产项目中的应用相关的知识,希望对你有一定的参考价值。
1.公司的项目是面向房地产的,包含新房(全国多个分公司),存租房(与建行建方的合作)项目,所以地图与看房相结合比较多,之前为了进度,地图这一块的业务都是H5实现,现在稳定下来后,H5的体验度不是很高,所以地图这一块全部换成原生。这篇文章也是做个探索和总结,以便大家一起参考学习。
2.地图采用百度地图,主要功能包括:定位+替换大头针图标,两点连线及采用自定义图片样式,导航,点标注,自定义标注UI,点击事件,点聚合的算法(重点)+优化
一. 定位+替换大头针图标
#pragma mark - 定位当前位置
- (void)initLocation
///BMKLocationManager类。初始化之前请设置 BMKLocationAuth 中的APIKey,否则将无法正常使用服务.
_locationManager = [[BMKLocationManager alloc] init];
_locationManager.delegate = self;
_locationManager.coordinateType = BMKLocationCoordinateTypeBMK09LL;
_locationManager.distanceFilter = kCLDistanceFilterNone;
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
_locationManager.activityType = CLActivityTypeAutomotiveNavigation;
_locationManager.pausesLocationUpdatesAutomatically = NO;
_locationManager.allowsBackgroundLocationUpdates = YES;
_locationManager.locationTimeout = 10;
_locationManager.reGeocodeTimeout = 10;
__weak BMKClusterAnnotationPage *weakSelf = self;
///单次定位。如果当前正在连续定位,调用此方法将会失败,返回NO。\\n该方法将会根据设定的 desiredAccuracy 去获取定位信息。如果获取的定位信息精确度低于 desiredAccuracy ,将会持续的等待定位信息,直到超时后通过completionBlock返回精度最高的定位信息。\\n可以通过 stopUpdatingLocation 方法去取消正在进行的单次定位请求
[_locationManager requestLocationWithReGeocode:YES withNetworkState:YES completionBlock:^(BMKLocation * _Nullable location, BMKLocationNetworkState state, NSError * _Nullable error)
BMKClusterAnnotationPage *strongSelf = weakSelf;
MyLocation * loc = [[MyLocation alloc]initWithLocation:location.location withHeading:nil];
[strongSelf addLocToMapView:loc];
];
//替换大头针图片方法之一
BMKLocationViewDisplayParam *displayParam = [[BMKLocationViewDisplayParam alloc] init];
displayParam.locationViewOffsetX=0;//定位偏移量(经度)
displayParam.locationViewOffsetY=0;//定位偏移量(纬度)
displayParam.isAccuracyCircleShow=NO;//经度圈是否显示
//这里替换自己的图标路径,必须把图片放到百度地图SDK的Resources/mapapi.bundle/images 下面
//还有一种方法就是获取到_locationView之后直接设置图片
displayParam.locationViewImgName=@"pin_red";
[_mapView updateLocationViewWithParam:displayParam];
- (void)addLocToMapView:(MyLocation *)loc
[_mapView updateLocationData:loc];
[_mapView setCenterCoordinate:loc.location.coordinate animated:YES];
[_mapView setZoomLevel:18];
_mapView.showsUserLocation = YES; //一定要设置这个参数为YES,不然大头针不出来
二.两点连线及采用自定义图片样式
#pragma mark - 两点之间划线
- (void)lineTwoAction:(MyLocation*)myLoc andOther:(MyLocation*)otherLoaction
CLLocationCoordinate2D coors[2] = 0;
coors[1].latitude = myLoc.location.coordinate.latitude;
coors[1].longitude = myLoc.location.coordinate.longitude;//定位坐标1
coors[0].latitude = otherLoaction.location.coordinate.latitude;
coors[0].longitude = otherLoaction.location.coordinate.longitude;//定位坐标2
BMKPolyline *polyLine = [BMKPolyline polylineWithCoordinates:coors count:2];
[_mapView addOverlay:polyLine];
//一定要实现这个代理方法
- (BMKOverlayView *)mapView:(BMKMapView *)mapView viewForOverlay:(id<BMKOverlay>)overlay
//连线,设置宽度,颜色等
BMKPolylineView *polylineView = [[BMKPolylineView alloc] initWithPolyline:overlay];
polylineView.strokeColor = [[UIColor purpleColor] colorWithAlphaComponent:1];
polylineView.lineWidth = 10.0;
//使用自定义图片连线
/*
BMKMapPoint point;
point.x = 0;
point.y = 0;
[polylineView renderTexturedLinesWithPoints:&point pointCount:2 lineWidth:10 textureID:[polylineView loadStrokeTextureImage:[UIImage imageNamed:@"xxx"]] looped:YES];
*/
return polylineView;
三.导航
我们做的导航没有内置在自己的APP里,而是调起第三方地图软件,进行导航。包括苹果原生地图,高德地图,百度地图。需传入起点终点经纬度,调起代码:
-(void)navigation:(NSDictionary*)param
//start_lng: 起点经度
//start_lat: 起点维度
//end_lng: 终点经度
//end_lat: 终点维度
//end_name: 终点楼盘名称
NSString *start_lng = [NSString stringWithFormat:@"%@", param[@"start_lng"]];
NSString *start_lat = [NSString stringWithFormat:@"%@", param[@"start_lat"]];
NSString *start_name = [NSString stringWithFormat:@"%@", param[@"start_address"]];
NSString *end_lng = [NSString stringWithFormat:@"%@", param[@"end_lng"]];
NSString *end_lat = [NSString stringWithFormat:@"%@", param[@"end_lat"]];
NSString *end_name = [NSString stringWithFormat:@"%@", param[@"end_name"]];
UIAlertController *avc = [UIAlertController alertControllerWithTitle:@"请选择导航地图" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
UIApplication *app = [UIApplication sharedApplication];
// -canOpenURL: failed for URL: "iosamap://navi" - error: "未能完成操作。(“OSStatus”错误 -10814。)"
if ([app canOpenURL:[NSURL URLWithString:@"map://"]])
UIAlertAction *action = [UIAlertAction actionWithTitle:@"使用苹果自带地图导航" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action)
CLLocationCoordinate2D coords1 = CLLocationCoordinate2DMake(start_lat.floatValue,start_lng.floatValue);
CLLocationCoordinate2D coords2 = CLLocationCoordinate2DMake(end_lat.floatValue,end_lng.floatValue);
MKMapItem *currentLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:coords1 addressDictionary:nil]];
currentLocation.name = start_name;
MKMapItem *toLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:coords2 addressDictionary:nil]];
toLocation.name = end_name;
NSArray *items = [NSArray arrayWithObjects:currentLocation, toLocation, nil];
NSDictionary *options = @ MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving, MKLaunchOptionsMapTypeKey: [NSNumber numberWithInteger:MKMapTypeStandard], MKLaunchOptionsShowsTrafficKey:@YES ; //打开苹果自身地图应用,并呈现特定的item
[MKMapItem openMapsWithItems:items launchOptions:options];
];
[avc addAction:action];
if ([app canOpenURL:[NSURL URLWithString:@"iosamap://navi"]])
UIAlertAction *action = [UIAlertAction actionWithTitle:@"使用高德地图导航" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action)
NSString *url = [[NSString stringWithFormat:@"iosamap://path?sourceApplication=applicationName&sid=BGVIS1&slat=%@&slon=%@&sname=%@&did=BGVIS2&dlat=%@&dlon=%@&dname=%@&dev=0&t=0", start_lat,start_lng,start_name,end_lat,end_lng,end_name] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
// NSString *url = [[NSString stringWithFormat:@"iosamap://navi?sourceApplication=applicationName&backScheme=applicationScheme&poiname=%@&poiid=BGVIS&lat=%@=%@&dev=1&style=2", end_name, end_lat, end_lng] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
];
[avc addAction:action];
if ([app canOpenURL:[NSURL URLWithString:@"baidumap://map"]])
UIAlertAction *action = [UIAlertAction actionWithTitle:@"使用百度地图导航" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action)
NSString *url = [[NSString stringWithFormat:@"baidumap://map/direction?origin=latlng:%@,%@|name:%@&destination=latlng:%@,%@|name:%@&mode=driving&src=webapp.navi.yourCompanyName.yourAppName", start_lat,start_lng,start_name,end_lat,end_lng,end_name]
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
];
[avc addAction:action];
UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action)
];
[avc addAction:cancel];
if (kIsIPAD)
UIPopoverController *poc = [[UIPopoverController alloc] initWithContentViewController:avc];
[poc presentPopoverFromRect:CGRectMake(SCREEN_WIDTH / 2.0, SCREEN_HEIGHT - 60, 200, 200) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
// avc.modalPresentationStyle = UIModalPresentationPopover;
// avc.popoverPresentationController.sourceView = self.view;
// avc.popoverPresentationController.sourceRect = CGRectMake(SCREEN_WIDTH / 2.0, SCREEN_HEIGHT - 60, 200, 200);
// avc.popoverPresentationController.permittedArrowDirections = UIPopoverArrowDirectionDown;
// [self presentViewController:avc animated:YES completion:nil];
else
[self presentViewController: avc animated: YES completion: nil];
四.点标注+自定义标注UI+点击事件
1.需要用到的相关代理
/**
地图加载完成时会调用此方法
@param mapView 当前地图View
*/
- (void)mapViewDidFinishLoading:(BMKMapView *)mapView
[self updateClusters];
/**
地图渲染每一帧画面过程中,以及每次需要重新绘制地图时(例如添加覆盖物)都会调用此方法
@param mapView 地图View
@param status 地图状态
*/
- (void)mapView:(BMKMapView *)mapView onDrawMapFrame:(BMKMapStatus *)status
if (_clusterZoom != 0 && _clusterZoom != (NSInteger)mapView.zoomLevel)
[self updateClusters];
2.添加标注,至于__block NSArray *array = [_clusterManager getClusters:_clusterZoom]里面的对象,可以参考百度demo BMKClusterAnnotationPage类里面。不过也只是自定义的一个NSObject对象。
#pragma mark - Clusters
- (void)updateClusters
_clusterZoom = (NSInteger)_mapView.zoomLevel;
@synchronized(_clusterManager.clusterCaches)
NSMutableArray *clusters = [_clusterManager.clusterCaches objectAtIndex:(_clusterZoom - 3)];
if (clusters.count > 0)
/**
移除一组标注
@param annotations 要移除的标注数组
*/
[_mapView removeAnnotations:_mapView.annotations];
//将一组标注添加到当前地图View中
[_mapView addAnnotations:clusters];
else
dispatch_async(dispatch_get_global_queue(0, 0), ^
///获取聚合后的标注
__block NSArray *array = [_clusterManager getClusters:_clusterZoom];
dispatch_async(dispatch_get_main_queue(), ^
for (BMKCluster *item in array)
ClusterAnnotation *annotation = [[ClusterAnnotation alloc] init];
//设置标注的经纬度坐标
annotation.coordinate = item.coordinate;
annotation.size = item.size;//标识
annotation.title = @""; //为空点击就没有气泡弹出
[clusters addObject:annotation];
/**
移除一组标注
@param annotations 要移除的标注数组
*/
[_mapView removeAnnotations:_mapView.annotations];
//将一组标注添加到当前地图View中
[_mapView addAnnotations:clusters];
);
);
3.根据anntation生成对应的View(就是自定义的大头针)
#pragma mark - BMKMapViewDelegate
// 根据anntation生成对应的View
- (BMKAnnotationView *)mapView:(BMKMapView *)mapView viewForAnnotation:(id <BMKAnnotation>)annotation
ClusterAnnotation *cluster = (ClusterAnnotation*)annotation;
BMKPinAnnotationView *annotationView = [[BMKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:annotationViewIdentifier];
if (cluster.size > 1)
annotationView.bounds = CGRectMake(0, 0, 100, 96);
else
annotationView.bounds = CGRectMake(0, 0, 100, 37);
annotationView.image = nil;
UIView *backView = [[UIView alloc] init];
UIImageView *tapImageView = [[UIImageView alloc] init];
tapImageView.image = [UIImage imageNamed:@"marker-golden-build"];
if (cluster.size > 1) //根据标识,来绘制不同的图片
backView.frame = CGRectMake(0, 0, 100, 96);
tapImageView.frame = CGRectMake(33, 17, 34, 58);
tapImageView.image = [UIImage imageNamed:@"marker-golden-build"];
annotationView.bounds = CGRectMake(0, 0, 100, 96);
tapImageView.image = [UIImage imageNamed:@"marker-golden-build"];
UIImageView *bottomImgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"marker-golden-circle"]];
bottomImgView.frame = CGRectMake(24, tapImageView.frame.origin.y+58,52, 21);
[backView addSubview:bottomImgView];
else
backView.frame = CGRectMake(0, 0, 100, 37);
tapImageView.frame = CGRectMake(32, 17, 25, 20);
annotationView.bounds = CGRectMake(0, 0, 100, 37);
tapImageView.image = [UIImage imageNamed:@"branch-build"];
[backView addSubview:tapImageView];
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 15)];
titleLabel.backgroundColor = [UIColor orangeColor];
titleLabel.text = [NSString stringWithFormat:@"我有%ld套房源", cluster.size];
titleLabel.font = [UIFont systemFontOfSize:14];
titleLabel.textAlignment = NSTextAlignmentCenter;
[backView addSubview:titleLabel];
[annotationView addSubview:backView];
annotationView.draggable = YES;
annotationView.annotation = annotation;
return annotationView;
4.踩坑集合:
4.1 如果想点击图标弹出气泡,在第二步annotation.title = @"";时一定要传值,不然无效
4.2 如果annotation.title = @""为空,图标自带的点击事件就不会相应
4.3 如果要点击事件,又不想气泡,在自定义图标上加个手势事件
4.4 百度有个自带的大头针,annotationView.image = nil; 除去
4.5 要想点击事件有效,必须正确设置annotationView.bounds和自定义的UI大小一致;
4.6 annotationView.image = nil;和annotationView.bounds;要放在自定义控件前面定义
五.点聚合的算法(重点)+优化
以上是关于iOS 百度地图在房地产项目中的应用的主要内容,如果未能解决你的问题,请参考以下文章