在移动应用开发中,地图是一个很重要的工具,基于地图的定位、导航等特点衍生出了很多著名的移动应用。在Weex开发中,如果要使用定位、导航和坐标计算等常见的地图功能,可以使用weex-amap插件。
weex-amap是高德针对Weex开发的一款地图插件,在Eros开发中,Eros对weex-amap进行二次封装,以便让开发者更集成地图功能。和其他的插件一样,集成此插件需要在原生平台中进行集成。
本文介绍的是如何在iOS中集成weex-amap,以及它的一些核心功能。本文将要介绍的内容如下:
1.高德地图开发准备工作
1.1 iOS高德地图开发流程简单介绍
1.2 android高德地图开发流程简单介绍
1.3 web高德地图开发流程简单介绍
2. weex-iOS地图组件扩展方式介绍
2.1 dwd-weex-amap
2.2 dwd-weex-amap-marker
2.3 dwd-weex-amap-info-window
2.4 dwd-weex-amap-circle
2.5 dwd-weex-amap-polygon
2.5 dwd-weex-amap-polyline
3.weex-android地图组件扩展方式介绍
3.1 dwd-weex-amap
3.2 dwd-weex-amap-marker
3.3 dwd-weex-amap-info-window
3.4 dwd-weex-amap-circle
3.5 dwd-weex-amap-polygon
3.6 dwd-weex-amap-polyline
4.weex-html5地图组件扩展方式介绍
4.1 dwd-weex-amap
4.2 dwd-weex-amap-marker
4.3 dwd-weex-amap-info-window
4.4 dwd-weex-amap-circle
4.5 dwd-weex-amap-polygon
4.6 dwd-weex-amap-polyline
5.获取地图数据(例如骑行路径规划)
5.1 weex-iOS地图骑行路径规划
5.2 weex-android地图骑行路径规划
5.3 weex-web地图骑行路径规划
准备工作
1.1 开发流程简绍
1.使用 CocoaPods 安装AMapSearch,AMap3DMap SDK
2.前往高德开放平台控制台申请 iOS Key
3.配置高德Key至AppDelegate.m文件
1.2 android高德地图开发流程简绍
1.使用 CocoaPods 安装AMapSearch,AMap3DMap SDK
2.前往高德开放平台控制台申请 android Key
3.AndroidManifest.xml的application标签中配置Key
4.AndroidManifest.xml中配置权限
1.3 HTML5高德地图开发流程简绍
1.前往高德开放平台控制台申请 jsAPI Key
2.可通过CDN同步加载方式或使用require异步方式来加载key
weex-iOS地图组件扩展
2.1 weex-amap
地图展示是地图最基本的功能,其常见的效果如下:
如有要在iOS中自定义weex-amap可以从以下几个步骤完成:
1.新建DMapViewComponent类继承WXComponent;
2.在DMapViewComponent实现文件中实现MAMapViewDelegate代理;
3. 重写DMapViewComponent的loadView方法加载地图视图并设置自身为代理对象;
4.在DMapViewComponent的初始化函数viewDidLoad中做一些准备工作;
5.在DMapViewComponent的initWithRef方法中实现属性绑定;
6.通过fireEvent添加适当时机可以触发的事件;
7.重写insertSubview方法来添加子组建包括覆盖物,线,圆等等。
下面是部分的业务实现代码:
@implementation DMapViewComponent ... // 属性绑定 - (instancetype)initWithRef:(NSString *)ref type:(NSString*)type styles:(nullable NSDictionary *)styles attributes:(nullable NSDictionary *)attributes events:(nullable NSArray *)events weexInstance:(WXSDKInstance *)weexInstance { self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]; if (self) { // 中心点 NSArray *center = [attributes map_safeObjectForKey:@"center"]; _zoomLevel = [[attributes map_safeObjectForKey:@"zoom"] floatValue]; // 是否允许显示指南针 _compass = [[attributes map_safeObjectForKey:@"compass"] boolValue]; // sdkKey if ([attributes map_safeObjectForKey:@"sdkKey"]) { [self setAPIKey:[attributes[@"sdkKey"] objectForKey:@"ios"] ? : @""]; } ... } return self; } // 重写DMapViewComponent的loadView方法加载地图视图并设置自身为代理对象 - (UIView *) loadView { UIWindow *window = [UIApplication sharedApplication].keyWindow; CGSize windowSize = window.rootViewController.view.frame.size; self.mapView = [[MAMapView alloc] initWithFrame:CGRectMake(0, 0, windowSize.width, windowSize.height)]; self.mapView.showsUserLocation = _showGeolocation; self.mapView.delegate = self; self.mapView.customMapStyleEnabled = YES; [self.mapView setCustomMapStyleWithWebData:[self getMapData]]; return self.mapView; } // 设置地图样式 - (NSData *)getMapData { NSString *path = [NSString stringWithFormat:@"%@/gaodeMapStyle.data", [NSBundle mainBundle].bundlePath]; NSData *data = [NSData dataWithContentsOfFile:path]; return data; } - (void)viewDidLoad { [super viewDidLoad]; self.mapView.showsScale = _showScale; self.mapView.showsCompass = _compass; [self.mapView setCenterCoordinate:_centerCoordinate]; [self.mapView setZoomLevel:_zoomLevel]; } // 添加覆盖物 - (void)insertSubview:(WXComponent *)subcomponent atIndex:(NSInteger)index { if ([subcomponent isKindOfClass:[DMapRenderer class]]) { DMapRenderer *overlayRenderer = (DMapRenderer *)subcomponent; [self addOverlay:overlayRenderer]; }else if ([subcomponent isKindOfClass:[DMapViewMarkerComponent class]]) { [self addMarker:(DMapViewMarkerComponent *)subcomponent]; } } // 更新属性 - (void)updateAttributes:(NSDictionary *)attributes { ... if (attributes[@"zoom"]) { [self setZoomLevel:[attributes[@"zoom"] floatValue]]; } ... } #pragma mark - component interface - (void)setAPIKey:(NSString *)appKey { [AMapServices sharedServices].apiKey = appKey; } - (void)setZoomLevel:(CGFloat)zoom { [self.mapView setZoomLevel:zoom animated:YES]; } #pragma mark - publish method - (NSDictionary *)getUserLocation { if(self.mapView.userLocation.updating && self.mapView.userLocation.location) { NSArray *coordinate = @[[NSNumber numberWithDouble:self.mapView.userLocation.location.coordinate.longitude],[NSNumber numberWithDouble:self.mapView.userLocation.location.coordinate.latitude]]; NSDictionary *userDic = @{@"result":@"success",@"data":@{@"position":coordinate,@"title":@""}}; return userDic; } return @{@"resuldt":@"false",@"data":@""}; } #pragma mark - mapview delegate /*! @brief 根据anntation生成对应的View */ - (MAAnnotationView*)mapView:(MAMapView *)mapView viewForAnnotation:(id <MAAnnotation>)annotation { if ([annotation isKindOfClass:[MAPointAnnotation class]]) { MAPointAnnotation *pointAnnotation = (MAPointAnnotation *)annotation; if ([pointAnnotation.component isKindOfClass:[WXMapInfoWindowComponent class]]) { return [self _generateCustomInfoWindow:mapView viewForAnnotation:pointAnnotation]; }else { return [self _generateAnnotationView:mapView viewForAnnotation:pointAnnotation]; } } return nil; } /** * @brief 当选中一个annotation views时,调用此接口 * @param mapView 地图View * @param view 选中的annotation views */ - (void)mapView:(MAMapView *)mapView didSelectAnnotationView:(MAAnnotationView *)view { MAPointAnnotation *annotation = view.annotation; for (WXComponent *component in self.subcomponents) { if ([component isKindOfClass:[WXMapViewMarkerComponent class]] && [component.ref isEqualToString:annotation.component.ref]) { WXMapViewMarkerComponent *marker = (WXMapViewMarkerComponent *)component; if (marker.clickEvent) { [marker fireEvent:marker.clickEvent params:[NSDictionary dictionary]]; } } } } /** * @brief 当取消选中一个annotation views时,调用此接口 * @param mapView 地图View * @param view 取消选中的annotation views */ - (void)mapView:(MAMapView *)mapView didDeselectAnnotationView:(MAAnnotationView *)view { } /** * @brief 地图移动结束后调用此接口 * @param mapView 地图view * @param wasUserAction 标识是否是用户动作 */ - (void)mapView:(MAMapView *)mapView mapDidMoveByUser:(BOOL)wasUserAction { if (_isDragend) { [self fireEvent:@"dragend" params:[NSDictionary dictionary]]; } } /**设置地图缩放级别 */ - (void)setMapViewRegion:(NSMutableArray *)poiArray animated:(BOOL)animated { NSMutableArray *arrays = [NSMutableArray array]; for (MAPointAnnotation *anot in self.mapView.annotations) { CLLocationCoordinate2D coordinate = anot.coordinate; NSDictionary *poidic = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:coordinate.latitude * 1000000], @"lat", [NSNumber numberWithInt:coordinate.longitude * 1000000], @"lng", nil]; [arrays addObject:poidic]; } MACoordinateRegion region = [self getCoordinateMapSpan:arrays]; [self.mapView setRegion:region animated:animated]; } /**配置地图region */ - (MACoordinateRegion)getCoordinateMapSpan:(NSMutableArray *)knightArray { MACoordinateRegion region; MACoordinateSpan span; CLLocationDegrees maxLat = -90; CLLocationDegrees maxLon = -180; CLLocationDegrees minLat = 90; CLLocationDegrees minLon = 180; if (knightArray && knightArray.count > 1) { for (int i = 0; i < knightArray.count; i++) { NSDictionary *knightDictionary = [knightArray objectAtIndex:i]; float lat = [[knightDictionary objectForKey:@"lat"] floatValue] / 1000000; float lng = [[knightDictionary objectForKey:@"lng"] floatValue] / 1000000; if(lat > maxLat) maxLat = lat; if(lat < minLat) minLat = lat; if(lng > maxLon) maxLon = lng; if(lng < minLon) minLon = lng; } span.latitudeDelta = (maxLat - minLat) * 2 + 0.005; span.longitudeDelta = (maxLon - minLon) * 2 + 0.005; region.center.latitude = (maxLat + minLat) / 2; region.center.longitude = (maxLon + minLon) / 2; region.span = span; } else { NSDictionary *knightDictionary = [knightArray objectAtIndex:0]; span.latitudeDelta = 0.01; span.longitudeDelta = 0.01; float lat = [[knightDictionary objectForKey:@"lat"] floatValue] / 1000000; float lng = [[knightDictionary objectForKey:@"lng"] floatValue] / 1000000; if (lat !=0 && lng != 0) { region.center.longitude = lng; region.center.latitude = lat; } else { region.center = [[ShopLocateManager shared] getLocationCoordinate]; } region.span = span; } return region; } ... @end
2.2 weex-amap-marker
marker主要用于实现锚点,其效果如下:
要在Weex中自定义锚点,需要遵循以下几步:
新建DMapViewMarkerComponent类继承WXComponent;
在DMapViewComponent中使用mapview的addAnnotation方法添加DMapViewMarkerComponent组件;
在DMapViewComponent重写insertSubview方法来添加子组建覆盖物。
部分实现代码如下: