【问题标题】:Add circle with blur effect on a MKMapView在 MKMapView 上添加具有模糊效果的圆圈
【发布时间】:2015-10-21 16:03:20
【问题描述】:

我正在尝试在地图上的叠加层上添加模糊效果。我实际上需要在地图上的一个圆圈上进行模糊效果,我用来获得的方法并不那么重要。

我有一个扩展自 MKCircleRenderer 的类,我想在它所覆盖的地图上添加模糊效果。

我尝试使用 -fillPath:inContext: 方法,但我对 Core Graphics 和 Core Image 的无知导致我一无所获,我真的对这个问题感到迷茫。

我的尝试是使用CIFilter,为此我需要一个CIImage,我试图从上下文中创建它。但我发现无法从上下文中创建CGBitmapContextCGImage 或任何其他类。我尝试的任何方法都导致 NULL 没有关于原因的更多细节。我不记得我尝试过的所有内容,所以很抱歉没有指出任何相关内容。

我的班级目前实现了一种并没有太多作用的方法:

- (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;
}

另一种方法是使用自定义MKAnnotation 并使用UIVisualEffectView 在视图上添加模糊效果。这种方法的难点在于缩放时增加/减小大小。

这应该适用于 iOS 8+

编辑

在这种情况下,圆圈内部后面的地图应该是模糊的

【问题讨论】:

  • 您能否提供您想要实现的目标的屏幕截图?模糊除特定圆圈之外的地图?还是只模糊一个圆圈?为什么它依赖于缩放?
  • 最好能截图显示你需要的东西
  • 模糊圆圈。我想要一个被模糊圆圈覆盖的区域。该区域应该有四分之一英里的半径,所以如果有人放大/缩小它必须改变它的大小。我很快就会添加图片。

标签: ios mkmapview core-graphics mapkit core-image


【解决方案1】:

所以我最终在叠加层顶部使用了UIVisualEffectView。诀窍在于使用CADisplayLink 来保持视图到位。

这是一些完成这项工作的代码示例(它忽略了在应用程序上实际执行此操作时应考虑的一些事项,例如删除链接、跟踪在 viewDidAppear 上完成的操作必须与可能对 viewWillDissapear 或其他东西进行对称工作,我认为我可以使用 viewDidLoad,但在测试时这样做了)。

#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

编辑:截图

【讨论】:

    【解决方案2】:

    有两种方法可以做到这一点。

    一个很简单,你可以使用Image。

    您可能会发现以下图片很有用:

    以及在 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];
            }
    }
    

    其他方法以编程方式执行此操作 [自己制作圆圈]

    此代码可以帮助您。

    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
        }
    
    
    }
    

    【讨论】:

    • 也许我表达的有问题,但在编辑上说得对。我需要模糊圆圈后面的地图,而不是漂浮在地图上的圆圈:/ 无论如何,谢谢。
    • 注释视图也将忽略缩放 AFAIK。如果我放大或缩小视图将在屏幕上显示相同的大小,但与地图上显示的实际内容无关。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-30
    • 2015-07-13
    • 2016-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多