高德地图sdk分析 - 简书
高德地图sdk分析
高德地图sdk是目前国内使用比较多的地图类sdk(还有百度地图也不错),目前项目中也用到了,但是相关封装还是不够清晰。为了做好这一层封装,首先需要把高德地图sdk研究一下。
高德地图有各种语言版本的sdk,其中iOS的sdk就包含基本sdk、云图sdk,导航sdk。后两个sdk暂时用不到,而基本sdk中又包含2d(栅格地图)和3d(矢量地图)两个版本的库以及搜索的库。今天要分析的就是2d和搜索的framework,最新的sdk版本是2.4.0。
几个核心类说明
地图视图类,sdk中最重要的一个类,用来负责地图的展示,该类直接从UIView继承而来。
1、属性visibleMapRect
self.mapView.visibleMapRect = MAMapRectMake(, , 6656);
它定义了地图的可见范围,如下图所示:
mamap_2.png
我们如果改变visibleMapRect的大小,地图就会显示不同的区域。
2、属性mapType地图类型,有两种类型: 普通地图和卫星地图,我们经常用到的就是普通地图
typedef NS_ENUM(NSInteger, MAMapType)
MAMapTypeStandard,
// 普通地图
MAMapTypeSatellite
// 卫星地图
3、属性showTraffic是否展示路况拥堵信息,默认是不展示的,一般也用不到。
4、属性scrollEnabled和zoomEnabledMAMapView虽然不是UIScrollView,但自身也实现了滚动和缩放功能(UIWebView同理)。这两个属性可以控制缩放和滚动的开关,默认都是打开的。
5、属性logoCenter和logoSize高德的logo位置和大小,这个logo是需要显示出来的,不能隐藏不能遮挡(尊重知识产权)
6、属性showsCompass、compassOrigin、compassSize地图的罗盘是否展示,展示的位置和大小
7、属性showsScale、scaleOrigin、scaleSize地图的比例尺是否展示,展示的位置和大小
8、属性centerCoordinate地图中心点的经纬度,改变它不会影响缩放比例。
9、属性showsUserLocation、userLocation、userTrackingMode是否显示用户位置,用户位置的数据、用户追踪的模式。
10、属性annotations地图上的标注,显示对应位置有什么东西,比较常用。
11、属性overlays地图上的覆盖图形,能够在地图指定位置绘制自定义的图层,比较常用。
12、属性distanceFilter、desiredAccuracy、headingFilter最小更新距离,定位精度,最小更新角度。
13、协议,MAMapViewDelegate,作为一个自定义的视图,当其数据对应数据发生变化时,肯定会有一些函数回调来改变自身。这些方法都被集中在MAMapViewDelegate中。一共有18个方法,大致可以分为4类:地图区域改变、用户位置发生变化、标注的创建和事件响应已经覆盖层的一些逻辑。个人觉得这个协议太大了,不符合接口分离原则 。
AMapSearchAPI
AMapSearchAPI是一个NSObject,代表高德地图的搜索功能。
1、属性timeOut。搜索请求超时时间,默认是20秒。
2、查询接口,不同的查询类型有不同的查询接口。
//POI查询接口函数,即根据 POI 参数选项进行 POI 查询。
- (void)AMapPlaceSearch:(AMapPlaceSearchRequest *)
//路径规划查询接口。
- (void)AMapNavigationSearch:(AMapNavigationSearchRequest *)
//输入提示查询接口。
- (void)AMapInputTipsSearch:(AMapInputTipsSearchRequest *)
//地址编码查询接口。
- (void)AMapGeocodeSearch:(AMapGeocodeSearchRequest *)
//逆地址编码查询接口。
- (void)AMapReGoecodeSearch:(AMapReGeocodeSearchRequest *)
//公交线路查询接口。
- (void)AMapBusLineSearch:(AMapBusLineSearchRequest *)
//公交车站查询接口。
- (void)AMapBusStopSearch:(AMapBusStopSearchRequest *)
3、协议AMapSearchDelegate,包含对各种请求接口成功失败的回调。
可以实现的功能
自定义用户坐标点
如果起用了定位,如下的方法会被调用到,因为自身打点也是一个Annotation,但这个Annotation的类型是MAUserLocation。然后通过设置MAUserLocationRepresentation,就可以将用户坐标点进行自定义。
- (void)mapView:(MAMapView *)mapView didAddAnnotationViews:(NSArray *)views
MAAnnotationView *view = views[0];
// 放到该方法中用以保证userlocation的annotationView已经添加到地图上了。
if ([view.annotation isKindOfClass:[MAUserLocation class]])
MAUserLocationRepresentation *pre = [[MAUserLocationRepresentation alloc] init];
pre.fillColor = [UIColor colorWithRed:0.9 green:0.1 blue:0.1 alpha:0.3];
pre.strokeColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.9 alpha:1.0];
pre.image = [UIImage imageNamed:@"location.png"];
pre.lineWidth = 3;
pre.lineDashPattern = @[@6, @3];
[self.mapView updateUserLocationRepresentation:pre];
view.calloutOffset = CGPointMake(0, 0);
缩放和滚动有属性直接控制,单击双击也能够支持,但是为了和AnnotationView进行区分,需要用下面的方法进行过滤。
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
浮层对象是遵循MAOverlay协议的对象,可以是圆、折线和多边形。在高德sdk中,MACircle、MAPolyline、MAPolygon都是浮层对象。然后通过
- (void)addOverlays:(NSArray *)
将浮层对象添加到MapView中。
自定义浮层
可以自定义浮层对象,只要符合MAOverlay协议即可。然后在绘制图层的代理方法中
- (MAOverlayRenderer *)mapView:(MAMapView *)mapView viewForOverlay:(id &MAOverlay&)overlay
子类话一个MAOverlayRenderer并返回,该子类只要重写方法
- (void)drawMapRect:(MAMapRect)mapRect zoomScale:(MAZoomScale)zoomScale inContext:(CGContextRef)context
该方法就如果UIView的drawRect,可以随心所欲的在上面画任何东西。
Overlay可以直接贴图,使用MAGroundOverlay类。虽然这个功能用自定义Overlay的方式也能实现,但比较麻烦。用MAGroundOverlay就很简单。
Overlay还支持大地曲线:MAGeodesicPolyline,图片tiles:MATileOverlay。
Annotaion就是在地图上标记一个位置,然后展示出来。展示的视图就是用MAAnnotationView。像MapView插入Annotation的方法是:
- (void)addAnnotation:(id &MAAnnotation&)
类似UITableView,MAAnnotationView的创建实在代理方法中实现的。
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id&MAAnnotation&)annotation
MAAnnotationView可以自定义,可以有更好的显示效果;Annotation还支持动画,让显示的点动起来。
POI(Point of Interest),信息点,一家餐馆就是一个信息点。POI搜索可以根据ID、关键字、中心点搜索周边、指定范围搜索等搜索方式来满足不同的需求。代码如下:
/* 根据ID来搜索POI. */
- (void)searchPoiByID
AMapPlaceSearchRequest *request = [[AMapPlaceSearchRequest alloc] init];
B000A80WBJ
B00141IEZK
B000A876EH
B000A7O1CU
request.searchType
= AMapSearchType_PlaceID;
request.uid
= @"B000A07060";
request.requireExtension
[self.search AMapPlaceSearch:request];
/* 根据关键字来搜索POI. */
- (void)searchPoiByKeyword
AMapPlaceSearchRequest *request = [[AMapPlaceSearchRequest alloc] init];
request.searchType
= AMapSearchType_PlaceK
request.keywords
= @"肯德基";
request.city
= @[@"010"];
request.requireExtension
[self.search AMapPlaceSearch:request];
/* 根据中心点坐标来搜周边的POI. */
- (void)searchPoiByCenterCoordinate
AMapPlaceSearchRequest *request = [[AMapPlaceSearchRequest alloc] init];
request.searchType
= AMapSearchType_PlaceA
request.location
= [AMapGeoPoint locationWithLatitude:39.990459 longitude:116.481476];
request.keywords
= @"餐饮";
/* 按照距离排序. */
request.sortrule
request.requireExtension
/* 添加搜索结果过滤 */
AMapPlaceSearchFilter *filter = [[AMapPlaceSearchFilter alloc] init];
filter.costFilter = @[@"100", @"200"];
filter.requireFilter = AMapRequireG
request.searchFilter =
[self.search AMapPlaceSearch:request];
/* 在指定的范围内搜索POI. */
- (void)searchPoiByPolygon
NSArray *points = [NSArray arrayWithObjects:
[AMapGeoPoint locationWithLatitude:39.990459 longitude:116.481476],
[AMapGeoPoint locationWithLatitude:39.890459 longitude:116.581476],
AMapGeoPolygon *polygon = [AMapGeoPolygon polygonWithPoints:points];
AMapPlaceSearchRequest *request = [[AMapPlaceSearchRequest alloc] init];
request.searchType
= AMapSearchType_PlaceP
request.polygon
request.keywords
= @"Apple";
request.requireExtension
[self.search AMapPlaceSearch:request];
输入提示查询
AMapInputTipsSearchRequest *tips = [[AMapInputTipsSearchRequest alloc] init];
tips.keywords = @"关键字";
[self.search AMapInputTipsSearch:tips];
输入提示回调
- (void)onInputTipsSearchDone:(AMapInputTipsSearchRequest *)request response:(AMapInputTipsSearchResponse *)response
[self.tips setArray:response.tips];
[self.displayController.searchResultsTableView reloadData];
搜索地理编码
AMapGeocodeSearchRequest *geo = [[AMapGeocodeSearchRequest alloc] init];
geo.address =
if (adcode.length & 0)
geo.city = @[adcode];
[self.search AMapGeocodeSearch:geo];
地理编码回调,得到一个地点的经纬度信息
- (void)onGeocodeSearchDone:(AMapGeocodeSearchRequest *)request response:(AMapGeocodeSearchResponse *)response
逆地理编码
逆地理编码与地理编码正好相反,是通过经纬度来查询文字描述的位置信息。发起逆地理编码查询
AMapReGeocodeSearchRequest *regeo = [[AMapReGeocodeSearchRequest alloc] init];
regeo.location = [AMapGeoPoint locationWithLatitude:coordinate.latitude longitude:coordinate.longitude];
regeo.requireExtension = YES;
[self.search AMapReGoecodeSearch:regeo];
逆地理编码回调
- (void)onReGeocodeSearchDone:(AMapReGeocodeSearchRequest *)request response:(AMapReGeocodeSearchResponse *)response
if (response.regeocode != nil)
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(request.location.latitude, request.location.longitude);
ReGeocodeAnnotation *reGeocodeAnnotation = [[ReGeocodeAnnotation alloc] initWithCoordinate:coordinate
reGeocode:response.regeocode];
[self.mapView addAnnotation:reGeocodeAnnotation];
除了以上的搜索,还有导航、搜索公交路线、公交站,这些再一般的应用中不会用到,就不介绍了。
i码农@南京