在MKMapView中,以用户位置为中心绘制一个半径为1000米的圆形区域。

64

(使用iOS 5和Xcode 4.2)

我有一个MKMapView,想在用户位置周围绘制一个1000m半径的圆。

表面上看来,实现mapView:viewForAnnotation:地图视图委托方法,并为用户位置添加自定义MKAnnotationView将是一个完美的解决方案。它将会像下面这样:

- (MKAnnotationView *)mapView:(MKMapView *)mapView
            viewForAnnotation:(id <MKAnnotation>)annotation
{
    // If it's the user location, return my custom MKAnnotationView.
    if ([annotation isKindOfClass:[MKUserLocation class]]) {
        return myCustomAnnotationView;
    } else {
        return nil;
    }
}

然而,当您放大或缩小地图时,地图上的注释并不会随之缩放。
因此,我尝试添加一个覆盖层(因为覆盖层可以随着地图一起缩放),使用MKCircle类并将其坐标设置为locationManger/map view delegate中最新的坐标。但是,由于MKCircle的coordinate property是只读的,每次用户移动时,我都必须删除覆盖层,然后添加一个新的覆盖层,这会导致明显的闪烁。
有没有办法使注释随着地图视图的缩放无缝缩放?还是有没有一种好的方法使覆盖层随着用户位置的变化无缝移动?
非常感谢您的帮助 :)

7
我认为你需要自定义叠加层和叠加视图(就像@Flink所暗示的那样)。不过,更符合你需求的苹果示例是来自2010年WWDC的LocationReminders应用程序。如果你是注册开发人员,你可以在这里找到它 here。它会自定义绘制一个圆形叠加层,其大小和位置可以动态改变。 - user467105
谢谢提供链接,听起来正是我需要的例子。而且我是注册开发者,这很方便 :) - Jon Cox
链接已经失效,但我在Github上找到了这个:https://github.com/master-nevi/WWDC-2010/tree/master/LocationReminders - foson
8个回答

81

尝试使用自定义叠加层。在viewDidLoad中添加以下内容:

MKCircle *circle = [MKCircle circleWithCenterCoordinate:userLocation.coordinate radius:1000];
[map addOverlay:circle];

通过将MKUserLocationAnnotation存储为属性,可以获取userLocation。然后,在地图视图的代理中放置以下内容以实际绘制圆形:

- (MKOverlayRenderer *)mapView:(MKMapView *)map viewForOverlay:(id <MKOverlay>)overlay
{
    MKCircleRenderer *circleView = [[MKCircleRenderer alloc] initWithOverlay:overlay];
    circleView.strokeColor = [UIColor redColor];
    circleView.fillColor = [[UIColor redColor] colorWithAlphaComponent:0.4];
    return circleView;
}

当用户位置改变时,移动圆形。 - Daij-Djan
我们如何移动这个圆?每次移动它时,我们需要创建一个新的MKCircle吗? - yuf
需要更新至iOS 7! - Hyperbole
18
注意,在iOS 7中,MKOverlayViewMKCircleView已被弃用(根据@Hyperbole的说法)。请改用MKOVerlayRendererMKCircleRenderer - ericsoco
1
你还需要使用MKMapViewDelegate协议才能使其正常工作。 - vladCovaliov

50

iOS 8.0 的更新版本,使用 Swift。

import Foundation
import MapKit

class MapViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate{
    var locationManager: CLLocationManager = CLLocationManager()

    @IBOutlet var mapView: MKMapView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // We use a predefined location
        var location = CLLocation(latitude: 46.7667 as CLLocationDegrees, longitude: 23.58 as CLLocationDegrees)

        addRadiusCircle(location)
    }

    func addRadiusCircle(location: CLLocation){
        self.mapView.delegate = self
        var circle = MKCircle(centerCoordinate: location.coordinate, radius: 10000 as CLLocationDistance)
        self.mapView.addOverlay(circle)
    }

    func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
        if overlay is MKCircle {
            var circle = MKCircleRenderer(overlay: overlay)
            circle.strokeColor = UIColor.redColor()
            circle.fillColor = UIColor(red: 255, green: 0, blue: 0, alpha: 0.1)
            circle.lineWidth = 1
            return circle
        } else {
            return nil
        }
    }
}

4
mapView:rendererfForOverlay 中不能返回 nil,参见修复方法:https://dev59.com/JY7ea4cB1Zd3GeqPG-L8#32452494。 - Ryan R
rendererForOverlay被替换为rendererFor。 - Guy
UIColor的颜色分量应该在0到1之间。你使用了255来表示红色 - 这是错误的! - Alexander Volkov

25

这里是Swift 3/Xcode 8:

func addRadiusCircle(location: CLLocation){
    if let poll = self.selectedPoll {
        self.mapView.delegate = self
        let circle = MKCircle(center: location.coordinate, radius: 10)
        self.mapView.add(circle)
    }
}

func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
    if overlay is MKCircle {
        let circle = MKCircleRenderer(overlay: overlay)
        circle.strokeColor = UIColor.red
        circle.fillColor = UIColor(red: 255, green: 0, blue: 0, alpha: 0.1)
        circle.lineWidth = 1
        return circle
    } else {
        return MKPolylineRenderer()
    }
}

然后这样调用:

self.addRadiusCircle(location: CLLocation(latitude: YOUR_LAT_HERE, longitude: YOUR_LNG_HERE))

2
self.selectedPoll是什么?它来自哪里? - BlueBoy
@thexande 半径:10,这里的10代表什么值?是英里、米还是千米? - Mitesh Dobareeya
@MiteshDobareeya,这个10点半径可以改成函数参数,如果你需要一个动态半径的圆。 - thexande
如果我需要获取用户当前位置并在其周围绘制圆圈,那么我应该把self.addRadiusCircle方法放在哪里? - Sachin Dobariya
你的意思是红色值为1,而不是255。 - Benny Davidovitz

3

我不确定面包屑示例如何解决MKCircle移动问题。 - user836026
我不确定如何使用crumbPath来完成这个。 - user836026

2
我不理解benwad的回答。这里有更清晰的答案
添加圆形相当容易。符合MKMapViewDelegate即可。
@interface MyViewController : UIViewController <MKMapViewDelegate>
@property (weak, nonatomic) IBOutlet MKMapView *mapView;
@end

在viewDidLoad方法中,创建一个圆形标注并将其添加到地图上:
CLLocationCoordinate2D center = {39.0, -74.00};

// Add an overlay
MKCircle *circle = [MKCircle circleWithCenterCoordinate:center radius:150000];
[self.mapView addOverlay:circle];

然后实现mapView:viewForOverlay:来返回视图。
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{
    MKCircleView *circleView = [[MKCircleView alloc] initWithOverlay:overlay];
    [circleView setFillColor:[UIColor redColor]];
    [circleView setStrokeColor:[UIColor blackColor]];
    [circleView setAlpha:0.5f];
    return circleView;
}

但是,如果您希望圆圈始终保持相同的大小,无论缩放级别如何,您需要采取不同的方法。就像您所说,在regionDidChange:animated:中获取latitudeDelta,然后创建一个新的圆(半径适合宽度),删除旧的圆并添加新的圆。

我的提示:不要忘记将mapview与您的视图控制器委托连接起来。否则,viewForOverlay将不会被调用。


1
我所做的就是,在地图工具上显示位置后,最后调用了以下函数。
@IBOutlet weak var mapView: GMSMapView!

var cirlce: GMSCircle!

override func viewDidLoad() {

    super.viewDidLoad()
    mapView.delegate = self
    circleview(redius: 5000) 

  }

//used this func to draw the circle

 func circleview(redius:Double) {

    let  circleCenter = CLLocationCoordinate2D(latitude: 13.3450223, longitude: 74.7512519)

    cirlce = GMSCircle(position: circleCenter, radius: redius)
    cirlce.fillColor = UIColor(red: 230.0/255.0, green: 230.0/255.0, blue: 250.0/255.0, alpha:1.0)
    cirlce.strokeColor = .blue
    cirlce.strokeWidth = 2
    cirlce.map = mapView
  }

3
这是一个针对MKMapView的问题,而不是Google Map。 - Manish Nahar

0
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay

自iOS 4.0起,它已被弃用。


0

添加圆形很容易。遵循MKMapViewDelegate协议。按照以下步骤进行操作:

步骤1:

 CLLocationCoordinate2D center= {self.locationManager.location.coordinate.latitude, self.locationManager.location.coordinate.longitude};
// Add an overlay
MKCircle *circle= [MKCircle circleWithCenterCoordinate:center radius: 20000];//your distance like 20000(like meters)
[myMapView addOverlay:circle];

步骤2:

 - (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
 {
    MKCircleView *C_View = [[MKCircleView alloc] initWithOverlay:overlay];
    [C_View setFillColor:[UIColor lightGrayColor]];
    [C_View setStrokeColor:[UIColor blackColor]];
    [C_View setAlpha:0.5f];

    return C_View;
 }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接