// // MAMapView+Flutter.m // amap_map // // Created by lly on 2020/10/30. // Updated by kuloud on 2024/07/29. // #import "MAMapView+Flutter.h" #import "AMapCameraPosition.h" #import "AMapConvertUtil.h" #import "AMapJsonUtils.h" #import @implementation MAMapView (Flutter) - (void)setCameraPosition:(AMapCameraPosition *)cameraPosition animated:(BOOL)animated duration:(CFTimeInterval)duration { if (cameraPosition == nil) { return; } MAMapStatus *mapStatus = [MAMapStatus statusWithCenterCoordinate:cameraPosition.target zoomLevel:cameraPosition.zoom rotationDegree:cameraPosition.bearing cameraDegree:cameraPosition.tilt screenAnchor:self.screenAnchor]; [self setMapStatus:mapStatus animated:animated duration:duration]; } - (AMapCameraPosition *)getCurrentCameraPosition { AMapCameraPosition *position = [[AMapCameraPosition alloc] init]; position.target = self.centerCoordinate; position.zoom = self.zoomLevel; position.bearing = self.rotationDegree; position.tilt = self.cameraDegree; return position; } - (void)setCameraUpdateDict:(NSDictionary *)updateDict { if (updateDict == nil || updateDict.count == 0) { return; } BOOL animated; if ([updateDict[@"animated"] isKindOfClass:[NSNull class]]) { animated = NO; } else { animated = [updateDict[@"animated"] boolValue]; } double duration; if ([updateDict[@"duration"] isKindOfClass:[NSNull class]]) { duration = 0; } else { duration = [updateDict[@"duration"] doubleValue]/1000.0; } NSArray *cameraUpdate = updateDict[@"cameraUpdate"]; //后面的操作时数组,第一个是操作符,后面才是真的参数; NSAssert(cameraUpdate.count >= 1, @"cameraUpdate 参数错误"); NSString *operation = cameraUpdate.firstObject; if ([operation isEqualToString:@"newCameraPosition"] && cameraUpdate.count == 2) {//按照cameraPositon移动 AMapCameraPosition *newCameraPosition = [AMapJsonUtils modelFromDict:cameraUpdate[1] modelClass:[AMapCameraPosition class]]; [self setCameraPosition:newCameraPosition animated:animated duration:duration]; } else if ([operation isEqualToString:@"newLatLng"] && cameraUpdate.count == 2) {//只移动屏幕中心点 CLLocationCoordinate2D position = [AMapConvertUtil coordinateFromArray:cameraUpdate[1]]; MAMapStatus *currentStatus = [self getMapStatus]; currentStatus.centerCoordinate = position; [self setMapStatus:currentStatus animated:animated duration:duration]; } else if ([operation isEqualToString:@"newLatLngBounds"] && cameraUpdate.count == 3) {//设置视图的显示范围和边界 // TODO: 这里没有使用参数duration MAMapRect boundRect = [AMapConvertUtil mapRectFromArray:cameraUpdate[1]]; double padding = [cameraUpdate[2] doubleValue]; UIEdgeInsets inset = UIEdgeInsetsMake(padding, padding, padding, padding); [self setVisibleMapRect:boundRect edgePadding:inset animated:animated]; } else if ([operation isEqualToString:@"newLatLngZoom"] && cameraUpdate.count == 3) {//设置地图中心点和zoomLevel CLLocationCoordinate2D position = [AMapConvertUtil coordinateFromArray:cameraUpdate[1]]; CGFloat zoomLevel = [cameraUpdate[2] floatValue]; MAMapStatus *currentStatus = [self getMapStatus]; currentStatus.centerCoordinate = position; currentStatus.zoomLevel = zoomLevel; [self setMapStatus:currentStatus animated:animated duration:duration]; } else if ([operation isEqualToString:@"scrollBy"] && cameraUpdate.count == 3) {//按照屏幕像素点移动 CGPoint pixelPointOffset = CGPointMake([cameraUpdate[1] doubleValue], [cameraUpdate[2] doubleValue]); CGPoint updateCenter = CGPointMake(self.center.x + pixelPointOffset.x/[UIScreen mainScreen].scale, self.center.y + pixelPointOffset.y/[UIScreen mainScreen].scale); CLLocationCoordinate2D centerCoord = [self convertPoint:updateCenter toCoordinateFromView:self]; MAMapStatus *currentStatus = [self getMapStatus]; currentStatus.centerCoordinate = centerCoord; [self setMapStatus:currentStatus animated:animated duration:duration]; } else if ([operation isEqualToString:@"zoomIn"]) { MAMapStatus *currentStatus = [self getMapStatus]; currentStatus.zoomLevel = currentStatus.zoomLevel + 1; [self setMapStatus:currentStatus animated:animated duration:duration]; } else if ([operation isEqualToString:@"zoomOut"]) { MAMapStatus *currentStatus = [self getMapStatus]; currentStatus.zoomLevel = currentStatus.zoomLevel - 1; [self setMapStatus:currentStatus animated:animated duration:duration]; } else if ([operation isEqualToString:@"zoomTo"] && cameraUpdate.count == 2) { MAMapStatus *currentStatus = [self getMapStatus]; currentStatus.zoomLevel = [cameraUpdate[1] doubleValue]; [self setMapStatus:currentStatus animated:animated duration:duration]; } } - (void)updateMapViewOption:(NSDictionary *)dict withRegistrar:(NSObject*)registrar { if ([dict isKindOfClass:[NSDictionary class]] == NO || dict == nil || dict.count == 0) { return; } //地图类型 NSNumber *mapType = dict[@"mapType"]; if (mapType) { self.mapType = mapType.integerValue; } NSDictionary *customStyleOptions = dict[@"customStyleOptions"]; if (customStyleOptions) { BOOL customMapStyleEnabled = [customStyleOptions[@"enabled"] boolValue]; self.customMapStyleEnabled = customMapStyleEnabled; if (customMapStyleEnabled) { MAMapCustomStyleOptions *styleOption = [[MAMapCustomStyleOptions alloc] init]; styleOption.styleData = ((FlutterStandardTypedData*)customStyleOptions[@"styleData"]).data; styleOption.styleExtraData = ((FlutterStandardTypedData*)customStyleOptions[@"styleExtraData"]).data; [self setCustomMapStyleOptions:styleOption]; } } NSDictionary *locationStyleDict = dict[@"myLocationStyle"]; if (locationStyleDict) { BOOL showUserLocation = [locationStyleDict[@"enabled"] boolValue]; self.showsUserLocation = showUserLocation; if (showUserLocation) { self.userTrackingMode = MAUserTrackingModeNone;//强制设置为非追随模式,追随模式后续在demo中,使用自定义定位样式实现 if (locationStyleDict[@"circleFillColor"] != nil || locationStyleDict[@"circleStrokeColor"] != nil || locationStyleDict[@"circleStrokeWidth"] != nil || locationStyleDict[@"icon"] != nil) {//自定义样式有不为空的属性时,才启动自定义的样式设置 MAUserLocationRepresentation *locationStyle = [[MAUserLocationRepresentation alloc] init]; if (locationStyleDict[@"circleFillColor"]) { locationStyle.fillColor = [AMapConvertUtil colorFromNumber:locationStyleDict[@"circleFillColor"]]; } if (locationStyleDict[@"circleStrokeColor"]) { locationStyle.strokeColor = [AMapConvertUtil colorFromNumber:locationStyleDict[@"circleStrokeColor"]]; } if (locationStyleDict[@"circleStrokeWidth"]) { locationStyle.lineWidth = [locationStyleDict[@"circleStrokeWidth"] doubleValue]; } if (locationStyleDict[@"icon"]) { locationStyle.image = [AMapConvertUtil imageFromRegistrar:registrar iconData:locationStyleDict[@"icon"]]; } [self updateUserLocationRepresentation:locationStyle]; } } } ///地图锚点 NSArray *screenAnchor = dict[@"screenAnchor"]; if (screenAnchor) { CGPoint anchorPoint = [AMapConvertUtil pointFromArray:screenAnchor]; self.screenAnchor = anchorPoint; } //缩放级别范围 NSArray* zoomData = dict[@"minMaxZoomPreference"]; if (zoomData) { CGFloat minZoom = (zoomData[0] == [NSNull null]) ? 3.0 : [zoomData[0] doubleValue]; self.minZoomLevel = minZoom; CGFloat maxZoom = (zoomData[1] == [NSNull null]) ? 20.0 : [zoomData[1] doubleValue]; self.maxZoomLevel = maxZoom; } NSArray *limitBounds = dict[@"limitBounds"]; if (limitBounds) { MAMapRect limitRect = [AMapConvertUtil mapRectFromArray:limitBounds]; self.limitMapRect = limitRect; } //显示路况开关 NSNumber *showTraffic = dict[@"trafficEnabled"]; if (showTraffic) { self.showTraffic = [showTraffic boolValue]; } // 地图poi是否允许点击 NSNumber *touchPOIEnable = dict[@"touchPoiEnabled"]; if (touchPOIEnable) { self.touchPOIEnabled = [touchPOIEnable boolValue]; } //是否显示3D建筑物 NSNumber *showBuilding = dict[@"buildingsEnabled"]; if (showBuilding) { self.showsBuildings = [showBuilding boolValue]; } //是否显示底图文字标注 NSNumber *showLable = dict[@"labelsEnabled"]; if (showLable) { self.showsLabels = [showLable boolValue]; } //是否显示指南针 NSNumber *showCompass = dict[@"compassEnabled"]; if (showCompass) { self.showsCompass = [showCompass boolValue]; } //是否显示比例尺 NSNumber *showScale = dict[@"scaleEnabled"]; if (showScale) { self.showsScale = [showScale boolValue]; } //是否支持缩放手势 NSNumber *zoomEnable = dict[@"zoomGesturesEnabled"]; if (zoomEnable) { self.zoomEnabled = [zoomEnable boolValue]; } //是否支持滑动手势 NSNumber *scrollEnable = dict[@"scrollGesturesEnabled"]; if (scrollEnable) { self.scrollEnabled = [scrollEnable boolValue]; } //是否支持旋转手势 NSNumber *rotateEnable = dict[@"rotateGesturesEnabled"]; if (rotateEnable) { self.rotateEnabled = [rotateEnable boolValue]; } //是否支持仰角手势 NSNumber *rotateCameraEnable = dict[@"tiltGesturesEnabled"]; if (rotateCameraEnable) { self.rotateCameraEnabled = [rotateCameraEnable boolValue]; } NSNumber *logoPosition = dict[@"logoPosition"]; NSNumber *logoBottomMargin = dict[@"logoBottomMargin"]; NSNumber *logoLeftMargin = dict[@"logoLeftMargin"]; CGSize mapSize = self.bounds.size; CGSize logoSize = CGSizeMake(110, 40); // 官方文档只一行代码 _mapView.logoCenter = CGPointMake(CGRectGetWidth(self.view.bounds)-55, 450);,猜测logo的大小是110x40 CGPoint logoCenter = CGPointZero; if (logoBottomMargin || logoLeftMargin) { CGFloat bottomMargin = logoBottomMargin ? [logoBottomMargin floatValue] : 0; CGFloat leftMargin = logoLeftMargin ? [logoLeftMargin floatValue] : 0; logoCenter.x = leftMargin + logoSize.width / 2; logoCenter.y = mapSize.height - bottomMargin - logoSize.height / 2; } else if (logoPosition) { NSInteger position = [logoPosition integerValue]; switch (position) { case 0: // LOGO_POSITION_BOTTOM_LEFT logoCenter = CGPointMake(logoSize.width / 2, mapSize.height - logoSize.height / 2); break; case 1: // LOGO_POSITION_BOTTOM_CENTER logoCenter = CGPointMake(mapSize.width / 2, mapSize.height - logoSize.height / 2); break; case 2: // LOGO_POSITION_BOTTOM_RIGHT logoCenter = CGPointMake(mapSize.width - logoSize.width / 2, mapSize.height - logoSize.height / 2); break; default: // 默认为左下角 logoCenter = CGPointMake(logoSize.width / 2, mapSize.height - logoSize.height / 2); break; } } else { logoCenter = CGPointMake(logoSize.width / 2, mapSize.height - logoSize.height / 2); } // 确保logoCenter在mapView.bounds之内 logoCenter.x = MAX(logoSize.width / 2, MIN(logoCenter.x, mapSize.width - logoSize.width / 2)); logoCenter.y = MAX(logoSize.height / 2, MIN(logoCenter.y, mapSize.height - logoSize.height / 2)); // 设置logo的位置 self.logoCenter = logoCenter; } @end