2012-01-29 11 views
8

Aggiungere invertito cerchio sovrapposizione alla cartina

Ho seguito le istruzioni qui (utilizzando iOS 5 e Xcode 4.2.): http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/LocationAwarenessPG/AnnotatingMaps/AnnotatingMaps.html#//apple_ref/doc/uid/TP40009497-CH6-SW15 e utilizzato le classi MKCircle e MKCircleView per aggiungere un cerchio sovrapposizione sulla mia MKMapView.

Tuttavia quello che realmente voglio è un cerchio di sovrapposizione rovesciata, come la mappa a sinistra nel disegno qui sotto (attualmente ho una sovrapposizione cerchio come quella a destra):

Inverted and not-inverted circle overlay sketches

Per la invertita Cerchio, la sovrapposizione dovrebbe coprire l'intera mappa, a parte il cerchio visibile.

Esiste un modo semplice per eseguire ciò utilizzando le classi MKCircle/MKCircleView? O dovrò andare più in profondità e definire un oggetto/vista sovrapposto personalizzato?

Grazie per il vostro aiuto :)

risposta

5

Il modo migliore per farlo, sarebbe quella di sottoclasse MKMapView e ignorare la chiamata super-drawRect metodo, poi dipingere sopra la mappa con il colore che si desidera. Quindi ogni volta che l'utente si sposta, drawRect dovrebbe rispondere disegnando in modo appropriato.

+0

Potete per favore suggerire come o che cosa hai scritto nel metodo drawRect? – HarshIT

+0

La pittura su tutta la mappa farà anche l'area tra i dipinti, ma non la vuole. Come la risposta è accettata? –

6

Ho avuto lo stesso compito e ecco come ho risolto:

NOTA: questo codice funziona solo a partire dal iOS7

Aggiungi un overlay alla mappa, da qualche parte nel vostro controller della vista:

MyMapOverlay *overlay = [[MyMapOverlay alloc] initWithCoordinate:coordinate]; 
[self.mapView addOverlay:overlay level:MKOverlayLevelAboveLabels]; 

Nei metodi MKMapViewDelegate scrivere accanto:

- (MKOverlayRenderer *)mapView:(MKMapView *)map rendererForOverlay:(id<MKOverlay>)overlay { 
    /// we need to draw overlay on the map in a way when everything except the area in radius of 500 should be grayed 
    /// to do that there is special renderer implemented - NearbyMapOverlay 
    if ([overlay isKindOfClass:[NearbyMapOverlay class]]) { 
     MyMapOverlayRenderer *renderer = [[MyMapOverlayRenderer alloc] initWithOverlay:overlay]; 
     renderer.fillColor = [UIColor whateverColor];/// specify color which you want to use for gray out everything out of radius 
     renderer.diameterInMeters = 1000;/// choose whatever diameter you need 

     return renderer; 
    } 
    return nil; 
} 
.210

Il MyMapOverlay sé dovrebbe essere qualcosa come seguito:

@interface MyMapOverlay : NSObject<MKOverlay> 
- (instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate; 
@end 

@implementation MyMapOverlay 

@synthesize coordinate = _coordinate; 

- (instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate { 
    self = [super init]; 
    if (self) { 
     _coordinate = coordinate; 
    } 
    return self; 
} 

- (MKMapRect)boundingMapRect { 
    return MKMapRectWorld; 
} 

@end 

E il MyMapOverlayRenderer:

@interface MyMapOverlayRenderer : MKOverlayRenderer 
@property (nonatomic, assign) double diameterInMeters; 
@property (nonatomic, copy) UIColor *fillColor; 
@end 

@implementation MyMapOverlayRenderer 

/// this method is called as a part of rendering the map, and it draws the overlay polygon by polygon 
/// which means that it renders overlay by square pieces 
- (void)drawMapRect:(MKMapRect)mapRect 
     zoomScale:(MKZoomScale)zoomScale 
     inContext:(CGContextRef)context { 

    /// main path - whole area 
    UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(mapRect.origin.x, mapRect.origin.y, mapRect.size.width, mapRect.size.height)]; 

    /// converting to the 'world' coordinates 
    double radiusInMapPoints = self.diameterInMeters * MKMapPointsPerMeterAtLatitude(self.overlay.coordinate.latitude); 
    MKMapSize radiusSquared = {radiusInMapPoints, radiusInMapPoints}; 
    MKMapPoint regionOrigin = MKMapPointForCoordinate(self.overlay.coordinate); 
    MKMapRect regionRect = (MKMapRect){regionOrigin, radiusSquared}; //origin is the top-left corner 
    regionRect = MKMapRectOffset(regionRect, -radiusInMapPoints/2, -radiusInMapPoints/2); 
    // clamp the rect to be within the world 
    regionRect = MKMapRectIntersection(regionRect, MKMapRectWorld); 

    /// next path is used for excluding the area within the specific radius from current user location, so it will not be filled by overlay fill color 
    UIBezierPath *excludePath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(regionRect.origin.x, regionRect.origin.y, regionRect.size.width, regionRect.size.height) cornerRadius:regionRect.size.width/2]; 
    [path appendPath:excludePath]; 

    /// setting overlay fill color 
    CGContextSetFillColorWithColor(context, self.fillColor.CGColor); 
    /// adding main path. NOTE that exclusionPath was appended to main path, so we should only add 'path' 
    CGContextAddPath(context, path.CGPath); 
    /// tells the context to fill the path but with regards to even odd rule 
    CGContextEOFillPath(context); 
} 

Di conseguenza si avrà esattamente lo stesso vista come su l'immagine a sinistra che è stato pubblicato nella questione .

Problemi correlati