内容简介:前言:随着公司业务中采用weex技术来实现业务的场景越来越多,对于扎根在即时物流的我们来说地图功能至关重要,然而插件市场现存的地图相关的插件长期没人维护,没有降级功能,路径计算等功能不全,android跑不起等等奇葩的坑让开发者苦不堪言,我们对此进行了探索,出于老业务采用高德地图来实现android,iOS,web相关功能的背景,我们处于兼容的考虑选择了高德地图对weex进行地图相关功能进行扩展,借此机会来记录下的这个虐心的过程,希望能帮助到正在使用weex开发的小伙伴们少走些弯路。注:
前言:随着公司业务中采用weex技术来实现业务的场景越来越多,对于扎根在即时物流的我们来说地图功能至关重要,然而插件市场现存的地图相关的插件长期没人维护,没有降级功能,路径计算等功能不全,android跑不起等等奇葩的坑让开发者苦不堪言,我们对此进行了探索,出于老业务采用高德地图来实现android,iOS,web相关功能的背景,我们处于兼容的考虑选择了高德地图对weex进行地图相关功能进行扩展,借此机会来记录下的这个虐心的过程,希望能帮助到正在使用weex开发的小伙伴们少走些弯路。
目录
- 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 iOS高德地图开发流程简单介绍
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高德地图开发流程简单介绍(本文采用elm封装的vue-amap作为试例)
1.前往高德开放平台控制台申请 jsAPI Key 2.可通过CDN同步加载方式或使用require异步方式来加载key
注: 高德地图开发文档 , vue-amap开发文档
2.weex-iOS地图组件扩展方式介绍**
- 2.1 dwd-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 dwd-weex-amap-marker 思路:
1. 新建DMapViewMarkerComponent类继承WXComponent 2.在DMapViewComponent中使用mapview的addAnnotation方法添加DMapViewMarkerComponent组件 3. 在DMapViewComponent重写insertSubview方法来添加子组建覆盖物
部分代码:
- (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) { if ([events containsObject:@"click"]) { _clickEvent = @"click"; } NSArray *offset = attributes[@"offset"]; if ([WXConvert isValidatedArray:offset]) { _offset = CGPointMake([WXConvert CGFloat:offset[0]], [WXConvert CGFloat:offset[1]]);//[WXConvert sizeToWXPixelType:attributes[@"offset"] withInstance:self.weexInstance]; } if (styles[@"zIndex"]) { _zIndex = [styles[@"zIndex"] integerValue]; } _hideCallout = [[attributes map_safeObjectForKey:@"hideCallout"] boolValue]; NSArray *position = [attributes map_safeObjectForKey:@"position"]; if ([WXConvert isValidatedArray:position]) { _location = [attributes map_safeObjectForKey:@"position"]; } _title = [attributes map_safeObjectForKey:@"title"]; _icon = [attributes map_safeObjectForKey:@"icon"]; } return self; } - (void)updateAttributes:(NSDictionary *)attributes { DMapViewComponent *mapComponent = (DMapViewComponent *)self.supercomponent; if (attributes[@"title"]) { _title = attributes[@"title"]; [mapComponent updateTitleMarker:self]; } if ([attributes map_safeObjectForKey:@"icon"]) { _icon = attributes[@"icon"]; [mapComponent updateIconMarker:self]; } NSArray *position = [attributes map_safeObjectForKey:@"position"]; if ([WXConvert isValidatedArray:position]) { _location = position; [mapComponent updateLocationMarker:self]; } }
- 2.3 dwd-weex-amap-info-window 思路:
1. 新建DMapInfoWindowComponent类继承WXComponent 2.在DMapViewComponent中使用mapview的addAnnotation方法添加DMapInfoWindowComponent组件 3. 在DMapViewComponent重写insertSubview方法来添加子组建信息窗体
部分代码:
- (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) { if (attributes[@"open"]) { _isOpen = [attributes[@"open"] boolValue]; } } return self; } - (UIView *) loadView { return [[DMapInfoWindow alloc] initWithAnnotation:_annotation reuseIdentifier:_identifier]; } - (void)insertSubview:(WXComponent *)subcomponent atIndex:(NSInteger)index{} - (void)updateAttributes:(NSDictionary *)attributes { [super updateAttributes:attributes]; if (attributes[@"open"]) { _isOpen = [attributes[@"open"] boolValue]; if (_isOpen) { [self _addSubView]; }else { [self _removeViewFromSuperView]; } } } #pragma mark - private method - (void)_addSubView { [self _removeViewFromSuperView]; [(DMapViewComponent *)self.supercomponent addMarker:self]; } - (void)_removeViewFromSuperView { [(DMapViewComponent *)self.supercomponent removeMarker:self]; }
- 2.4 dwd-weex-amap-circle 思路:
1. 新建DMapCircleComponent类继承WXComponent 2.在DMapViewComponent中使用mapview的addOverlay方法添加DMapCircleComponent组件 3. 在DMapViewComponent重写insertSubview方法来添加子组建圆
部分代码:
- (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 *centerArray = [attributes map_safeObjectForKey:@"center"]; if ([WXConvert isValidatedArray:centerArray]) { _center = centerArray; } _radius = [[attributes map_safeObjectForKey:@"radius"] doubleValue]; } return self; } - (void)updateAttributes:(NSDictionary *)attributes { NSArray *centerArray = [attributes map_safeObjectForKey:@"center"]; DMapViewComponent *parentComponent = (DMapViewComponent *)self.supercomponent; if ([WXConvert isValidatedArray:centerArray]) { _center = centerArray; [parentComponent removeOverlay:self]; [parentComponent addOverlay:self]; }else if ([[attributes map_safeObjectForKey:@"radius"] doubleValue] >= 0) { _radius = [[attributes map_safeObjectForKey:@"radius"] doubleValue]; [parentComponent removeOverlay:self]; [parentComponent addOverlay:self]; }else { [super updateAttributes:attributes]; } }
- 2.5 dwd-weex-amap-polygon 思路:
1. 新建DMapPolygonComponent类继承WXComponent 2.在DMapViewComponent中使用mapview的addOverlay方法添加DMapPolygonComponent组件 3. 在DMapViewComponent重写insertSubview方法来添加子组建多边形
部分代码:
- (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) { _fillColor = [attributes map_safeObjectForKey:@"fillColor"]; _fillOpacity = [attributes map_safeObjectForKey:@"fillOpacity"]; } return self; } - (void)updateAttributes:(NSDictionary *)attributes { if ([attributes map_safeObjectForKey:@"fillColor"]) { _fillColor = [attributes map_safeObjectForKey:@"fillColor"]; }else if ([attributes map_safeObjectForKey:@"fillOpacity"]) { _fillOpacity = [attributes map_safeObjectForKey:@"fillOpacity"]; }else { [super updateAttributes:attributes]; } }
- 2.5 dwd-weex-amap-polyline 思路:
1. 新建DMapPolylineComponent类继承WXComponent 2.在DMapViewComponent中使用mapview的addOverlay方法添加DMapPolylineComponent组件 3. 在DMapViewComponent重写insertSubview方法来添加子组建折线
部分代码:
@implementation DMapPolylineComponent - (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 * pathArray = [attributes map_safeObjectForKey:@"path"]; if ([WXConvert isValidatedArray:pathArray]) { _path = pathArray; } _strokeColor = [attributes map_safeObjectForKey:@"strokeColor"]; _strokeWidth = [[attributes map_safeObjectForKey:@"strokeWidth"] doubleValue]; _strokeOpacity = [[attributes map_safeObjectForKey:@"strokeOpacity"] doubleValue]; _strokeStyle = [attributes map_safeObjectForKey:@"strokeStyle"]; } _viewLoaded = NO; return self; } - (void)updateAttributes:(NSDictionary *)attributes { NSArray * pathArray = [attributes map_safeObjectForKey:@"path"]; DMapViewComponent *parentComponent = (DMapViewComponent *)self.supercomponent; if (pathArray) { if ([WXConvert isValidatedArray:pathArray]) { _path = pathArray; } [parentComponent removeOverlay:self]; [parentComponent addOverlay:self]; return; }else if ([attributes map_safeObjectForKey:@"strokeColor"]) { _strokeColor = [attributes map_safeObjectForKey:@"strokeColor"]; }else if ([[attributes map_safeObjectForKey:@"strokeWidth"] doubleValue] >= 0) { _strokeWidth = [[attributes map_safeObjectForKey:@"strokeWidth"] doubleValue]; }else if ([[attributes map_safeObjectForKey:@"strokeOpacity"] doubleValue] >= 0) { _strokeOpacity = [[attributes map_safeObjectForKey:@"strokeOpacity"] doubleValue]; }else if ([attributes map_safeObjectForKey:@"strokeStyle"]) { _strokeStyle = [attributes map_safeObjectForKey:@"strokeStyle"]; } [parentComponent updateOverlayAttributes:self]; } @end
3.weex-android地图组件扩展方式介绍**
- 3.1 dwd-weex-amap 思路:
1. 新建DMapViewComponent类继承WXVContainer实现LocationSource 2.使用initComponentHostView(context)初始化 3.在DMapViewComponent实现文件中实现初始化map对象initMap,设置map的key 4.@WXComponentProp注解实现属性绑定 5.通过fireEvent添加适当时机可以触发的事件 6.设置mapview的setInfoWindowAdapter,addPolyline,addPolygon,addCircle,addMarker等方式来实现覆盖物,,线,圆等等
部分代码:
@Override protected FrameLayout initComponentHostView(@NonNull Context context) { mapContainer = new FrameLayout(context) { @Override public boolean onInterceptTouchEvent(MotionEvent ev) { // 解决与Scroller的滑动冲突 if (ev.getAction() == MotionEvent.ACTION_UP) { requestDisallowInterceptTouchEvent(false); } else { requestDisallowInterceptTouchEvent(true); } return false; } }; mapContainer.setBackgroundColor(fakeBackgroundColor); if (context instanceof Activity) { mActivity = (Activity) context; } return mapContainer; } @Override protected void setHostLayoutParams(FrameLayout host, int width, int height, int left, int right, int top, int bottom) { super.setHostLayoutParams(host, width, height, left, right, top, bottom); if (!isMapLoaded.get() && !isInited.get()) { isInited.set(true); mapContainer.postDelayed(new Runnable() { @Override public void run() { mMapView = new TextureMapView(getContext()); mapContainer.addView(mMapView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); WXLogUtils.e(TAG, "Create MapView " + mMapView.toString()); initMap(); } }, 0); } } private void initMap() { mMapView.onCreate(null); isMapLoaded.set(false); if (mAMap == null) { mAMap = mMapView.getMap(); mAMap.setInfoWindowAdapter(new InfoWindowAdapter(this)); mAMap.setOnMapLoadedListener(new AMap.OnMapLoadedListener() { @Override public void onMapLoaded() { WXLogUtils.e(TAG, "Map loaded"); isMapLoaded.set(true); mZoomLevel = mAMap.getCameraPosition().zoom; mMapView.postDelayed(new Runnable() { @Override public void run() { execPaddingTasks(); } }, 16); } }); // 绑定 Marker 被点击事件 mAMap.setOnMarkerClickListener(new AMap.OnMarkerClickListener() { // marker 对象被点击时回调的接口 // 返回 true 则表示接口已响应事件,否则返回false @Override public boolean onMarkerClick(Marker marker) { if (marker != null) { for (int i = 0; i < getChildCount(); i++) { if (getChild(i) instanceof DMapMarkerComponent) { DMapMarkerComponent child = (DMapMarkerComponent) getChild(i); if (child.getMarker() != null && child.getMarker().getId() == marker.getId()) { child.onClick(); } } } } return false; } }); mAMap.setOnCameraChangeListener(new AMap.OnCameraChangeListener() { private boolean mZoomChanged; @Override public void onCameraChange(CameraPosition cameraPosition) { mZoomChanged = mZoomLevel != cameraPosition.zoom; mZoomLevel = cameraPosition.zoom; } @Override public void onCameraChangeFinish(CameraPosition cameraPosition) { if (mZoomChanged) { float scale = mAMap.getScalePerPixel(); float scaleInWeex = scale / WXViewUtils.getWeexPxByReal(scale); VisibleRegion visibleRegion = mAMap.getProjection().getVisibleRegion(); WXLogUtils.d(TAG, "Visible region: " + visibleRegion.toString()); Map<String, Object> region = new HashMap<>(); region.put("northeast", convertLatLng(visibleRegion.latLngBounds.northeast)); region.put("southwest", convertLatLng(visibleRegion.latLngBounds.southwest)); Map<String, Object> data = new HashMap<>(); data.put("targetCoordinate", cameraPosition.target.toString()); data.put("zoom", cameraPosition.zoom); data.put("tilt", cameraPosition.tilt); data.put("bearing", cameraPosition.bearing); data.put("isAbroad", cameraPosition.isAbroad); data.put("scalePerPixel", scaleInWeex); data.put("visibleRegion", region); getInstance().fireEvent(getRef(), WeexConstant.EVENT.ZOOM_CHANGE, data); } } }); mAMap.setOnMapTouchListener(new AMap.OnMapTouchListener() { boolean dragged = false; @Override public void onTouch(MotionEvent motionEvent) { switch (motionEvent.getAction()) { case MotionEvent.ACTION_MOVE: dragged = true; break; case MotionEvent.ACTION_UP: if (dragged) getInstance().fireEvent(getRef(), WeexConstant.EVENT.DRAG_CHANGE); dragged = false; break; } } }); setUpMap(); } } }
- 3.2 dwd-weex-amap-marker 思路:
1. 新建DMapViewMarkerComponent类继承WXComponent 2.在DMapViewComponent中使用mapview的addMarker方法添加DMapViewMarkerComponent组件
部分代码:
private void initMarker(final String title, final String position, final String icon) { postMapOperationTask((WXMapViewComponent) getParent(), new DMapViewComponent.MapOperationTask() { @Override public void execute(TextureMapView mapView) { final MarkerOptions markerOptions = new MarkerOptions(); //设置Marker可拖动 markerOptions.draggable(true); // 将Marker设置为贴地显示,可以双指下拉地图查看效果 markerOptions.setFlat(true); // markerOptions.icon(BitmapDescriptorFactory.fromView(new View(getContext()))); Marker marker = mapView.getMap().addMarker(markerOptions); setMarkerTitle(marker, title); setMarkerPosition(marker, position); setMarkerIcon(marker, icon); setWidget(marker); String ref = (String) getDomObject().getAttrs().get("markerRef"); ((WXMapViewComponent) getParent()).getCachedMarker().put(ref, DMapMarkerComponent.this); } }); }
- 3.3 dwd-weex-amap-info-window 思路:
1. 新建DMapViewMarkerComponent类继承WXComponent 2.在DMapViewComponent中使用mapview的addMarker方法添加DMapViewMarkerComponent组件
部分代码:
private static class InfoWindowAdapter implements AMap.InfoWindowAdapter { private DMapViewComponent mWXMapViewComponent; InfoWindowAdapter(DMapViewComponent wxMapViewComponent) { mWXMapViewComponent = wxMapViewComponent; } @Override public View getInfoWindow(Marker marker) { return render(marker); } @Override public View getInfoContents(Marker marker) { return null; // return render(marker); } private View render(Marker marker) { WXMapInfoWindowComponent wxMapInfoWindowComponent = mWXMapViewComponent.mInfoWindowHashMap.get(marker.getId()); if (wxMapInfoWindowComponent != null) { WXFrameLayout host = wxMapInfoWindowComponent.getHostView(); // WXFrameLayout content = (WXFrameLayout) host.getChildAt(0); host.getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT; host.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT; WXLogUtils.d(TAG, "Info size: " + host.getMeasuredWidth() + ", " + host.getMeasuredHeight()); return host; } else { WXLogUtils.e(TAG, "WXMapInfoWindowComponent with marker id " + marker.getId() + " not found"); } return null; } }
- 3.4 dwd-weex-amap-circle 思路:
1. 新建DMapViewMarkerComponent类继承WXComponent 2.在DMapViewComponent中使用mapview的addCircle方法添加DMapViewMarkerComponent组件
部分代码:
private void initCircle() { postMapOperationTask((DMapViewComponent) getParent(), new DMapViewComponent.MapOperationTask() { @Override public void execute(TextureMapView mapView) { CircleOptions circleOptions = new CircleOptions(); circleOptions.strokeColor(mColor); circleOptions.strokeWidth(mWeight); circleOptions.radius(mRadius); circleOptions.fillColor(mFillColor); setWidget(mapView.getMap().addCircle(circleOptions)); } }); }
- 3.5 dwd-weex-amap-polygon 思路:
1. 新建DMapPolygonComponent类继承WXComponent 2.在DMapViewComponent中使用mapview的addPolygon方法添加DMapPolygonComponent组件
部分代码:
private void initPolygon() { postMapOperationTask((DMapViewComponent) getParent(), new DMapViewComponent.MapOperationTask() { @Override public void execute(TextureMapView mapView) { PolygonOptions polygonOptions = new PolygonOptions(); polygonOptions.addAll(mPosition); polygonOptions.strokeColor(mColor); polygonOptions.strokeWidth(mWidth); setWidget(mapView.getMap().addPolygon(polygonOptions)); } }); }
- 3.6 dwd-weex-amap-polyline 思路:
1. 新建DMapPolyLineComponent类继承WXComponent 2.在DMapViewComponent中使用mapview的addPolyline方法添加DMapPolyLineComponent组件
部分代码:
private void initPolygon() { postMapOperationTask((DMapViewComponent) getParent(), new DMapViewComponent.MapOperationTask() { @Override public void execute(TextureMapView mapView) { PolygonOptions polygonOptions = new PolygonOptions(); polygonOptions.addAll(mPosition); polygonOptions.strokeColor(mColor); polygonOptions.strokeWidth(mWidth); setWidget(mapView.getMap().addPolygon(polygonOptions)); } }); }
4.weex-html5地图组件扩展方式介绍**
- 4.1 dwd-weex-amap 基础示例:
<template> <div class="amap-page-container"> <el-amap ref="map" vid="amapDemo" :amap-manager="amapManager" :center="center" :zoom="zoom" :plugin="plugin" :events="events" class="amap-demo"> </el-amap> <div class="toolbar"> <button @click="getMap()">get map</button> </div> </div> </template> <style> .amap-demo { height: 300px; } </style> <script> // NPM 方式 // import { AMapManager } from 'vue-amap'; // CDN 方式 let amapManager = new VueAMap.AMapManager(); module.exports = { data: function() { return { amapManager, zoom: 12, center: [121.59996, 31.197646], events: { init: (o) => { console.log(o.getCenter()) console.log(this.$refs.map.$$getInstance()) o.getCity(result => { console.log(result) }) }, 'moveend': () => { }, 'zoomchange': () => { }, 'click': (e) => { alert('map clicked'); } }, plugin: ['ToolBar', { pName: 'MapType', defaultType: 0, events: { init(o) { console.log(o); } } }] }; }, methods: { getMap() { // amap vue component console.log(amapManager._componentMap); // gaode map instance console.log(amapManager._map); } } }; </script>
- 4.2 dwd-weex-amap-marker 基础示例:
<template> <div class="amap-page-container"> <el-amap vid="amapDemo" :zoom="zoom" :center="center" class="amap-demo"> <el-amap-marker vid="component-marker" :position="componentMarker.position" :content-render="componentMarker.contentRender" ></el-amap-marker> <el-amap-marker v-for="(marker, index) in markers" :position="marker.position" :events="marker.events" :visible="marker.visible" :draggable="marker.draggable" :vid="index"></el-amap-marker> </el-amap> <div class="toolbar"> <button type="button" name="button" v-on:click="toggleVisible">toggle first marker</button> <button type="button" name="button" v-on:click="changePosition">change position</button> <button type="button" name="button" v-on:click="chnageDraggle">change draggle</button> <button type="button" name="button" v-on:click="addMarker">add marker</button> <button type="button" name="button" v-on:click="removeMarker">remove marker</button> </div> </div> </template> <style> .amap-demo { height: 300px; } </style> <script> const exampleComponents = { props: ['text'], template: `<div>text from parent: {{text}}</div>` } module.exports = { name: 'amap-page', data() { return { count: 1, slotStyle: { padding: '2px 8px', background: '#eee', color: '#333', border: '1px solid #aaa' }, zoom: 14, center: [121.5273285, 31.21515044], markers: [ { position: [121.5273285, 31.21515044], events: { click: () => { alert('click marker'); }, dragend: (e) => { console.log('---event---: dragend') this.markers[0].position = [e.lnglat.lng, e.lnglat.lat]; } }, visible: true, draggable: false, template: '<span>1</span>', } ], renderMarker: { position: [121.5273285, 31.21715058], contentRender: (h, instance) => { // if use jsx you can write in this // return <div style={{background: '#80cbc4', whiteSpace: 'nowrap', border: 'solid #ddd 1px', color: '#f00'}} onClick={() => ...}>marker inner text</div> return h( 'div', { style: {background: '#80cbc4', whiteSpace: 'nowrap', border: 'solid #ddd 1px', color: '#f00'}, on: { click: () => { const position = this.renderMarker.position; this.renderMarker.position = [position[0] + 0.002, position[1] - 0.002]; } } }, ['marker inner text'] ) } }, componentMarker: { position: [121.5273285, 31.21315058], contentRender: (h, instance) => h(exampleComponents,{style: {backgroundColor: '#fff'}, props: {text: 'father is here'}}, ['xxxxxxx']) }, slotMarker: { position: [121.5073285, 31.21715058] } }; }, methods: { onClick() { this.count += 1; }, changePosition() { let position = this.markers[0].position; this.markers[0].position = [position[0] + 0.002, position[1] - 0.002]; }, chnageDraggle() { let draggable = this.markers[0].draggable; this.markers[0].draggable = !draggable; }, toggleVisible() { let visableVar = this.markers[0].visible; this.markers[0].visible = !visableVar; }, addMarker() { let marker = { position: [121.5273285 + (Math.random() - 0.5) * 0.02, 31.21515044 + (Math.random() - 0.5) * 0.02] }; this.markers.push(marker); }, removeMarker() { if (!this.markers.length) return; this.markers.splice(this.markers.length - 1, 1); } } }; </script>
- 4.3 dwd-weex-amap-info-window 基础示例:
<template> <div class="amap-page-container"> <el-amap vid="amap" :zoom="zoom" :center="center" class="amap-demo"> <el-amap-info-window :position="currentWindow.position" :content="currentWindow.content" :visible="currentWindow.visible" :events="currentWindow.events"> </el-amap-info-window> </el-amap> <button @click="switchWindow(0)">Show First Window</button> <button @click="switchWindow(1)">Show Second Window</button> </div> </template> <style> .amap-demo { height: 300px; } </style> <script> module.exports = { data () { return { zoom: 14, center: [121.5273285, 31.21515044], windows: [ { position: [121.5273285, 31.21515044], content: 'Hi! I am here!', visible: true, events: { close() { console.log('close infowindow1'); } } }, { position: [121.5375285, 31.21515044], content: 'Hi! I am here too!', visible: true, events: { close() { console.log('close infowindow2'); } } } ], slotWindow: { position: [121.5163285, 31.21515044] }, currentWindow: { position: [0, 0], content: '', events: {}, visible: false } } }, mounted() { this.currentWindow = this.windows[0]; }, methods: { switchWindow(tab) { this.currentWindow.visible = false; this.$nextTick(() => { this.currentWindow = this.windows[tab]; this.currentWindow.visible = true; }); } } }; </script>
- 4.4 dwd-weex-amap-circle 基础示例:
<template> <div class="amap-page-container"> <el-amap vid="amapDemo" :zoom="zoom" :center="center" class="amap-demo"> <el-amap-circle v-for="circle in circles" :center="circle.center" :radius="circle.radius" :fill-opacity="circle.fillOpacity" :events="circle.events"></el-amap-circle> </el-amap> </div> </template> <style> .amap-page-container { height: 200px; } </style> <script> module.exports = { data () { return { zoom: 15, center: [121.5273285, 31.21515044], circles: [ { center: [121.5273285, 31.21515044], radius: 200, fillOpacity: 0.5, events: { click: () => { alert('click'); } } } ] } } }; </script>
- 4.5 dwd-weex-amap-polygon 基础示例:
<template> <div class="amap-page-container"> <el-amap vid="amapDemo" :zoom="zoom" :center="center" class="amap-demo"> <el-amap-rectangle v-for="retangle in retangles" :events="retangle.events" :center="retangle.center" :bounds="retangle.bounds" :fill-color="retangle.fillColor" :fill-opacity="retangle.fillOpacity"></el-amap-rectangle> </el-amap> </div> </template> <style> .amap-page-container { height: 200px; } </style> <script> module.exports = { data () { return { zoom: 12, center: [121.5273285, 31.21515044], retangles: [ { center: [121.5273285, 31.21515044], bounds: [[121.5273285, 31.21515044], [121.7276285, 31.24545044]], fillOpacity: 0.7, fillColor: '#ffffff', events: { click: () => { alert('click'); } } } ] } } }; </script>
- 4.6 dwd-weex-amap-polyline 基础示例:
<template> <div class="amap-page-container"> <el-amap vid="amap" :zoom="zoom" :center="center" class="amap-demo"> <el-amap-polyline :editable="polyline.editable" :path="polyline.path" :events="polyline.events"></el-amap-polyline> </el-amap> <div class="toolbar"> <button type="button" name="button" v-on:click="changeEditable">change editable</button> </div> </div> </template> <style> .amap-demo { height: 300px; } </style> <script> module.exports = { data() { return { zoom: 12, center: [121.5273285, 31.25515044], polyline: { path: [[121.5389385, 31.21515044], [121.5389385, 31.29615044], [121.5273285, 31.21515044]], events: { click(e) { alert('click polyline'); }, end: (e) => { let newPath = e.target.getPath().map(point => [point.lng, point.lat]); console.log(newPath); } }, editable: false } }; }, methods: { changeEditable() { this.polyline.editable = !this.polyline.editable; } } }; </script>
5.获取地图数据(例如骑行路径规划)**
- 5.1 weex-iOS地图骑行路径规划 基础示例:
- (void)searchRidingRouteFromLat:(int)fromLat fromLng:(int)fromLng toLat:(int)toLat toLng:(int)toLng { AMapRidingRouteSearchRequest *request = [[AMapRidingRouteSearchRequest alloc] init]; request.origin = [AMapGeoPoint locationWithLatitude:INT_2_FLOAT(fromLat) / 1000000 longitude:INT_2_FLOAT(fromLng) / 1000000]; request.destination = [AMapGeoPoint locationWithLatitude:INT_2_FLOAT(toLat) / 1000000 longitude:INT_2_FLOAT(toLng) / 1000000]; //发起路径搜索 [self.aMapSearch AMapRidingRouteSearch:request]; } - (void)onRouteSearchDone:(AMapRouteSearchBaseRequest *)request response:(AMapRouteSearchResponse *)response { if(response.route == nil) { return; } //通过AMapNavigationSearchResponse对象处理搜索结果 AMapRoute *route = response.route; if (route.paths.count > 0) { AMapPath *amapPath = route.paths[0]; NSArray *coordArray = amapPath.steps; NSMutableArray *mArray = [NSMutableArray array]; NSArray *start = @[[NSString stringWithFormat:@"%f", request.origin.longitude], [NSString stringWithFormat:@"%f", request.origin.latitude]]; [mArray insertObject:start atIndex:0]; for (AMapStep *step in coordArray) { NSString *polistring = step.polyline; NSArray *array = [polistring componentsSeparatedByString:@";"]; for (NSString *str in array) { NSArray *loc =[str componentsSeparatedByString:@","]; [mArray addObject:loc]; } } NSArray *end = @[[NSString stringWithFormat:@"%f", request.destination.longitude], [NSString stringWithFormat:@"%f", request.destination.latitude]]; [mArray insertObject:end atIndex:mArray.count]; [[DMessageChannelManager shared] postMessage:@"mapLines" andData:@{@"result": @"success", @"data": @{@"mapLines":mArray}}]; } } - (void)AMapSearchRequest:(id)request didFailWithError:(NSError *)error { NSLog(@"Error: %@", error); } @end
- 5.2 weex-android地图骑行路径规划 基础示例:
private RouteTask.OnRouteCalculateListener calculateListener = new RouteTask.OnRouteCalculateListener() { @Override public void onRouteCalculate(RideRouteResult result, int code) { HashMap<String, Object> res = new HashMap<>(2); if (code == 1000 && result != null) { Map<String, Object> data = new HashMap<>(1); data.put("mapLines", getLatLngList(result.getPaths().get(0), routeTask.getStartPoint(), routeTask.getEndPoint())); res.put("result", "success"); res.put("data", data); } else { res.put("result", "fail"); } String dataJson = new Gson().toJson(res); NotifyDataManager.getInstance().postMessage("mapLines", dataJson); WXLogUtils.d("RideRouteResult Json: " + dataJson); } }; routeTask.addRouteCalculateListener(calculateListener); /** * 通过首尾经纬度计算走路规划路径中所有经纬度 * * @param fromLat * @param fromLng * @param toLat * @param toLng */ @JSMethod public void searchRidingRouteFromLat(float fromLat, float fromLng, float toLat, float toLng) { LocationEntity fromLe = new LocationEntity(); fromLe.lat = fromLat / 1e6; fromLe.lng = fromLng / 1e6; LocationEntity toLe = new LocationEntity(); toLe.lat = toLat / 1e6; toLe.lng = toLng / 1e6; if (routeTask == null) { routeTask = RouteTask.getInstance(mWXSDKInstance.getContext()); routeTask.addRouteCalculateListener(calculateListener); } routeTask.search(fromLe, toLe); }
- 5.3 weex-web地图骑行路径规划 基础示例:
//根据起终点坐标规划骑行路线 let stream = weex.requireModule('stream') stream.fetch({ timeout:20000, method: 'GET', url: 'https://restapi.amap.com/v4/direction/bicycling?key=87453539f02a65cd6585210fa2e64dc9&origin='+fromLng/1000000+','+fromLat/1000000+'&destination='+toLng/1000000+','+toLat/1000000, }, (response) => { if (response.status == 200) { let apiData = JSON.parse(response.data) if(apiData.data){ var polyline= new Array(); polyline[0] = apiData.data.origin.split(","); var polylineList = apiData.data.paths['0'].steps[0].polyline.split(";"); for(var i=0;i<polylineList.length;i++) { var polylinePoint = polylineList[i].split(","); polyline.push(polylinePoint); } polyline.push(apiData.data.destination.split(",")); //字符分割 callback({"result":"success","data": {"mapLines":polyline}}); } } }, () => {})
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
TCP/IP详解 卷3:TCP事务协议、HTTP、NNTP和UNIX域协议
胡谷雨、吴礼发、W.Richard Stevens / 胡谷雨 / 机械工业出版社 / 2000-9 / 35.00元
《CP.IP详解(卷3):CP事务协议.HP.P和UIX域协议》是“TCP/IP详解系列”的延续。主要内容包括:TCP事务协议,即T/TCP,这是对TCP的扩展,使客户-服务器事务更快、更高效和更可靠;TCP/IP应用,主要是HTTP和NNTP;UNIX域协议,这些协议提供了进程之间通信的一种手段。当客户与服务器进程在同一台主机上时,UNIX域协议通常要比TCP/IP快一倍。《CP.IP详解(卷3......一起来看看 《TCP/IP详解 卷3:TCP事务协议、HTTP、NNTP和UNIX域协议》 这本书的介绍吧!