2015-10-21 18 views
13

Sto tentando di aggiungere un effetto sfocato su una sovrapposizione su una mappa. In realtà ho bisogno dell'effetto sfocatura su un cerchio sulla mappa, il metodo che uso per ottenere non è così importante.Aggiungi cerchio con effetto sfocatura su un MKMapView

Ho una classe che si estende da MKCircleRenderer e volevo aggiungere un effetto sfocatura sulla mappa che copre.

Stavo provando a utilizzare il metodo -fillPath:inContext:, ma la mia ignoranza su Core Graphics e Core Image mi ha portato in nessun posto e sono davvero molto perso su questo problema.

Il mio tentativo era utilizzare il CIFilter e per quello ho bisogno di un CIImage che ho provato a creare dal contesto. Ma non ho trovato alcun modo per creare un CGBitmapContext, CGImage né alcuna altra classe dal contesto. Qualsiasi metodo che ho provato è risultato su NULL senza ulteriori dettagli sul perché. Non riesco a ricordare tutto ciò che ho provato, quindi mi dispiace non aver puntato nulla a riguardo.

La mia classe attualmente implementa uno metodi che non fanno in realtà molto:

- (instancetype)initWithOverlay:(id<MKOverlay>)overlay { 
    if (self = [super initWithOverlay:overlay]) { 
     self.strokeColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1]; 
     self.fillColor = [UIColor colorWithRed:0.4 green:0.2 blue:0.2 alpha:0.1]; 
     self.lineWidth = 1; 
    } 
    return self; 
} 

Un'alternativa potrebbe essere utilizza uno personalizzato MKAnnotation e aggiungere l'effetto di sfocatura sopra la vista con il UIVisualEffectView. La parte difficile con questo approccio è aumentare/diminuire le dimensioni durante lo zoom.

Questo dovrebbe funzionare su iOS 8+

Modifica

In questo caso, la mappa dietro l'interno del cerchio dovrebbe essere offuscata

+0

è possibile fornire uno screenshot di che cosa esattamente si vuole raggiungere? Sfocare la mappa ad eccezione di un cerchio specifico? O solo sfocare un cerchio? Perché è dipendente dallo zoom? – luk2302

+0

Sarebbe meglio se mostri uno screenshot di quello che ti serve –

+0

Sfoca il cerchio. Mi piacerebbe avere un'area coperta da un cerchio sfocato. L'area dovrebbe avere un raggio di un quarto di miglio, quindi se qualcuno esegue lo zoom in/out deve cambiare le sue dimensioni. Aggiungerò presto un'immagine. –

risposta

2

Così ho finito per usare un UIVisualEffectView in cima alla sovrapposizione. Il trucco consisteva nell'usare uno CADisplayLink per mantenere la vista in posizione.

Ecco un esempio di codice che fa il lavoro (ignora alcune cose che dovrebbero essere prese in considerazione quando lo si fa in un'applicazione, come rimuovere il collegamento, tenendo traccia che ciò che viene fatto su viewDidAppear deve essere accoppiato con un lavoro probabilmente simmetrico su viewWillDissapear o qualcosa del genere, potrei usare viewDidLoad, penso, ma lo ha fatto in questo modo durante il test).

#import "ViewController.h" 
#import <MapKit/MapKit.h> 
#import <QuartzCore/QuartzCore.h> 

@interface ViewController() { 
    IBOutlet MKMapView *map; 
    UIView *ov; 
    MKCircle *c; 
    UIVisualEffectView *ev; 
} 

@end 

@implementation ViewController 

- (void)viewDidAppear:(BOOL)animated { 
    [super viewDidAppear:animated]; 

    CLLocationCoordinate2D center = CLLocationCoordinate2DMake(40.7828647,-73.9675438); 
    c = [MKCircle circleWithCenterCoordinate:center radius:1000]; 
    [map addOverlay:c]; 
    MKCoordinateSpan span = MKCoordinateSpanMake(0.07, 0.07); 
    MKCoordinateRegion region = MKCoordinateRegionMake(center, span); 
    region = [map regionThatFits:region]; 
    [map setRegion:region animated:YES]; 

    ov = [[UIView alloc] init]; 
    ov.translatesAutoresizingMaskIntoConstraints = NO; 
    ov.backgroundColor = [UIColor clearColor]; 
    ov.clipsToBounds = YES; 
    ov.layer.borderWidth = 1; 
    ov.layer.borderColor = [UIColor blackColor].CGColor; 
    [map addSubview:ov]; 

    UIBlurEffect *blur = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; 
    ev = [[UIVisualEffectView alloc] initWithEffect:blur]; 
    [ov addSubview:ev]; 

    CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(update:)]; 
    [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; 
} 

- (void)update:(CADisplayLink *)link { 
    ov.frame = [map convertRegion:MKCoordinateRegionForMapRect(c.boundingMapRect) toRectToView:map]; 
    ov.layer.cornerRadius = ov.frame.size.height/2; 
    ev.frame = CGRectMake(0, 0, ov.frame.size.width, ov.frame.size.height); 
} 

@end 

Edit: Schermata

2

Ci sono due modi per farlo quella.

Uno è semplice, è sufficiente utilizzare Immagine.

Potreste trovare le seguenti immagini utili:

enter image description hereenter image description hereenter image description hereenter image description hereenter image description here

e al codice di utilizzarli in viewForAnnotation:

- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation 
{ 
    // ... get the annotation delegate and allocate the MKAnnotationView (annView) 
     if ([annotationDelegate.type localizedCaseInsensitiveCompare:@"NeedsBluePin"] == NSOrderedSame) 
     { 
      UIImage * image = [UIImage imageNamed:@"blue_pin.png"]; 
      UIImageView *imageView = [[[UIImageView alloc] initWithImage:image] autorelease]; 
      [annView addSubview:imageView]; 
     } 
} 

Altro metodo di farlo a livello di codice [fanno cerchio te ]

Questo codice può aiutarti.

import UIKit 
import AddressBook 
import AddressBookUI 
import MapKit 
import CoreLocation 
import MessageUI 
import Social 

class ViewController: UIViewController, ABPeoplePickerNavigationControllerDelegate, MFMailComposeViewControllerDelegate, MKMapViewDelegate { 

    @IBOutlet weak var name: UILabel! 
    @IBOutlet weak var email: UILabel! 
    @IBOutlet weak var photo: UIImageView! 
    @IBOutlet weak var map: MKMapView! 

    let locMan:CLLocationManager=CLLocationManager() 

    // Blurring Code 
    @IBOutlet weak var labelBackground: UIView! 
    var backgroundBlur: UIVisualEffectView! 


    @IBAction func newBFF(sender: AnyObject) { 
     let picker: ABPeoplePickerNavigationController = 
      ABPeoplePickerNavigationController() 
     picker.peoplePickerDelegate = self 
     presentViewController(picker, animated: true, completion: nil) 
    } 

    @IBAction func sendEmail(sender: AnyObject) { 
     var emailAddresses:[String]=[self.email.text!] 
     var mailComposer:MFMailComposeViewController = 
      MFMailComposeViewController() 
     mailComposer.mailComposeDelegate=self; 
     mailComposer.setToRecipients(emailAddresses) 

     presentViewController(mailComposer, animated: true, completion: nil) 
    } 

    func mailComposeController(controller: MFMailComposeViewController!, 
     didFinishWithResult result: MFMailComposeResult, error: NSError!) { 
     dismissViewControllerAnimated(true, completion: nil) 
    } 

    func peoplePickerNavigationController(peoplePicker: ABPeoplePickerNavigationController!, didSelectPerson person: ABRecord!) { 

     let friendName:String = ABRecordCopyValue(person, kABPersonFirstNameProperty).takeRetainedValue() as String as String 
     name.text=friendName 

     let friendAddressSet:ABMultiValueRef = ABRecordCopyValue(person, kABPersonAddressProperty).takeRetainedValue() 

     if ABMultiValueGetCount(friendAddressSet)>0 { 
      let friendFirstAddress: Dictionary = ABMultiValueCopyValueAtIndex(friendAddressSet, 0).takeRetainedValue() as NSDictionary 
      showAddress(friendFirstAddress) 
     } 

     let friendEmailAddresses:ABMultiValueRef = ABRecordCopyValue(person, kABPersonEmailProperty).takeRetainedValue() 

     if ABMultiValueGetCount(friendEmailAddresses)>0 { 
      let friendEmail: String = ABMultiValueCopyValueAtIndex(friendEmailAddresses, 0).takeRetainedValue() as String 
      email.text=friendEmail 
     } 

     if ABPersonHasImageData(person) { 
      photo.image = UIImage(data: ABPersonCopyImageData(person).takeRetainedValue()) 
     } 
    } 

    func showAddress(fullAddress:NSDictionary) { 
     let geocoder: CLGeocoder = CLGeocoder() 
     geocoder.geocodeAddressDictionary(fullAddress, completionHandler: 
      {(placemarks: [AnyObject]!, error: NSError!) -> Void in 
       let friendPlacemark:CLPlacemark = placemarks[0] as CLPlacemark 
       let mapRegion:MKCoordinateRegion = 
        MKCoordinateRegion(center: friendPlacemark.location.coordinate, 
         span: MKCoordinateSpanMake(0.2, 0.2)) 
       self.map.setRegion(mapRegion, animated: true) 
       let mapPlacemark: MKPlacemark = MKPlacemark(placemark: friendPlacemark) 
       self.map.addAnnotation(mapPlacemark) 
     }) 
    } 

    func mapView(aMapView: MKMapView!, 
     viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! { 
      let pinDrop:MKPinAnnotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "myspot") 
      pinDrop.animatesDrop=true 
      pinDrop.canShowCallout=true 
      pinDrop.pinColor=MKPinAnnotationColor.Purple 
      return pinDrop 
    } 

    @IBAction func sendTweet(sender: AnyObject) { 
     let geocoder: CLGeocoder = CLGeocoder() 
     geocoder.reverseGeocodeLocation(map.userLocation.location, completionHandler: 
      {(placemarks: [AnyObject]!, error: NSError!) -> Void in 
       let myPlacemark:CLPlacemark = placemarks[0] as CLPlacemark 
       let tweetText:String = 
        "Hello all - I'm currently in \(myPlacemark.locality)!" 

       let tweetComposer: SLComposeViewController = 
        SLComposeViewController(forServiceType: SLServiceTypeTwitter) 

       if SLComposeViewController.isAvailableForServiceType(SLServiceTypeTwitter) { 
        tweetComposer.setInitialText(tweetText) 
        self.presentViewController(tweetComposer, animated: true, completion: nil) 
       } 
     }) 
    } 


    override func viewDidLoad() { 
     super.viewDidLoad() 
     // Do any additional setup after loading the view, typically from a nib. 
     //let locMan:CLLocationManager=CLLocationManager() 
     locMan.requestWhenInUseAuthorization() 

     let blur: UIBlurEffect = UIBlurEffect(style: UIBlurEffectStyle.Light) 
     backgroundBlur = UIVisualEffectView (effect: blur) 
     backgroundBlur.frame = labelBackground.frame 
     view.insertSubview(backgroundBlur, belowSubview: labelBackground) 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 

    override func preferredStatusBarStyle() -> UIStatusBarStyle { 
     return UIStatusBarStyle.LightContent 
    } 


} 
+1

Forse ho espresso qualcosa di sbagliato, ma sulla modifica è stato detto correttamente. Devo sfocare la mappa dietro il cerchio, non un cerchio che galleggia sulla mappa:/Grazie comunque. –

+1

Anche la vista per l'annotazione ignorerà lo zoom AFAIK. Se eseguo lo zoom in avanti o indietro, la vista mostrerà le stesse dimensioni sullo schermo, ma non in relazione alle cose reali mostrate sulla mappa. –

Problemi correlati