2012-04-27 14 views
5

Mi chiedo se ci sia un modo per configurare le nostre mappe MapKit come facciamo con l'oggetto MapTypeStyle nell'API di Google Maps.MapTypeStyle in MapKit

Se mi riferisco ad Apple doc, MKMapView ha un'opzione maptype che prende MKMapType constant ma nessun parametro stili come MapOptions con la MapTypeStyle e wich MapTypeStyler è molto potente per le mappe veloci personalizzazione.

Quindi la mia domanda è: c'è un modo per ottenere qualcosa di simile con il framework MapKit, se no, qual è il miglior framework/libreria per fare questo? Sto pensando a MapBox e prodotti simili.

+0

È possibile modificare i colori di MKMapView modificando una classe privata, ma sono abbastanza sicuro che Apple non consentirà Questo . Se sei comunque interessato a questa opzione, ti posterò un codice di esempio. –

+0

Sarebbe bello da vedere! –

+1

@Lee Armstrong ho aggiunto un breve codice di esempio –

risposta

3

Ci sono alcune opzioni per te, amico mio. Si potrebbe utilizzare uno di questi quadri

http://cloudmade.com/products/iphone-sdk

https://github.com/route-me/route-me

Oppure si potrebbe usare mapbox. La loro api sembra piuttosto buona. In alternativa si forniscono le tessere della mappa e il mapkit overlay. Qualcosa di simile a questo in un MKOverlayView

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

NSURL* fileURL = [(HeatMap*)self.overlay localUrlForStyle:@"alien" withMapRect:mapRect andZoomScale:zoomScale]; 
NSData *imageData = [NSData dataWithContentsOfURL:fileURL ]; 
if (imageData != nil) { 
    UIImage* img = [UIImage imageNamed:@"aTileX.png"]; 
    // Perform the image render on the current UI context 
    UIGraphicsPushContext(context); 
    [img drawInRect:[self rectForMapRect:mapRect] blendMode:kCGBlendModeNormal alpha:1.0]; 
    UIGraphicsPopContext(); 
    } 
} 

verificare anche questo se si vuole "terreno" non supportato modalità http://openradar.appspot.com/9621632

In realtà sono nel bel mezzo di un programma che richiede sovrapposizione di piastrelle su una mappa. This example è stato molto utile. Dovrai esaminare MKOverlay e MKOverlayView. Il progetto che sto facendo prevede l'utilizzo di gheat. Sto accedendo alle tessere attraverso un NSURLConnection e li memorizzo localmente. A gist della mia implementazione.

+0

L'opzione tessere personalizzate sembra essere l'approccio migliore nel mio caso, in quanto la mia mappa è limitata a un limite di città, con pochi livelli di zoom. Lo scaverò, se c'è un modo per immagazzinare le tessere localmente, probabilmente userò questa soluzione per la produzione. Puoi aggiungere altre informazioni/link sulla sovrapposizione nella tua risposta, quindi contrassegno questa domanda come accettata? Grazie mille. – rayfranco

2

Non c'è modo di personalizzare gli stili di mappa in modo nativo con mapkit. L'unica opzione per questo è optare per un approccio di app ibrido e quindi personalizzare gli stili utilizzando html/javascript nella pagina stessa.

+0

Questa è una soluzione intelligente e semplice, ma non una che posso usare nel mio caso. Ho upvoted in modo che le persone possano vedere questa soluzione che può adattarsi alle esigenze di qualcun altro. – rayfranco

2

Poiché il disegno delle tessere avviene in una classe privata denominata MKMapTileView, non è possibile scrivere semplicemente una categoria. Devi implementare un'altra classe per il disegno personalizzato. I metodi di questa classe saranno utilizzati per sovraccaricare l'attuazione di MKMapTileView durante il runtime:

file di intestazione:

@interface MyColorMap : NSObject 
+ (void)overLoadMethods:(Class)destinationClass; 
@end 

Imlementation:

#import "MyColorMap.h" 
#import <objc/runtime.h> 

@implementation MyColorMap 

+ (void)overLoadMethods:(Class)destinationClass { 
    // get the original method for drawing a tile 
    Method originalDrawLayer = class_getInstanceMethod(destinationClass, @selector(drawLayer:inContext:)); 

    // get the method we will replace with the original implementation of 'drawLayer:inContext:' later 
    Method backupDrawLayer = class_getInstanceMethod([self class], @selector(backupDrawLayer:inContext:)); 

    // get the method we will use to draw our own colors 
    Method myDrawLayer = class_getInstanceMethod([self class], @selector(myDrawLayer:inContext:)); 

    // dito with the implementations 
    IMP impOld = method_getImplementation(originalDrawLayer); 
    IMP impNew = method_getImplementation(myDrawLayer); 

    // replace the original 'drawLayer:inContext:' with our own implementation 
    method_setImplementation(originalDrawLayer, impNew); 

    // set the original 'drawLayer:inContext:' implementation to our stub-method, so wie can call it later on 
    SEL selector = method_getName(backupDrawLayer); 
    const char *types = method_getTypeEncoding(backupDrawLayer); 
    class_addMethod(destinationClass, selector, impOld, types); 
} 


- (void)backupDrawLayer:(CALayer*)l inContext:(CGContextRef)c { 
    // stub method, implementation will never be called. The only reason we implement this is so we can call the original method durring runtime 
} 

- (void)myDrawLayer:(CALayer*)l inContext:(CGContextRef)c { 
    // set background to white so wie can use it for blendmode 
    CGContextSetFillColorWithColor(c, [[UIColor whiteColor] CGColor]); 
    CGContextFillRect(c, CGContextGetClipBoundingBox(c)); 

    // set blendmode so the map will show as grayscale 
    CGContextSetBlendMode(c, kCGBlendModeLuminosity); 
    // kCGBlendModeExclusion for inverted colors etc. 

    // calling the stub-method which will become the original method durring runtime 
    [self backupDrawLayer:l inContext:c]; 

    // if you want more advanced manipulations you can alter the context after drawing: 

// int w = CGBitmapContextGetWidth(c); 
// int h = CGBitmapContextGetHeight(c); 
//  
// unsigned char* data = CGBitmapContextGetData(c); 
// if (data != NULL) { 
//  int maxY = h; 
//  for(int y = 0; y<maxY; y++) { 
//   for(int x = 0; x<w; x++) { 
//     
//    int offset = 4*((w*y)+x); 
//    char r = data[offset]; 
//    char g = data[offset+1]; 
//    char b = data[offset+2]; 
//    char a = data[offset+3]; 
//     
//    // do what ever you want with the pixels 
//     
//    data[offset] = r; 
//    data[offset+1] = g; 
//    data[offset+2] = b; 
//    data[offset+3] = a; 
//   } 
//  } 
// } 
} 

ora si deve chiamare [MyColorMap overLoadMethods:NSClassFromString(@"MKMapTileView")] ad un certo punto, prima utilizzando un MKMapView

+0

Questo sembra un trucco profondo per un'esigenza così semplice :) Probabilmente userò la sovrapposizione (vedi @ risposta jb1a1) poiché non vedo il vantaggio dell'utilizzo della soluzione. Ancora una buona cosa sapere. Grazie per aver condiviso questo esempio. Hope MapKit si aggiornerà presto e ci permetterà di personalizzare le mappe in modo JS. – rayfranco

+0

Questo non sembra funzionare con il controllo MKMapView di iOS 6. Forse questa versione non usa "MKMapTileView"? –

+0

in iOS 6 la mappa è completamente refactored. La maggior parte del nuovo rendering utilizza openGL e questo hack non funziona più. –

Problemi correlati