如何创建图像叠加并添加到MKMapView?

时间:2022-10-22 07:22:42

I am trying to learn MapKit and am now trying to add an image as an overlay to the map view. I can't seem to find any sample code to help explain how to do this.

我正在尝试学习MapKit,现在我正在尝试将图像添加为地图视图的叠加层。我似乎无法找到任何示例代码来帮助解释如何执行此操作。

Can you guys please help me how to create MKOverlays and add them to MKMapKit.

你能帮我们如何创建MKOverlay并将它们添加到MKMapKit。

Thanks in advance..

提前致谢..

4 个解决方案

#1


25  

Here is an example to how to sets a UIImage to a MKMapView overlay. Some parameter (coordinates and image path) are fixed, but the code can be easily changed, I guess.

以下是如何将UIImage设置为MKMapView叠加层的示例。一些参数(坐标和图像路径)是固定的,但我猜想代码可以很容易地改变。

Create an class that conforms to MKOverlay:

创建一个符合MKOverlay的类:

MapOverlay.h

MapOverlay.h

@interface MapOverlay : NSObject <MKOverlay> {

}

- (MKMapRect)boundingMapRect;
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;

@end

MapOverlay.m

MapOverlay.m

@implementation MapOverlay

- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate {
    self = [super init];
    if (self != nil) {


    }
    return self;
}

- (CLLocationCoordinate2D)coordinate
{
    CLLocationCoordinate2D coord1 = {
        37.434999,-122.16121
    };

    return coord1;
}

- (MKMapRect)boundingMapRect
{

    MKMapPoint upperLeft = MKMapPointForCoordinate(self.coordinate);

    MKMapRect bounds = MKMapRectMake(upperLeft.x, upperLeft.y, 2000, 2000);
    return bounds;
}


@end

Create an class that conforms to MKOverlayView:

创建一个符合MKOverlayView的类:

MapOverlayView.h

MapOverlayView.h

@interface MapOverlayView : MKOverlayView {

}

@end

MapOverlayView.m

MapOverlayView.m

@implementation MapOverlayView

- (void)drawMapRect:(MKMapRect)mapRect
          zoomScale:(MKZoomScale)zoomScale
          inContext:(CGContextRef)ctx
{

    UIImage *image          = [[UIImage imageNamed:@"image.png"] retain];

    CGImageRef imageReference = image.CGImage;

    MKMapRect theMapRect    = [self.overlay boundingMapRect];
    CGRect theRect           = [self rectForMapRect:theMapRect];
    CGRect clipRect     = [self rectForMapRect:mapRect];

    CGContextAddRect(ctx, clipRect);
    CGContextClip(ctx);

    CGContextDrawImage(ctx, theRect, imageReference);

    [image release]; 

}


@end

Add the overlay to the MKMapView:

将叠加层添加到MKMapView:

MapOverlay * mapOverlay = [[MapOverlay alloc] init];
[mapView addOverlay:mapOverlay];
[mapOverlay release];

On the mapView delegate, implement the viewForOverlay:

在mapView委托上,实现viewForOverlay:

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

    MapOverlay *mapOverlay = overlay;
    MapOverlayView *mapOverlayView = [[[MapOverlayView alloc] initWithOverlay:mapOverlay] autorelease];

    return mapOverlayView;

}

Hope it helps!

希望能帮助到你!

#2


2  

Documentation:

文档:

  • MKMapView functions to manage overlays allow for adding them to a map view.
  • 用于管理叠加层的MKMapView函数允许将它们添加到地图视图中。
  • MKOverlay is the protocol which your overlay object must conform to.
    • MKPolygon, MKPolyLine, MKCircle implement this protocol for simple shapes.
    • MKPolygon,MKPolyLine,MKCircle实现了这个简单形状的协议。
  • MKOverlay是覆盖对象必须符合的协议。 MKPolygon,MKPolyLine,MKCircle实现了这个简单形状的协议。
  • MKOverlayView is used to actually draw the overlay; subclasses exist for each of the above-mentioned simple shapes.
  • MKOverlayView用于实际绘制叠加层;对于每个上述简单形状存在子类。

Sample code:

示例代码:

#3


0  

In the search for a solution for my problem, I keep coming back to this question, and here and also here

在寻找我的问题的解决方案时,我不断回到这个问题,在这里和这里

They were all answering the question I needed answered but in reverse.

他们都在回答我需要回答的问题,但反之亦然。

I needed to determine if a UIView, i.e. a draw square on my MapView contains a map pin, if it does let me know so I can remove it or select it etc.

我需要确定一个UIView,即我的MapView上的绘图方块是否包含地图引脚,如果确实让我知道,那么我可以删除它或选择它等。

Finally after trying to convert my UIView into some MKCoordinateRegion or alike, I thought work backwards. Instead of turning my UIView or square into map madness, I turned the pins into simple CGPoints and did a simple Rect contains point. Which ended up being my solution.. after about 2 hrs!

最后,在尝试将我的UIView转换为某些MKCoordinateRegion或类似之后,我认为向后工作。我没有把我的UIView或方块变成地图疯狂,而是将引脚​​转换成简单的CGPoints并做了一个简单的Rect包含点。最终成为我的解决方案......约2小时后!

Hope this help someone down the line

希望这有助于某人下线

 func findMapPinsWithinBox() {

    guard let myBox = myBox else { return } // some UIView you have drawn or placed on map

    let visibleMapRect = mapView.visibleMapRect
    let visibleAnnotations =  mapView.annotationsInMapRect(visibleMapRect)

    for pin in visibleAnnotations {

        // depending on design you may need to do some casting here
        // ie let pin = pin as! MyMapAnnotation

        let pinsCGPoint = mapView.convertCoordinate(pin.coordinate, toPointToView: self.view)

        if myBox.frame.contains(pinsCGPoint) {
            print("Pin Found within the Box")
            // select pin or delete etc
        }
    }
}

#4


-1  

From just looking at Apple's documentation for the MKOverlay protocol, it doesn't look very complex. Just make a class to do whatever you need to compute the overlay and make sure it conforms to that protocol. That means you must have the coordinate and boundingMapRect properties as well as an implementation for intersectsMapRect:. The Apple docs explain it all.

从仅查看Apple的MKOverlay协议文档来看,它看起来并不复杂。只需创建一个类来完成计算叠加层所需的任何内容,并确保它符合该协议。这意味着您必须具有coordinate和boundingMapRect属性以及intersectsMapRect:的实现。 Apple文档解释了这一切。

Take a look at the HazardMap sample code from Apple. It uses a custom overlay view like you want to do to display an image in the overlay. You simply need to implement mapView:viewForOverlay: in your MKMapViewDelegate class and return a new instance of your subclass of MKOverlayView to get the custom overlay drawn on the screen.

看一下Apple的HazardMap示例代码。它使用您想要的自定义叠加视图来显示叠加层中的图像。您只需在MKMapViewDelegate类中实现mapView:viewForOverlay:并返回MKOverlayView子类的新实例,以获取在屏幕上绘制的自定义叠加层。

#1


25  

Here is an example to how to sets a UIImage to a MKMapView overlay. Some parameter (coordinates and image path) are fixed, but the code can be easily changed, I guess.

以下是如何将UIImage设置为MKMapView叠加层的示例。一些参数(坐标和图像路径)是固定的,但我猜想代码可以很容易地改变。

Create an class that conforms to MKOverlay:

创建一个符合MKOverlay的类:

MapOverlay.h

MapOverlay.h

@interface MapOverlay : NSObject <MKOverlay> {

}

- (MKMapRect)boundingMapRect;
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;

@end

MapOverlay.m

MapOverlay.m

@implementation MapOverlay

- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate {
    self = [super init];
    if (self != nil) {


    }
    return self;
}

- (CLLocationCoordinate2D)coordinate
{
    CLLocationCoordinate2D coord1 = {
        37.434999,-122.16121
    };

    return coord1;
}

- (MKMapRect)boundingMapRect
{

    MKMapPoint upperLeft = MKMapPointForCoordinate(self.coordinate);

    MKMapRect bounds = MKMapRectMake(upperLeft.x, upperLeft.y, 2000, 2000);
    return bounds;
}


@end

Create an class that conforms to MKOverlayView:

创建一个符合MKOverlayView的类:

MapOverlayView.h

MapOverlayView.h

@interface MapOverlayView : MKOverlayView {

}

@end

MapOverlayView.m

MapOverlayView.m

@implementation MapOverlayView

- (void)drawMapRect:(MKMapRect)mapRect
          zoomScale:(MKZoomScale)zoomScale
          inContext:(CGContextRef)ctx
{

    UIImage *image          = [[UIImage imageNamed:@"image.png"] retain];

    CGImageRef imageReference = image.CGImage;

    MKMapRect theMapRect    = [self.overlay boundingMapRect];
    CGRect theRect           = [self rectForMapRect:theMapRect];
    CGRect clipRect     = [self rectForMapRect:mapRect];

    CGContextAddRect(ctx, clipRect);
    CGContextClip(ctx);

    CGContextDrawImage(ctx, theRect, imageReference);

    [image release]; 

}


@end

Add the overlay to the MKMapView:

将叠加层添加到MKMapView:

MapOverlay * mapOverlay = [[MapOverlay alloc] init];
[mapView addOverlay:mapOverlay];
[mapOverlay release];

On the mapView delegate, implement the viewForOverlay:

在mapView委托上,实现viewForOverlay:

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

    MapOverlay *mapOverlay = overlay;
    MapOverlayView *mapOverlayView = [[[MapOverlayView alloc] initWithOverlay:mapOverlay] autorelease];

    return mapOverlayView;

}

Hope it helps!

希望能帮助到你!

#2


2  

Documentation:

文档:

  • MKMapView functions to manage overlays allow for adding them to a map view.
  • 用于管理叠加层的MKMapView函数允许将它们添加到地图视图中。
  • MKOverlay is the protocol which your overlay object must conform to.
    • MKPolygon, MKPolyLine, MKCircle implement this protocol for simple shapes.
    • MKPolygon,MKPolyLine,MKCircle实现了这个简单形状的协议。
  • MKOverlay是覆盖对象必须符合的协议。 MKPolygon,MKPolyLine,MKCircle实现了这个简单形状的协议。
  • MKOverlayView is used to actually draw the overlay; subclasses exist for each of the above-mentioned simple shapes.
  • MKOverlayView用于实际绘制叠加层;对于每个上述简单形状存在子类。

Sample code:

示例代码:

#3


0  

In the search for a solution for my problem, I keep coming back to this question, and here and also here

在寻找我的问题的解决方案时,我不断回到这个问题,在这里和这里

They were all answering the question I needed answered but in reverse.

他们都在回答我需要回答的问题,但反之亦然。

I needed to determine if a UIView, i.e. a draw square on my MapView contains a map pin, if it does let me know so I can remove it or select it etc.

我需要确定一个UIView,即我的MapView上的绘图方块是否包含地图引脚,如果确实让我知道,那么我可以删除它或选择它等。

Finally after trying to convert my UIView into some MKCoordinateRegion or alike, I thought work backwards. Instead of turning my UIView or square into map madness, I turned the pins into simple CGPoints and did a simple Rect contains point. Which ended up being my solution.. after about 2 hrs!

最后,在尝试将我的UIView转换为某些MKCoordinateRegion或类似之后,我认为向后工作。我没有把我的UIView或方块变成地图疯狂,而是将引脚​​转换成简单的CGPoints并做了一个简单的Rect包含点。最终成为我的解决方案......约2小时后!

Hope this help someone down the line

希望这有助于某人下线

 func findMapPinsWithinBox() {

    guard let myBox = myBox else { return } // some UIView you have drawn or placed on map

    let visibleMapRect = mapView.visibleMapRect
    let visibleAnnotations =  mapView.annotationsInMapRect(visibleMapRect)

    for pin in visibleAnnotations {

        // depending on design you may need to do some casting here
        // ie let pin = pin as! MyMapAnnotation

        let pinsCGPoint = mapView.convertCoordinate(pin.coordinate, toPointToView: self.view)

        if myBox.frame.contains(pinsCGPoint) {
            print("Pin Found within the Box")
            // select pin or delete etc
        }
    }
}

#4


-1  

From just looking at Apple's documentation for the MKOverlay protocol, it doesn't look very complex. Just make a class to do whatever you need to compute the overlay and make sure it conforms to that protocol. That means you must have the coordinate and boundingMapRect properties as well as an implementation for intersectsMapRect:. The Apple docs explain it all.

从仅查看Apple的MKOverlay协议文档来看,它看起来并不复杂。只需创建一个类来完成计算叠加层所需的任何内容,并确保它符合该协议。这意味着您必须具有coordinate和boundingMapRect属性以及intersectsMapRect:的实现。 Apple文档解释了这一切。

Take a look at the HazardMap sample code from Apple. It uses a custom overlay view like you want to do to display an image in the overlay. You simply need to implement mapView:viewForOverlay: in your MKMapViewDelegate class and return a new instance of your subclass of MKOverlayView to get the custom overlay drawn on the screen.

看一下Apple的HazardMap示例代码。它使用您想要的自定义叠加视图来显示叠加层中的图像。您只需在MKMapViewDelegate类中实现mapView:viewForOverlay:并返回MKOverlayView子类的新实例,以获取在屏幕上绘制的自定义叠加层。