Weex地图组件开发流程及使用(IOS)

Weex地图组件开发流程及使用(IOS

一、组件开发前准备

   首先,新建高德地图开发者账号,获取地图的key

   进入自己的高德开发账号,点击创建新应用’ 

 

创建应用完成点击右上角的添加新key

 

下图证书的位置

 

 Info.list中添加相应的权限

 

使用 CocoaPods 安装 SDK

1、在您当前工程文件(.xcodeproj)所在文件夹下创建一个名为 Podfile 的文件。 Podfile 内容如下(以 3D 地图 SDK 为例,其他 SDK 的 Pod 库名称参考下表):

platform :ios, '7.0' #手机的系统

target 'YourProjectTarget' do #工程名字

     pod 'AMap3DMap'  #3D地图 SDK

end

 

2、mac的终端执行下面命令进行配置并安装 SDK。

pod repo update  #用于保证本地地图相关SDK为最新版

pod install    #用于集成SDK到项目中

二、组件开发

1、 新建MyMapComponent.h继承WXComponent

   #import <UIKit/UIKit.h>

   #import <MAMapKit/MAMapKit.h>

   #import <WeexSDK/WeexSDK.h>

   @interface MyMapComponent : WXComponen

   @end

2、 MyMapComponent.m实现文件中实现MAMapViewDelegate代理

   #import "MyMapComponent.h"

   #import <MAMapKit/MAMapKit.h>

   @interface MyMapComponent()<MAMapViewDelegate>

   @property (nonatomic,assign)Boolean mapLoaded;

   @property (nonatomic,assign)Boolean showsUserLocation;

   @property (nonatomic,assign)NSInteger mapType;

   @property (nonatomic, strong) MAMapView *mapView;

   @property (nonatomic, strong) MAGroundOverlay *groundOverlay;

   //-(void)saveImage;

   //-(void)addAnnotation;

   //-(void)addCircleWithLat:(float)lattude Lng:(float)longitude    radius:(int)r;

   //-(void)addOverlay;

   //-(void)alert;

   @end 

   @implementation MyMapComponent

3、 重写MyMapComponent.mloadView方法加载地图视图并设置自身为代理对象

   //加载视图对象

   -(UIView*)loadView{

       _mapView=[[MAMapView alloc] initWithFrame:CGRectMake(0, 0, 400,   500)];

     _mapView.tag=101;

    //设置代理对象为自身

    self.mapView.delegate = self;

    return _mapView;

}

4、 MyMapComponent.m的初始化函数viewDidLoad中做一些准备工作

   //生命周期函数,加载map的过程中可以做一些设置

   -(void)viewDidLoad{

       MAMapView* mapView=[self.view viewWithTag:101];

       mapView.showsUserLocation=_showsUserLocation;

       NSString *stringInt = [NSString stringWithFormat:@"%d",_mapType];

       NSLog([@"mapType====================="   stringByAppendingString:stringInt]);

       if(_mapType==1){

           //标准地图

           [mapView setMapType:MAMapTypeStandard];

       }else if(_mapType==2){

           //卫星地图

           [mapView setMapType:MAMapTypeSatellite];

       }else if(_mapType==3){

           //夜景模式地图

           [mapView setMapType:MAMapTypeStandardNight];

       }else{

           //导航模式地图

           [mapView setMapType:MAMapTypeNavi];

       }

   }

5、 MyMapComponent.m中实现属性绑定实现

   //属性绑定

   - (instancetype)initWithRef:(NSString *)ref type:(NSString *)type  styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes  events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance  {

       if(self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) {

        if (attributes[@"showsUserLocation"]) {//是否显示当前位置标识

            _showsUserLocation = [WXConvert BOOL: attributes[@"showsUserLocation"]];

        }

        if(attributes[@"mapType"]){

             //地图类型

            _mapType=[WXConvert NSInteger:attributes[@"mapType"]];

        }

    }

    return self;

· }

//动态监听属性变化并更新属性

-(void)updateAttributes:(NSDictionary *)attributes{

    MAMapView* mapView=[self.view viewWithTag:101];

    if (attributes[@"showsUserLocation"]) {

        _showsUserLocation = [WXConvert BOOL: attributes[@"showsUserLocation"]];

        mapView.showsUserLocation=_showsUserLocation;

    }

    if(attributes[@"mapType"]){

        _mapType=[WXConvert NSInteger:attributes[@"mapType"]];

        if(_mapType==1){

            //标准地图

            [mapView setMapType:MAMapTypeStandard];

        }else if(_mapType==2){

            //卫星地图

            [mapView setMapType:MAMapTypeSatellite];

        }else if(_mapType==3){

            //夜景模式地图

            [mapView setMapType:MAMapTypeStandardNight];

        }else{

            //导航模式地图

            [mapView setMapType:MAMapTypeNavi];

        }

    }

6、 MyMapComponent.m中暴露方法给JS

 

   @implementation MyMapComponent

   // 暴露该方法给js

   WX_EXPORT_METHOD(@selector(alert:));

   WX_EXPORT_METHOD(@selector(saveImage));

   WX_EXPORT_METHOD(@selector(addAnnotation));

   WX_EXPORT_METHOD(@selector(addCircleWithLat:Lng:radius:));

   WX_EXPORT_METHOD(@selector(addOverlay));

   WX_EXPORT_METHOD(@selector(addAnnotation));

 

7、 添加适当时机可以触发的事件

·  

   //添加事件

   -(void)addEvent:(NSString *)eventName{

       if ([eventName isEqualToString:@"mapLoaded"]) {

           _mapLoaded = YES;

       }

·    }

· 接下来我们需要在我们想要触发该事件的时候发送事件通知来触发事件。

   //在适宜的时间发事件通知,出发时间,这里是在component布局加载完成后触发

   -(void)layoutDidFinish{

       if (_mapLoaded) {

           [self fireEvent:@"mapLoaded"       params:@{@"customKey":@"customValue"} domChanges:nil];

       }

  }

8、 扩展功能实现

1) 绘制点标记

//绘制点标记

-(void)addAnnotation{

    //添加标注数据对象。

    MAMapView* mapView=[self.view viewWithTag:101];

    MAPointAnnotation *pointAnnotation = [[MAPointAnnotation alloc] init];

    pointAnnotation.coordinate = CLLocationCoordinate2DMake(39.989631, 116.481018);

    pointAnnotation.title = @"方恒国际";

    pointAnnotation.subtitle = @"阜通东大街6";

    

    [mapView addAnnotation:pointAnnotation];

}

//实现 <MAMapViewDelegate> 协议中的 mapView:viewForAnnotation:回调函数,设置标注样式

-(MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id<MAAnnotation>)annotation{

    if ([annotation isKindOfClass:[MAPointAnnotation class]])

    {

        static NSString *pointReuseIndentifier = @"pointReuseIndentifier";

        MAPinAnnotationView*annotationView = (MAPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndentifier];

        if (annotationView == nil)

        {

            annotationView = [[MAPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndentifier];

        }

        annotationView.canShowCallout= YES;       //设置气泡可以弹出,默认为NO

        annotationView.animatesDrop = YES;        //设置标注动画显示,默认为NO

        annotationView.draggable = YES;        //设置标注可以拖动,默认为NO

        annotationView.pinColor = MAPinAnnotationColorPurple;

        return annotationView;

    }

    return nil;

}

2) 绘制折线

//绘制折线

-(void)addOverlay{

    MAMapView* mapView=[self.view viewWithTag:101];

    CLLocationCoordinate2D commonPolylineCoords[2];

    commonPolylineCoords[0].latitude = 39.989631;

    commonPolylineCoords[0].longitude = 116.481018;

 

    

    commonPolylineCoords[1].latitude = 39.802136;

    commonPolylineCoords[1].longitude = 116.44095;

    

    //构造折线对象

    MAPolyline *commonPolyline = [MAPolyline polylineWithCoordinates:commonPolylineCoords count:2];

    

    //在地图上添加折线对象

    [mapView addOverlay: commonPolyline];

   

· }

//实现 <MAMapViewDelegate> 协议中的 mapView:rendererForOverlay: 回调函数,设置折线的样式

- (MAOverlayRenderer *)mapView:(MAMapView *)mapView rendererForOverlay:(id <MAOverlay>)overlay

{

    if ([overlay isKindOfClass:[MAPolyline class]])

    {

        MAPolylineRenderer *polylineRenderer = [[MAPolylineRenderer alloc] initWithPolyline:overlay];

        

        polylineRenderer.lineWidth    = 8.f;

        polylineRenderer.strokeColor  = [UIColor colorWithRed:0 green:1 blue:0 alpha:0.6];

        polylineRenderer.lineJoinType = kMALineJoinRound;

        polylineRenderer.lineCapType  = kMALineCapRound;

        

        return polylineRenderer;

    }

    return nil;

}

3) 绘制圆形区域

//绘制圆形区域,参数,latitude:经度、longitude:纬度、radius:半径

-(void)addCircleWithLat:(float)lattude Lng:(float)longitude radius:(int)r{

    MAMapView* mapView=[self.view viewWithTag:101];

    MACircle *circle = [MACircle circleWithCenterCoordinate:CLLocationCoordinate2DMake(lattude, longitude) radius:r];

    //在地图上添加圆

    [mapView addOverlay: circle];

}

4) 截图

 //地图截屏

    -(int)saveImage{

    MAMapView* mapView=[self.view viewWithTag:101];

    __block UIImage *screenshotImage = nil;

    __block NSInteger resState = 0;

    //    CGRect* inRect=CGRectMake(0, 0, 400, 500);

    [mapView takeSnapshotInRect:mapView.frame      withCompletionBlock:^(UIImage *resultImage, NSInteger state) {

        screenshotImage = resultImage;

        NSArray  *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,  NSUserDomainMask, YES);

        NSString *filePath=[[paths  objectAtIndex:0]stringsByAppendingPaths:[NSString  stringWithFormat:@"shortImage.png"]];

        BOOL result =[UIImagePNGRepresentation(screenshotImage)writeToFile:filePath atomically:YES]; // 保存成功会返回YES

        resState = state; // state表示地图此时是否完整,0-不完整,1-完整

      

    }];

      return resState;

}

 
 

三、组件主要功能及使用方法

1)MyMapComponent使用

    H5中使用组件:

   <map class="maps" ref="map" mapType="1" showsUserLocation="true"   @mapLoaded="alert"></map>

a、 属性

属性可以直接写在标签内使用,组件中的mapType我们分别用1234四个数字代表不同的地图模式,包括卫星地图、标准地图、交通线路地图等。

b、 绘制点标记

要绘制点标记我们可以调用原生暴露给js的对应的方法来实现。

       <map class="maps" ref="map" mapType="1" showsUserLocation="true"    @mapLoaded="alert"></map>

       js中写上如下代码:

       this.$refs.map.addAnnotation();

 

 

c、 绘制折线

要绘制折线我们可以调用原生暴露给js的对应的方法来实现。

       <map class="maps" ref="map" mapType="1" showsUserLocation="true"    @mapLoaded="alert"></map>

       js中写上如下代码:

       this.$refs.map.addOverlay();

 

 

 

d、 绘制圆形区域

要绘制圆形区域我们可以调用原生暴露给js的对应的方法来实现。

       <map class="maps" ref="map" mapType="1" showsUserLocation="true"    @mapLoaded="alert"></map>

       js中写上如下代码:

       this.$refs.map.addCircle(lat,lng,radius);

 

e、 截图

要实现截图功能我们可以调用原生暴露给js的对应的方法来实现。

       <map class="maps" ref="map" mapType="1" showsUserLocation="true"    @mapLoaded="alert"></map>

       js中写上如下代码:

       this.$refs.map.addImage();

即可将地图截图保存到原生代码中指定的路径中。

 

除此之外还有很多地图相关的操作,如热力图、纹理线、位置分享、导航分享等。在高德地图开放平台均有相关开发文档,可在原生代码中实现这些操作,将接口暴露给JS端即可。因此并没有一一实现。

注意:有一点需要特别注意的地方,不能再vue界面的created()生命周期函数中直接调用一些绘制操作,因为created()是界面创建完成的钩子函数,并不是加载完成,此时界面中的地图控件这时还没有完全加载完成,无法实现在地图控件上的相关绘制操作。

因此,我们如果需要在初始化界面时就在map控件上绘制相关图形,需要在onPageInit(自定义的一个界面加载完成的)的回调方法中执行这些绘制操作,代码如下:

created(){
    var self=this;
    var globalEvent = weex.requireModule('globalEvent');
    globalEvent.addEventListener("onPageInit", function (e) {
        //绘制点标记
        
self.$refs.map.addAnnotation();
    });
}