您的位置:首页 > 移动开发 > IOS开发

iOS上地图画线,画线区域内的经纬度坐标点添加大头针

2013-12-02 16:50 666 查看
实现在Google地图上用手指可以画线的功能,同时地图上的一点(经纬度坐标点)如果在画线的区域内,会在这个点落下大头针的功能,类似大众点评的画线圈商铺的效果





在做了前两篇博客的工作以后,对手指移动画线的方法有了了解,所以思路是一样的,先在根视图上加一个MapView,然后在MapView上面加画图的View,也就是说地图是地图,画线是画线,互不干扰,但是这样做的话怎么能实现范围内经纬度点的识别呢?这里就要用到地图坐标和画图坐标的转换,后面会讲。

所以解决方法是在画布View上画图,然后通过坐标转换获得这一圈儿的经纬度坐标点,然后在经纬度值的范围内的坐标点找出来,然后在这个坐标点上加大头针。

但是在实际操作中发现就算我获得了这一圈儿的经纬度值,存在一个数组里,我也不知道如何判断某个经纬度是不是在这个范围之内。

所以反着来想,之前的解决思路是View上的坐标转化成地图的经纬度坐标,当然也可以把地图上经纬度坐标转化成View上的坐标,因为在View上CGPath范围内的点是可以找出来的(后面会讲),所以后来决定按这个思路做,会更顺利些。

 

 

下面是具体代码,首先创建一个SingleView项目,引入必要的两个库文件CoreLocation.framewrok和MapKit.framework,地图的展示和定位都要用到,然后ViewController.h头文件添加如下代码:

#import <UIKit/UIKit.h>
#import “MapKit/MapKit.h”
@interface ViewController : UIViewController<CLLocationManagerDelegate,MKMapViewDelegate>
{
MKMapView *innerMap;//地图层
UIImageView *imageView;//绘画层
CLLocationManager *locationManager;//定位实例
NSMutableArray *array;//存储经纬度坐标的数组,这里用不着
CGMutablePathRef pathRef;//手指画线的Path
CLLocationCoordinate2D testLocation;//测试的位置(经纬度)
CGPoint locationConverToImage;//存储转换测试位置的CGPoint
}
@end

之后是终点ViewController.m的代码,视图中两个按钮就不说了,通过IB拖拽的,功能函数下面会说,功能如其名,首先是ViewDidLoad方法:

- (void)viewDidLoad
{
[super viewDidLoad];
//添加地图层
innerMap=[[MKMapView alloc] initWithFrame:CGRectMake(0, 50, 320, 430)];
[self.view addSubview:innerMap];
//[innerMap setShowsUserLocation:YES];//不显示定位小蓝点儿
[innerMap setDelegate:self];
//添加定位信息,为了设置地图显示的Region范围
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate=self;
locationManager.desiredAccuracy=kCLLocationAccuracyBest;
locationManager.distanceFilter=1000.0f;
[locationManager startUpdatingLocation];
MKCoordinateSpan theSpan;
theSpan.latitudeDelta=0.03;
theSpan.longitudeDelta=0.03;
MKCoordinateRegion theRegion={ {0.0, 0.0 }, { 0.0, 0.0 } };
theRegion.center=locationManager.location.coordinate;
theRegion.span=theSpan;
[innerMap setRegion:theRegion animated:YES];
//用当前经纬度来设置测试经纬度点,便于查看
// NSLog(@”latitude !!! %f”,locationManager.location.coordinate.latitude);
//  NSLog(@”longtitude !!! %f”,locationManager.location.coordinate.longitude);
//初始化数组为以后存储数据使用
array=[NSMutableArray array];
}

 上面的代码加载了按钮和地图,并让地图显示区域调整到当前位置为中心的一个范围内,准备工作做好了,下面是draw按钮的代码,事件如下:

-(IBAction)drawFunction:(id)sender{
imageView=[[UIImageView alloc] initWithFrame:innerMap.frame];
[self.view addSubview:imageView];
imageView.userInteractionEnabled=YES;
UIGraphicsBeginImageContext(imageView.frame.size);
[imageView.image drawInRect:CGRectMake(0, 0, imageView.frame.size.width, imageView.frame.size.height)];
CGContextSetRGBFillColor(UIGraphicsGetCurrentContext(), 50, 79, 133, 1.0);
CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), [UIColor redColor].CGColor);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 4);
//地理坐标转换成点
testLocation.latitude=39.995012;//设定测试点的坐标是当前位置
testLocation.longitude=116.411892;
locationConverToImage=[innerMap convertCoordinate:testLocation toPointToView:imageView];
// NSLog(@”111 %f”,locationConverToImage.x);
// NSLog(@”222 %f”,locationConverToImage.y);
}

上面的方法点击后会创建一个imageView,我们会在上面来画图,同时设定了上下文和画线的宽度填充色等元素,最底下

convertCoordinate:toPointToView:

这个方法就是坐标转换的方法了,把一个经纬度坐标转化为CGPoint坐标并存储在locationConverToImage里,这里要说明一下坐标的转化了,坐标转化能做什么呢?

(1)让当前屏幕显示区域的CGPoint点坐标(x,y)值映射到当前地图可视区域同一个位置的CLLocationCoordinate2D(latitude,longitude)值,也就是让绘图层上的一点的xy值对应地图层上一点的经纬度值

(2)反之,让地图上的经纬度点坐标转换成同位置的CGPoint点坐标。

这里我觉得这个方法的功能实现的很奇妙,两个毫不相关的层就这么互通有无了,相信苹果一定利用某种算法计算了当前显示的地图区域的缩放等级并有一个经纬度范围。

总之这个draw按钮的点击创建了绘画层,也定义了一个测试的经纬度坐标点,同时把这个点转换成了imageView上面的CGPoint点

再看下Clear按钮:

-(IBAction)clearFunction:(id)sender{
[imageView removeFromSuperview];//删除绘图层
[array removeAllObjects];
[innerMap removeAnnotations:innerMap.annotations];//删除大头针
UIGraphicsEndImageContext();//删除画布
}

这个就比较简单了,剩下的就是添加touch的三个方法,begin,move,end,在begin和move的时候画图,在end的时候做判断区域的处理并添加大头针
首先是touchbegin:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:imageView];
//创建path
pathRef=CGPathCreateMutable();
CGPathMoveToPoint(pathRef, NULL, location.x, location.y);
}

在点击开始的方法里记录了点击的坐标,同时创建了一个CGPath,并设置起点为当前坐标,这个Path在手指移动的时候会跟随着改变,接下来是touchmove方法:

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:imageView];
CGPoint pastLocation = [touch previousLocationInView:imageView];
//画线
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), pastLocation.x, pastLocation.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), location.x, location.y);
CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathFillStroke);
imageView.image=UIGraphicsGetImageFromCurrentImageContext();
//更新Path
CGPathAddLineToPoint(pathRef, NULL, location.x, location.y);
}

这里的画线部分和之前的博客一样,值得注意的是每一次touchmove都会让path跟着更新,接下来是touchend方法:

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
CGPathCloseSubpath(pathRef);
if (CGPathContainsPoint(pathRef, NULL, locationConverToImage, NO)) {
NSLog(@”point in path!”);
MKPointAnnotation *pointAnnotation = nil;
pointAnnotation = [[MKPointAnnotation alloc] init];
pointAnnotation.coordinate = locationManager.location.coordinate;
pointAnnotation.title = @”大头针”;
[innerMap addAnnotation:pointAnnotation];
}
}

可以看到抬手的时候判断是否在path区域内的点locationConverToImage就是测试经纬度坐标点转化完以后的点,如果在这个区域里就添加大头针,如果想让大头针有落下的动画或者自定义颜色还要加上这个代理方法:

- (MKAnnotationView*) mapView: (MKMapView*) mapView viewForAnnotation: (id<MKAnnotation>) annotation{
MKPinAnnotationView *pinView = nil;
static NSString *defaultPinID = @”com.invasivecode.pin”;
pinView = (MKPinAnnotationView *)[innerMap dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil ) pinView = [[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID];
pinView.pinColor = MKPinAnnotationColorPurple;
pinView.animatesDrop = YES;
[innerMap.userLocation setTitle:@"欧陆经典"];
[innerMap.userLocation setSubtitle:@"vsp"];
return pinView;
}

接下来要完成的是填充path颜色,增加多个点等等,有待继续完善

(转自:http://lipengxuan.easymorse.com/?p=588)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: