基于Google maps的定位 marker 路线规划 事件监听、响应等

闽朝
2023-12-01

近期做得一个基于Google maps的定位查找功能,由于国内对Google地图使用极少,所以走了不少弯路。千难万难下总算实现了功能,特地在这儿上传下代码,希望能对有需要的朋友们提供点便利。
下面的代码主要实现了这样几个功能:
1. 根据服务端经纬度定位,放置marker(单个或多个大头针)
2. 拖动地图自后根据视野中地图中心经纬度请求服务器获取该点周围的店铺
3. 点击大头针上的信息窗口之后的规划路线与导航
4. 以及一些效果实现,体验优化

上代码!———-


#import "ShopMapController.h"
@import GoogleMaps;
#import "ShopModel.h"
#import "ShopDetailController.h"
#import <XWKit/XWLocationManager.h>





@interface ShopMapController ()<GMSMapViewDelegate>

@property (strong, nonatomic) IBOutlet UIButton *refreshBtn;
@property (strong, nonatomic) IBOutlet UIButton *myLocationbtn;
@property (strong, nonatomic) IBOutlet UIImageView *centerFlagImage;
@property (strong, nonatomic) NSArray *shopList;//周边店铺列表
@property (nonatomic) CLLocationCoordinate2D coordinate;

@property (strong, nonatomic) IBOutlet NSLayoutConstraint *centertImageConstraints;




@end

@implementation ShopMapController{
    UIButton *_refreshBtn;
    GMSMapView *_mapView;
    BOOL _isUserMove;
    CLLocationCoordinate2D _lastCoord;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    _isUserMove = NO;
    _mapView.settings.zoomGestures = YES;
    if (self.isFromDetail) {
        self.title = [NSString stringWithFormat:@"%@ %@",self.shopName?LS(self.shopName):LS(@"Shop"),LS(@"Address")];
        [self updateMapByShopAddress];
    }else{
        [self getMyLocation];
        [self updateMapViewWhenNoData];
        [self getNearbyShopWith:self.coordinate];
        self.title = LS(@"Shop Nearby");
    }
}
- (void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];

    [self.view removeFromSuperview];
}

//获取附近店铺
- (void)getNearbyShopWith:(CLLocationCoordinate2D)camCoord{
    __weak typeof(self) ws = self;
    [[HttpManager sharedInstance] fetchNearbyShopListWith:camCoord.latitude lon:camCoord.longitude token:@"" CompleteBlock:^(id response, OCResult *result) {
            if (result.success && [response isKindOfClass:[NSArray class]]) {
                self.shopList = (NSArray *)response;

                if (self.shopList && self.shopList.count > 0) {
                    [_mapView clear];
                    [ws updateNearbyShopForMaps];
                }else{
                    [ws xw_showMessage:LS(@"No shop around")];
                }
            } else {
                [ws xw_showError:result.message];
            }
    }];



}
#pragma mark - 展示 ---------------------
//创建GMSMaps
- (void)updateMapViewWhenNoData{
        GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:self.coordinate.latitude
                                                            longitude:self.coordinate.longitude
                                                                 zoom:16.0];
    _mapView = [GMSMapView mapWithFrame:CGRectMake(0, 0, SCREEN_W, SCREEN_H - 64) camera:camera];


    _mapView.delegate = self;
    _mapView.buildingsEnabled = NO;
    _mapView.indoorEnabled = NO;
    _mapView.myLocationEnabled = YES;
    _mapView.settings.compassButton = YES;
    _mapView.settings.allowScrollGesturesDuringRotateOrZoom = NO;

    [self.view addSubview: _mapView];
    [self.view bringSubviewToFront:self.refreshBtn];
    [self.view bringSubviewToFront:self.myLocationbtn];
    [self.view bringSubviewToFront:self.centerFlagImage];
    _lastCoord = camera.target;
}
//展示附近的商家
- (void)updateNearbyShopForMaps{
    ShopModel *shopModel;
    for (int i = 0; i < self.shopList.count; i ++) {

        shopModel = self.shopList[i];
        GMSMarker *marker = [[GMSMarker alloc] init];
        marker.position = CLLocationCoordinate2DMake(shopModel.lat, shopModel.lng);
        marker.appearAnimation = kGMSMarkerAnimationPop;
        marker.icon = [UIImage imageNamed:@"shop_map_flag.png"];
        marker.snippet = LS(((ShopModel*)self.shopList[i]).restaurantName);
        marker.userData = (ShopModel*)self.shopList[i];
        marker.map = _mapView;
    }
}


//当是shopDetail push过来的时候   只显示单独的一个大头针
- (void)updateMapByShopAddress{
    if (!self.startPoint || (!self.startPoint.coordinate.latitude || !self.startPoint.coordinate.longitude)) {
        [self getMyLocation];
        self.startPoint = [[CLLocation alloc]initWithLatitude:self.coordinate.latitude longitude:self.coordinate.longitude];
        [self xw_showMessage:LS(@"Unable to locate the current store")];
    }

    GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:self.startPoint.coordinate.latitude
                                                            longitude:self.startPoint.coordinate.longitude
                                                                 zoom:16.0];
    _mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];

    _mapView.delegate = self;
    _mapView.settings.myLocationButton = YES;
    _mapView.myLocationEnabled = YES;
    _mapView.settings.compassButton = YES;

    GMSMarker *marker = [[GMSMarker alloc] init];
    marker.position = camera.target;
    marker.snippet = LS(self.shopName);
    marker.icon = [UIImage imageNamed:@"shop_map_flag.png"];
    marker.appearAnimation = kGMSMarkerAnimationPop;
    marker.map = _mapView;
    self.view = _mapView;

}

#pragma marker ----------googlemaps delegate
//定制信息窗口(大头针点击后展示的View)   view 可复用
//- (UIView *GMS_NULLABLE_PTR)mapView:(GMSMapView *)mapView markerInfoWindow:(GMSMarker *)marker{
//    
//    if (marker.userData) {
//        写的不好,但是木易原创哦
//    }
//    
//    return [[UIView alloc]init];
//}
//大头针上的snippet被点击时响应
- (void)mapView:(GMSMapView *)mapView didTapInfoWindowOfMarker:(GMSMarker *)marker{
    NSLog(@"点我干啥?");

    if (self.isFromDetail) {
        ADAlertSheetAction *action1 = [ADAlertSheetAction actionWithName:LS(@"Planning route") style:UIAlertActionStyleDefault action:^{
            [self getToDestinationWithDirections:mapView.myLocation.coordinate destination:mapView.selectedMarker.position];
        }];
        ADAlertSheetAction *action2 = [ADAlertSheetAction actionWithName:LS(@"Navigation") style:UIAlertActionStyleDefault action:^{
            [self openUserMappAPPToNavigation:mapView.myLocation.coordinate toLocation:mapView.selectedMarker.position];
        }];
        [ADAlertSheet actionSheetWithTitle:nil message:nil actionList:@[action1, action2]];
    }else{
        //来自nearby的时候   直接到该店铺
        if (marker.userData && [marker.userData isKindOfClass:[ShopModel class]]) {
            ShopDetailController * sdvc = [[ShopDetailController alloc]init];
            sdvc.shopModel = marker.userData;
            [self.navigationController pushViewController:sdvc animated:YES];
        }
    }

}
//点击定位自己按钮的时候调用
- (BOOL)didTapMyLocationButtonForMapView:(GMSMapView *)mapView{
    NSLog(@"定一下自己在哪里、、、");
    //若是shopDetail时    只需要定位到当前位置
    if (!self.isFromDetail) {
        _isUserMove = YES;
        [mapView animateToLocation:mapView.myLocation.coordinate];
    }else{
        [mapView animateToLocation:mapView.myLocation.coordinate];
    }
    [_mapView animateToZoom:16];
    return YES;
}

//判断本次移动
- (void)mapView:(GMSMapView *)mapView willMove:(BOOL)gesture{
    if (gesture) {
        _isUserMove = YES;
    }
}
//移动完成之后
- (void)mapView:(GMSMapView *)mapView idleAtCameraPosition:(GMSCameraPosition *)position{
    if (_isUserMove && !_isFromDetail) {
        //判断移动距离
        if (GMSGeometryDistance(_lastCoord, position.target) >= 500) {
            [self getNearbyShopWith:position.target];

            [UIView animateWithDuration:0.1 animations:^{
                self.centertImageConstraints.constant = - 4;
                [self.view layoutIfNeeded];
            } completion:^(BOOL finished) {
                [UIView animateWithDuration:0.15 animations:^{
                    self.centertImageConstraints.constant = 4;
                    [self.view layoutIfNeeded];
                } completion:^(BOOL finished) {
                    [UIView animateWithDuration:0.1 animations:^{
                        self.centertImageConstraints.constant = 0;
                        [self.view layoutIfNeeded];
                    }];
                }];
            }];
            _isUserMove = NO;
            _lastCoord = position.target;
        }else{
            NSLog(@"\n moved distance is too small\n\n");
        }
    }
}

#pragma mark - -----------------
- (IBAction)refreshBtn_action:(id)sender {
    [self refreshUserLocationNearbyShop];
}
- (IBAction)myLocationBtn_action:(id)sender {
    _isUserMove = YES;
//    [_mapView animateToZoom:16];
    [_mapView animateToLocation:_mapView.myLocation.coordinate];
}

//刷新目前所在地周边店铺
- (void)refreshUserLocationNearbyShop{
    [self getNearbyShopWith:_mapView.myLocation.coordinate];
}
#pragma mark -------调用自带地图定位---------------
//当前位置   目的地   打开自带地图
- (void)openUserMappAPPToNavigation:(CLLocationCoordinate2D)currentLoac toLocation:(CLLocationCoordinate2D)destination{
//    currentLoac.latitude = 31.19929369;
//    currentLoac.longitude = 121.47497177;
    MKMapItem *myLocation = [[MKMapItem alloc]initWithPlacemark:[[MKPlacemark alloc]initWithCoordinate:currentLoac addressDictionary:nil]];
    myLocation.name = LS(@"current location");
    MKMapItem *toLocation = [[MKMapItem alloc]initWithPlacemark:[[MKPlacemark alloc]initWithCoordinate:destination addressDictionary:nil]];
    toLocation.name = LS(self.shopName);

    NSArray *items = [NSArray arrayWithObjects:myLocation, toLocation, nil];
    NSDictionary *options = @{MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving
                              ,MKLaunchOptionsMapTypeKey:[NSNumber numberWithInteger:MKMapTypeStandard]
                              ,MKLaunchOptionsShowsTrafficKey:@YES};

    [MKMapItem openMapsWithItems:items launchOptions:options];
}
#pragma mark -  路线规划 ----------------
//根据自己所在位置和目的地  获取规划路线点
- (void)getToDestinationWithDirections:(CLLocationCoordinate2D )localCoord destination:(CLLocationCoordinate2D)toCoord {

    NSString *urlStr = [NSString stringWithFormat:@"https://maps.googleapis.com/maps/api/directions/json?origin=%g,%g&destination=%g,%g&sensor=false&mode=walking",localCoord.latitude,localCoord.longitude,toCoord.latitude,toCoord.longitude];

    AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:urlStr]];
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];

    NSURLSessionDataTask *sessionTask = nil;
    sessionTask = [manager GET:urlStr parameters:nil progress:^(NSProgress * _Nonnull uploadProgress) {

    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {

        if (responseObject && [responseObject isKindOfClass:[NSData class]]) {
            GMSPath *path = [GMSPath pathFromEncodedPath:[self getDirecPolyLinePoit:responseObject]];
            GMSPolyline *polyLine = [GMSPolyline polylineWithPath:path];
            polyLine.strokeWidth = 5.f;
            polyLine.strokeColor = UIColorFromRGB(0x4CACE2);
            polyLine.geodesic = YES;
            polyLine.map = _mapView;

            GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithCoordinate:localCoord coordinate:toCoord];
            GMSCameraUpdate *upData = [GMSCameraUpdate fitBounds:bounds withEdgeInsets:UIEdgeInsetsMake(20, 50, 20, 50)];
            [_mapView animateWithCameraUpdate:upData];

        }else{
            [self xw_showError:LS(@"data exception")];
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        OCLog(@"operation:%@, responseObject:%@", task, error);
        [ADAlertView alertWithTitle:LS(@"") message:nil cancel:LS(@"cancle") ok:LS(@"ok") cancelBlock:^(UIAlertAction * _Nullable action) {
            return ;
        } okBlock:^(UIAlertAction * _Nullable action) {
            [self getToDestinationWithDirections:_mapView.myLocation.coordinate destination:_mapView.selectedMarker.position];
        }];
    }];
}

- (id)getDirecPolyLinePoit:(id)respon{
    NSDictionary *dic = [RootRoute getDictionaryWithJSONString:respon];
    NSDictionary *tmp;
    if (dic) {
        tmp = [dic[@"routes"] objectAtIndex:0][@"overview_polyline"];
        if (tmp[@"points"]) {
            return tmp[@"points"];
        }
    }
    [self xw_showError:LS(@"Data resolution failure")];
    return nil;
}
#pragma mark - 获取当前位置
- (void)getMyLocation{
    if (self.coordinate.latitude == 0 || self.coordinate.longitude == 0) {
        if ([XWLocationManager sharedInstance].location) {
            if (CLLocationCoordinate2DIsValid([XWLocationManager sharedInstance].location.coordinate)) {
                self.coordinate = [XWLocationManager sharedInstance].location.coordinate;
                OCLog(@"定位完成");
            } else {
                self.coordinate = kCLLocationCoordinate2DInvalid;
            }
        } else {
            self.coordinate = kCLLocationCoordinate2DInvalid;
        }
    }
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}
@end
 类似资料: