首先介紹下我們app:
由于我們是一個(gè)地圖打點(diǎn)券躁,連線的app惩坑。客戶提出一個(gè)需求也拜,在手機(jī)上畫出一個(gè)矩形以舒,要求計(jì)算矩形中的線總長度。
看到這個(gè)需求后慢哈,就去翻閱了百度sdk的文檔: http://lbsyun.baidu.com/index.php?title=iossdk/guide/map-render/ploygon
百度地圖sdk中蔓钟,存在繪制面,弧線的api卵贱,但是都是需要經(jīng)緯度之后才能繪制滥沫。 當(dāng)時(shí)就放棄了這種方法。
- 因?yàn)橹白鯽pp的時(shí)候 我們在mapview上有過view键俱,然后轉(zhuǎn)化為百度地圖的gps坐標(biāo)兰绣。所以覺得邏輯應(yīng)該是,使用touch代理時(shí)間或者拖拽來在百度地圖上畫一個(gè)矩形view编振。然后將view的坐標(biāo)轉(zhuǎn)化為百度地圖的坐標(biāo)缀辩。這樣子來確定經(jīng)緯度范圍。
所以:最終的方案是踪央,先使用touch代理畫取矩形(我使用的touch代理臀玄,沒用拖拽手勢)。然后將view貼到mapview上畅蹂。轉(zhuǎn)化為mapview的經(jīng)緯度范圍镐牺。再進(jìn)行篩選。
一步一步實(shí)現(xiàn):
- 先畫一個(gè)view:
自己做了一個(gè)小demo魁莉,通過touch的代理方法 來畫出矩睬涧。下面看代碼募胃。
先看看代碼塊顯示效果
PacView 是我自定義的一個(gè)view。 剛開始以為要用到drawrect畦浓。
- (void)viewDidLoad {
[super viewDidLoad];
self.title = _titleStr;
self.view.backgroundColor = [UIColor whiteColor];
_zyqview = [[PacView alloc]initWithFrame:CGRectMake(50, 104, 80, 80)];
[self.view addSubview:_zyqview];
_zyqview.backgroundColor = [UIColor greenColor];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
NSSet *allTouches = [event allTouches]; //返回與當(dāng)前接收者有關(guān)的所有的觸摸對象
UITouch *touch = [allTouches anyObject]; //視圖中的所有對象
CGPoint point = [touch locationInView:[touch view]]; //返回觸摸點(diǎn)在視圖中的當(dāng)前坐標(biāo)
_oriX = point.x;
_oriY = point.y;
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[super touchesMoved:touches withEvent:event];
NSSet *allTouches = [event allTouches]; //返回與當(dāng)前接收者有關(guān)的所有的觸摸對象
UITouch *touch = [allTouches anyObject]; //視圖中的所有對象
CGPoint point = [touch locationInView:[touch view]]; //返回觸摸點(diǎn)在視圖中的當(dāng)前坐標(biāo)
_changeX = point.x;
_changeY = point.y;
// NSLog(@"2touch (x, y) is (%d, %d)", _changeX, _changeY);
[self jisuanHeightWidth];
}
- (void)jisuanHeightWidth {
int height = 0;
int width = 0;
if (_changeX > _oriX) {
width = _changeX - _oriX;
}else {
width = _oriX - _changeX;
}
if (_changeY >_oriY) {
height = _changeY - _oriY;
}else {
height = _oriY - _changeY;
}
CGRect rect = CGRectMake(0, 0, 0, 0);
//右下
if (_changeX > _oriX && _changeY >_oriY) {
rect = CGRectMake(_oriX, _oriY, width, height);
}
//右上
if (_changeX > _oriX && _changeY <_oriY) {
rect = CGRectMake(_oriX, _changeY, width, height);
}
//左下
if (_changeX < _oriX && _changeY >_oriY) {
rect = CGRectMake(_changeX, _oriY, width, height);
}
//左上
if (_changeX < _oriX && _changeY <_oriY) {
rect = CGRectMake(_changeX, _changeY, width, height);
}
_zyqview.frame = rect;
}
以上代碼就可以畫出一個(gè)矩形了痹束。 如果是拖拽方法的話,可能jisuanHeightWidth方法里的frame獲取要改變下讶请。
- 接入百度地圖項(xiàng)目:
上面的畫矩形方法直接扔到項(xiàng)目里就行了祷嘶。
[self.view addSubview:_zyqview]; 這個(gè)方法的self.view 改為 mapview就行了。 因?yàn)橐粫阋D(zhuǎn)化為mapview的坐標(biāo)經(jīng)緯度
然后畫完矩形后夺溢,手指松開论巍,會走下面的方法
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
[super touchesEnded:touches withEvent:event];
if (_isRightXY == YES) {
[self caclulaterPacViewToMapView];
}
_isRightXY = NO;
}
- (void)caclulaterPacViewToMapView {
if (_jisuanButton.selected == YES) {
//百度地圖
BMKCoordinateRegion region = [_mapView convertRect:_zyqview.frame toRegionFromView:_mapView];
// region.span.latitudeDelta //緯度范圍 是指總長,類似寬高风响。
// region.span.longitudeDelta 經(jīng)度范圍
// CLLocationCoordinate2D center; ///< 中心點(diǎn)經(jīng)緯度坐標(biāo)
double leftLat = region.center.latitude - region.span.latitudeDelta/2;
double rightLat = region.center.latitude + region.span.latitudeDelta/2;
double topLog = region.center.longitude - region.span.longitudeDelta/2;//最小
double bootomLog = region.center.longitude + region.span.longitudeDelta/2;//最大
// 113.615697,34.745975;113.611570,34.750439 long嘉汰,lat;long状勤,lat
//另一種計(jì)算方法
// 左下 右上 最小最大
CGPoint mixPoint = CGPointMake(CGRectGetMinX(_zyqview.frame), CGRectGetMinY(_zyqview.frame)+CGRectGetHeight(_zyqview.frame));
CGPoint maxPoint = CGPointMake(CGRectGetMinX(_zyqview.frame) + CGRectGetWidth(_zyqview.frame), CGRectGetMinY(_zyqview.frame));
CLLocationCoordinate2D mixCoordinate = [_mapView convertPoint:mixPoint toCoordinateFromView:_mapView];
CLLocationCoordinate2D maxCoordinate = [_mapView convertPoint:maxPoint toCoordinateFromView:_mapView];
leftLat = mixCoordinate.latitude;
rightLat = maxCoordinate.latitude;
topLog = mixCoordinate.longitude;
bootomLog = maxCoordinate.longitude;
NSLog(@"圈圈圈%f,%f,%f,%f",topLog,bootomLog,leftLat,rightLat);
NSMutableArray * counArray = [NSMutableArray new];
for (TYBMKPolyline * line in _mapView.overlays) {
if ([line isKindOfClass:[TYBMKPolyline class]]) {
NSArray * latAndLogArray = [line.slnInfo.line_Longitude_Latitude componentsSeparatedByString:@";"];
NSString * firstCor = latAndLogArray[0];//第一個(gè)coors
NSString * secCor = latAndLogArray[1];//第2個(gè)coors
double firstLog = [[firstCor componentsSeparatedByString:@","][0] doubleValue];
double firstLat = [[firstCor componentsSeparatedByString:@","][1] doubleValue];
double secLog = [[secCor componentsSeparatedByString:@","][0] doubleValue];
double sectLat = [[secCor componentsSeparatedByString:@","][1] doubleValue];
CLLocationCoordinate2D coors[2] = {0};
coors[0].latitude = firstLat;
coors[0].longitude = firstLog;
coors[1].latitude = sectLat;
coors[1].longitude = secLog;
CLLocationCoordinate2D converTos[2] = {0};
converTos[0] = [TYTool baiduLocationFromGPSCoordinate2D:coors[0]];
converTos[1] = [TYTool baiduLocationFromGPSCoordinate2D:coors[1]];
firstLat = converTos[0].latitude;
firstLog = converTos[0].longitude;
sectLat = converTos[1].latitude;
secLog = converTos[1].longitude;
double minLog = MIN(firstLog, secLog);
double minLat = MIN(firstLat, sectLat);
double maxLog = MAX(firstLog, secLog);
double maxLat = MAX(firstLat, sectLat);
NSLog(@"%f,%f,%f,%f \n ---%f",minLog,maxLog,minLat,maxLat,line.slnInfo.line_Distance);
if (minLog>topLog && maxLog<bootomLog && minLat>leftLat && maxLat<rightLat) {//最大的和最大的比鞋怀,最小的和最小的比
// NSLog(@"%f,%f,%f,%f ---%f",minLog,maxLog,minLat,maxLat,line.slnInfo.line_Distance);
[counArray addObject:line];
}
}
}
// NSLog(@"%ld",counArray.count);
if (counArray.count != 0) {
double allLineDis = 0.0;
for (TYBMKPolyline * line in counArray) {
allLineDis = allLineDis + line.slnInfo.line_Distance;
}
_tipsLabel.text = [NSString stringWithFormat:@"長度為%.f 米",allLineDis];
// UIAlertController * ac = [UIAlertController alertControllerWithTitle:@"提示" message:[NSString stringWithFormat:@"%f",allLineDis] preferredStyle:UIAlertControllerStyleAlert];
// UIAlertAction * deleteAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
//// _zyqview.hidden = YES;
// }];
// [ac addAction:deleteAction];
// [self presentViewController:ac animated:YES completion:nil];
}else {
[[TYNotification share] showPromptView:@"沒有符合要求的線"];
_tipsLabel.text = @"請劃線";
// _zyqview.hidden = YES;
}
}
}
關(guān)于百度sdk的這個(gè)方法:
BMKCoordinateRegion region = [_mapView convertRect:_zyqview.frame toRegionFromView:_mapView];
// region.span.latitudeDelta //緯度范圍 是指總長,類似寬高持搜。
// region.span.longitudeDelta 經(jīng)度范圍
// CLLocationCoordinate2D center; ///< 中心點(diǎn)經(jīng)緯度坐標(biāo)
double leftLat = region.center.latitude - region.span.latitudeDelta/2;
double rightLat = region.center.latitude + region.span.latitudeDelta/2;
double topLog = region.center.longitude - region.span.longitudeDelta/2;//最小
double bootomLog = region.center.longitude + region.span.longitudeDelta/2;//最大
// 113.615697,34.745975;113.611570,34.750439 long密似,lat;long葫盼,lat
api上給的是 將view坐標(biāo) 轉(zhuǎn)化為經(jīng)緯度残腌。 region.span.longitudeDelta 經(jīng)度范圍,這個(gè)經(jīng)度范圍最開始 我當(dāng)成是寬/2來計(jì)算贫导。
double leftLat = region.center.latitude - region.span.latitudeDelta
后來發(fā)現(xiàn)根本不正確废累,精確度錯(cuò)的太多,后來web同事提醒脱盲,是不是region.span.longitudeDelta是寬度的一半邑滨,就改成了這樣
double leftLat = region.center.latitude - region.span.latitudeDelta/2
后來發(fā)現(xiàn)還是不行,雖然精確度提高了钱反,但是還是誤差很大很大掖看。
最后曲線救國吧
// 左下 右上 最小最大
CGPoint mixPoint = CGPointMake(CGRectGetMinX(_zyqview.frame), CGRectGetMinY(_zyqview.frame)+CGRectGetHeight(_zyqview.frame));
CGPoint maxPoint = CGPointMake(CGRectGetMinX(_zyqview.frame) + CGRectGetWidth(_zyqview.frame), CGRectGetMinY(_zyqview.frame));
CLLocationCoordinate2D mixCoordinate = [_mapView convertPoint:mixPoint toCoordinateFromView:_mapView];
CLLocationCoordinate2D maxCoordinate = [_mapView convertPoint:maxPoint toCoordinateFromView:_mapView];
leftLat = mixCoordinate.latitude;
rightLat = maxCoordinate.latitude;
topLog = mixCoordinate.longitude;
bootomLog = maxCoordinate.longitude;
將左下,右上的點(diǎn)提出來轉(zhuǎn)化為經(jīng)緯度面哥,最后就ok了哎壳。
以上就是這次需求開發(fā)的坑。尚卫。
第一次用markdown寫企孩。gif不知道怎么上傳=- =