基础地图
开发者可利用SDK提供的接口,使用百度提供的基础地图数据。目前百度地图SDK所提供的地图等级为19级,所包含的信息有建筑物、道路、河流、学校、公园等内容。
百度地图支持多点触摸、双击放大、多点单击缩小、旋转等手势操作,此外自2.2.0版本起,支持相应的控制接口来开启/关闭这些手势操作;此外,在该版本地图对象实现了多实例特性,即开发者可以在一个页面中建立多个地图对象,并且针对这些对象分别操作且不会产生相互干扰。具体使用方法请参考MultiMapViewDemo的介绍。
地图上自定义的标注点和覆盖物我们统称为地图覆盖物。您可以通过定制BMKAnnotation和BMKOverlay来添加对应的标注点和覆盖物。地图覆盖物的设计遵循数据与View分离的原则,BMKAnnotation和BMKOverlay系列的类主要用来存放覆盖物相关的数据,BMKAnnotaionView和BMKOverlayView系列类为覆盖物对应的View。
SDK支持画点、折线、圆、多边形(包括凹凸两种)、图片图层和自定义覆盖物。从2.0.0开始矢量地图采用OpenGL绘制,新增支持OpenGL绘制的基本线绘制、面绘制接口。详见AnnotationDemo,SDK内置的BMKPolylineOverlay、BMKPolygonOverlay,BMKCircleOverlay均采用OpenGL绘制。
1. 卫星图
//切换为卫星图
[_mapView setMapType:BMKMapTypeSatellite];
运行后效果如下:
2. 由卫星图切换为普通矢量图的核心代码如下:
//切换为普通地图
[_mapView setMapType:BMKMapTypeStandard];
3. 实时交通图
利用地图SDK所提供的接口,开发者可显示当前地图城市内的实时路况信息(点击查看支持实时路况的城市)。此外,自2.0.0版本起,SDK还支持城际(城市之间,如高速)路况。
开启实时路况的核心代码如下:
//打开实时路况图层
[_mapView setTrafficEnabled:YES];
运行后效果如下:
关闭实时路况的核心代码如下:
//关闭实时路况图层
[_mapView setTrafficEnabled:NO];
4. 百度城市热力图
百度地图SDK继为广大开发者开放热力图本地绘制能力之后,再次进一步开放百度自有数据的城市热力图层,帮助开发者构建形式更加多样的移动端应用。
百度城市热力图的性质及使用与实时交通图类似,只需要简单的接口调用,即可在地图上展现样式丰富的百度城市热力图。
在地图上使用百度城市热力图的核心代码如下:
//打开百度城市热力图图层(百度自有数据)
[_mapView setBaiduHeatMapEnabled:YES];
运行后效果如下:
//关闭百度城市热力图图层(百度自有数据)
[_mapView setBaiduHeatMapEnabled:NO];
5. 地图标注
1). 标注
BMKAnnotation为标注对应的protocal,您可以自定义标注类实现该protocal。百度地图SDK也预置了基本的标注点(BMKPointAnnotation)和一个大头针标注View(BMKPinAnnotationView),您可以直接使用来显示标注。方法如下:
第一步,ViewController 遵守 BMKMapViewDelegate 协议:
第二步,修改ViewController.m文件,实现BMKMapViewDelegate的_mapView:viewForAnnotation:函数,并在viewDidAppear添加标注数据对象,核心代码如下:
运行后,会在地图显示对应的标注点,点击会弹出气泡,效果如图:
通过以上几步简单的操作,您就可以实现在地图上添加标注了,相应的删除标注方法如下:
2). 点聚合功能
自v2.9.0版本起,新增点聚合功能,可通过缩小地图层级,将定义范围内的多个标注点,聚合显示成一个标注点,解决加载大量点要素到地图上产生覆盖现象的问题,并提高性能。此次在Demo中开放源码,方便开发者自行修改。
添加点聚合的方法:
I. 声明点聚合管理类为全局变量,并初始化,核心代码如下:
BMKClusterManager*_clusterManager;//点聚合管理类
//初始化点聚合管理类
_clusterManager = [[BMKClusterManager alloc]init];
II. 向点聚合管理类中添加点,核心代码如下
CLLocationCoordinate2D coor = CLLocationCoordinate2DMake(39.915,116.404);
//向点聚合管理类中添加标注
for(NSInteger i=0;i<20;i++){
double lat=(arc4random()%100)*0.001f;
double lon=(arc4random()%100)*0.001f;
BMKClusterItem *clusterItem = [[BMKClusterItem alloc]init];
clusterItem.coor = CLLocationCoordinate2DMake(coor.latitude+lat,coor.longitude+lon);[_clusterManager addClusterItem:clusterItem];
}
III. 获取聚合后的点,并添加到地图中,核心代码如下
///获取聚合后的标注
NSArray *array = [_clusterManager getClusters:_clusterZoom];
NSMutableArray *clusters = [NSMutableArray array];
for(BMKCluster *iteminarray) {
ClusterAnnotation *annotation = [[ClusterAnnotation alloc]init];
annotation.coordinate = item.coordinate;
annotation.size = item.size;
annotation.title = [NSString stringWithFormat:@"我是%ld个",item.size];
[clusters addObject:annotation];
}
[_mapView removeAnnotations:_mapView.annotations];
[_mapView addAnnotations:clusters];
具体源码请在ClusterDemo中查看。
3). 底图标注
自v2.9.0版本起,SDK给BMKMapView提供了控制底图标注的showMapPoi方法,默认显示底图标注。利用此方法可得到仅显示道路信息的地图。
将底图标注设置为隐藏,方法如下:
//设置隐藏地图标注
[_mapView setShowMapPoi:NO];
运行后,底图标注被隐藏,效果如图:
4). 几何图形
百度地图SDK支持的几何图形有:折线、弧线、多边形和圆,折线、弧线及其他几何图形的边框自v2.6.0版本起支持使用虚线或者纹理图片进行绘制(具体使用方法请参考官方Demo,覆盖物章节的介绍)。我们可利用相应的接口,在地图上快速绘制这些图形,满足相应的业务需求。
I. 折线
在地图上添加折线的方法如下:
运行后效果如下:
iOS地图SDK自v2.8.0版本起,新增了折线多段颜色绘制能力,实现的核心代码如下:
运行效果如下:
自v2.9.0版本起,新增了折线分段颜色绘制能力
实现的核心代码如下:
第一步,添加折线分段颜色绘制覆盖物,核心代码如下:
CLLocationCoordinate2D coords[5]={0};
coords[0].latitude=39.965;
coords[0].longitude=116.404;
coords[1].latitude=39.925;
coords[1].longitude=116.454;
coords[2].latitude=39.955;
coords[2].longitudev = 116.494;
coords[3].latitudev=39.905;
coords[3].longitude =116.554;
coords[4].latitude = 39.965;
coords[4].longitude = 116.604;
//构建分段颜色索引数组
NSArray*colorIndexs = [NSArray arrayWithObjects:[NSNumber numberWithInt:2],
[NSNumber numberWithInt:0],
[NSNumber numberWithInt:1],
[NSNumber numberWithInt:2],nil];
//构建BMKPolyline,使用分段颜色索引,其对应的BMKPolylineView必须设置colors属性.
BMKPolyline*colorfulPolyline=[BMKPolyline polylineWithCoordinates:coords count:5 textureIndex:colorIndexs];
[_mapView addOverlay:colorfulPolyline];
第二步,实现BMKMapViewDelegate回调,核心代码如下:
//根据overlay生成对应的View
- (BMKOverlayView*)mapView:(BMKMapView*)mapView viewForOverlay:(id)overlay {
if([overlay isKindOfClass:[BMKPolylineclass]]) {
BMKPolylineView *polylineView = [[BMKPolylineView alloc]initWithOverlay:overlay];
polylineView.lineWidth=5;
/// 使用分段颜色绘制时,必须设置(内容必须为UIColor)
polylineView.colors = [NSArray arrayWithObjects:[UIColor greenColor],
[UIColor redColor],
[UIColor yellowColor],nil];
returnpolylineView;
}
returnnil;
}
运行效果如下:
II. 弧线
百度地图iOS SDK自v2.1.1版本起,新增了绘制弧线的方法。可以根据三个有序点唯一确定一条弧线。首先,修改.m文件,实现BMKMapViewDelegate的_mapView:viewForOverlay:方法,并在viewDidLoad添加弧线数据对象,核心代码如下:
运行效果如下:
III. 多边形
修改ViewController.h文件,使其实现BMKMapViewDelegate;同时修改ViewController.m文件,实现BMKMapViewDelegate的_mapView:viewForOverlay:函数,并在viewDidLoad添加多边形数据对象。核心代码如下:
运行效果如下:
IV. 圆
与多边形实现的方式类似,首先要修改ViewController.h文件,实现BMKMapViewDelegate协议;然后修改ViewController.m文件,实现BMKMapViewDelegate的_mapView:viewForOverlay:函数,并在viewDidLoad添加圆数据对象。核心代码如下:
运行效果如下:
V. 地形图图层
自V2.1.0开始,新增图片图层,开发者可在地图的指定位置上添加图片。该图片可随地图的平移、缩放、旋转等操作做相应的变换。图片图层是一种特殊的Overlay, 它位于底图和底图标注层之间(即图片图层不会遮挡地图标注信息), 此外,图片图层的添加顺序不会影响其他图层(例如:POI搜索图层、我的位置图层等)的叠加关系。
图片图层对象初始化的方法有两种:(1)根据指定经纬度坐标生成 (2)根据指定区域生成。下面举例分步说明添加图片图层的步骤:
运行效果如下图:
VI. 热力图功能
热力图是用不同颜色的区块叠加在地图上描述人群分布、密度和变化趋势的一个产品,百度地图SDK将绘制热力图的能力为广大开发者开放,帮助开发者利用自有数据,构建属于自己的热力图,提供丰富的展示效果。
注意:此处的“热力图功能”不同于“百度城市热力图”。百度城市热力图通过简单的接口调用,开发者可展示百度数据的热力图层。而此处的热力图功能,需要开发者传入自己的位置数据,然后SDK会根据热力图绘制规则为开发者做本地的热力图渲染绘制。
利用热力图功能构建自有数据热力图的方式如下:
运行结果如下:
VII. 自定义覆盖物
从v2.0.0开始,地图渲染采用OpenGL方式实现,因此覆盖物基类BMKOverlayView新增glRender接口,以及绘制基本线renderLinesWithPoints、面renderRegionWithPoints的接口来实现对覆盖物的OpenGL渲染。绘制自定义overlay时,继承BMKOverlayView的子类需实现glRender接口,在glRender中通过调用renderLinesWithPoints、renderRegionWithPoints来组合自己想要实现的图形。
CustomOverlayView继承BMKOverlayPathView,在CustomOverlayView中实现glRender。核心代码如下所示:
从2.0.0开始,地图渲染采用OpenGL方式实现,因此覆盖物基类BMKOverlayView新增glRender接口,以及绘制基本线renderLinesWithPoints、面renderRegionWithPoints的接口来实现对覆盖物的OpenGL渲染。绘制自定义overlay时,继承BMKOverlayView的子类需实现glRender接口,在glRender中通过调用renderLinesWithPoints、renderRegionWithPoints来组合自己想要实现的图形。
CustomOverlayView继承BMKOverlayPathView,在CustomOverlayView中实现glRender。核心代码如下所示:
-(void)glRender{
//自定义overlay绘制
CustomOverlay *customOverlay = [self customOverlay];
if(customOverlay.pointCount>=3) {
[self renderRegionWithPoints:
customOverlay.pointspointCount:
customOverlay.pointCountfillColor:self.fillColorusingTriangleFan:YES];
//绘制多边形
}else{
[self renderLinesWithPoints:
customOverlay.pointspointCount:
customOverlay.pointCountstrokeColor:
self.strokeColorlineWidth:
self.lineWidthlooped:NO];
//绘制线
}
}
如果不实现glRender,则需实现drawMapRect默认使用系统GDI绘制,GDI绘制方式在overlayView尺寸较大时可能有效率问题,因此建议使用glRender来实现自定义overlay绘制。
针对已添加的自定义覆盖物,您可以通过一下方式进行删除操作:
if(overlay!=nil){
[_mapView removeOverlay:overlay];
}
VIII. OpenGL绘制功能
自v2.6.0起,iOS地图SDK为广大开发者开放了OpenGL绘制功能,开发者可利用OpenGL的绘制来实现更多复杂的覆盖物绘制。
v2.6.0新增BMKMapViewDelegate中新增-mapView:onDrawMapFrame:,地图渲染每一帧画面过程中,以及每次需要重绘地图时(例如添加覆盖物)都会调用此接口。开发者可以在这个接口中进行opengl的绘制。不需要用户自己创建context和buffer,步骤如下(具体代码请参考BaiduMap_IOSSDK_SampleOpenGL绘制功能 部分):
1、转换坐标(坐标系原点为地图中心点);
2、根据地图的状态,设置旋转和缩放比例;
3、绘制;
IX. 瓦片图层
iOS地图SDK自v2.9.0起,新增瓦片图层(tileOverlay), 该图层支持开发者添加自有瓦片数据,包括本地加载和在线下载两种方式。
该图层可随地图的平移、缩放、旋转等操作做相应的变换,它仅位于底图之上(即瓦片图层将会遮挡底图,不遮挡其他图层),瓦片图层的添加顺序不会影响其他图层(例如:POI搜索图层、我的位置图层等)的叠加关系,适用于开发者拥有某一区域的地图,并希望使用此区域地图覆盖相应位置的百度地图。
一、瓦片划分规则:
百度地图SDK会根据不同的比例尺将地图划分成若干个瓦片,并且以中心点经纬度(0,0)开始计算瓦片,当地图显示缩放级别增大时,每一个瓦片被划分成4 个瓦片。如:
地图级别为0时,只有1张瓦片
地图级别为1时,会分成 1 * 4 = 4 张瓦片
依次类推,
地图级别为n时,总共划分的瓦片为:4的n次方
为了保证瓦片的显示效果,第n级的瓦片显示的地图level范围为[n - 0.5, n + 0.5)
二、瓦片图层分为本地加载和在线下载两种绘制方式。
1. 本地加载,将图片打包于应用内,适用于图片较小且不需要频繁变更,通过继承BMKSyncTileLayer实现,具体请参考demo,效果如下:
2. 在线下载,将图片存放于开发者提供的服务中,提供给SDK一个URL模板,适用于图片需要随时变更,下面举例说明添加在线瓦片图层的步骤:
I. 根据URL模版(即指向相关图层图片的URL)创建BMKURLTileLayer对象。
BMKURLTileLayer *urlTileLayer = [[BMKURLTileLayer alloc] initWithURLTemplate:@"http://api0.map.bdimg.com/customimage/tile?&x={x}&y={y}&z={z}&udt=20150601&customid=light"];
II. 设置BMKURLTileLayer的可见最大/最小Zoom值。
urlTileLayer.maxZoom=18;
urlTileLayer.minZoom=16;
III. 设定BMKURLTileLayer的可渲染区域。
urlTileLayer.visibleMapRect = BMKMapRectMake(32994258,35853667,3122,5541);
IV. 将BMKURLTileLayer对象添加到BMKMapView中
[_mapView addOverlay:urlTileLayer];
V. 实现BMKMapViewDelegate回调,核心代码如下
- (BMKOverlayView*)mapView:(BMKMapView*)mapView viewForOverlay:(id)overlay{
if([overlay isKindOfClass:[BMKTileLayerclass]]){
BMKTileLayerView *view = [[BMKTileLayerView alloc] initWithTileLayer:overlay];
return view;
} return nil; }
运行结果如下: