带有遮罩层的 UIVisualEffectView

UIVisualEffectView with mask layer

我正在尝试模糊 MKMapView,同时还在其上方显示一个圆形遮罩。为了更好地形象化我的意思,您可以附上我当前状态的图像:

这几乎显示了我想要的内容,但背景(地图)应该是模糊的,而这张照片中的情况并非如此。我尝试使用 UIVisualEffectView,但似乎我在那里做错了什么。这是我尝试过的:

func createOverlay(at: CGPoint) {
    var blur: UIView!
    blur = UIVisualEffectView (effect: UIBlurEffect (style: UIBlurEffectStyle.dark))

    blur.frame = self.mapView.frame
    blur.isUserInteractionEnabled = false
    self.mapView.addSubview(blur)

    let circleSize: CGFloat = 200

    let path = UIBezierPath (
        roundedRect: blur.frame,
        cornerRadius: 0)

    let circle = UIBezierPath (
        roundedRect: CGRect (origin: CGPoint(x:at.x - circleSize/2, y: at.y-circleSize/2),
                             size: CGSize (width: circleSize, height: circleSize)), cornerRadius: circleSize/2)

    path.append(circle)
    path.usesEvenOddFillRule = true

    let maskLayer = CAShapeLayer()
    maskLayer.path = path.cgPath
    maskLayer.fillRule = kCAFillRuleEvenOdd

    let borderLayer = CAShapeLayer()
    borderLayer.path = circle.cgPath
    borderLayer.strokeColor = UIColor.white.cgColor
    borderLayer.lineWidth = 10
    blur.layer.addSublayer(borderLayer)

    blur.layer.mask = maskLayer
}

总结一下我的问题: 如何更改我的代码才能模糊地图视图并在其上方显示圆圈掩码?

编辑 刚发现如果我删除添加圆形遮罩的代码,地图视图的模糊会起作用...也许这对解决这个问题有任何好处。

经过一番研究,我现在找到了解决方案。我假设您使用的是 Xcode 8,因为 layer.mask 有一个已知错误,您不能在同一层上同时使用模糊和蒙版。

在弄乱了 playground 之后,我已经解决了这个问题,因此将尝试调整您的代码以匹配我的解决方案。如果您改用 blurView 的 "mask" 属性,那么应该没有问题。我相信已经向 Apple 提交了关于 layer.mask 不工作

的错误报告

最后是您当前的代码

let maskLayer = CAShapeLayer()
maskLayer.path = path.cgPath
maskLayer.fillRule = kCAFillRuleEvenOdd

let borderLayer = CAShapeLayer()
borderLayer.path = circle.cgPath
borderLayer.strokeColor = UIColor.white.cgColor
borderLayer.lineWidth = 10
blur.layer.addSublayer(borderLayer)

blur.layer.mask = maskLayer

而不是这个,尝试使用以下内容:

let maskLayer = CAShapeLayer()
maskLayer.path = path.cgPath
maskLayer.fillRule = kCAFillRuleEvenOdd

let borderLayer = CAShapeLayer()
borderLayer.path = circle.cgPath
borderLayer.strokeColor = UIColor.white.cgColor
borderLayer.fillColor = UIColor.clear.cgColor //Remember this line, it caused me some issues
borderLayer.lineWidth = 10

let maskView = UIView(frame: self.view.frame)
maskView.backgroundColor = UIColor.black
maskView.layer.mask = maskLayer

blur.layer.addSublayer(borderLayer)
blur.mask = maskView

如果您有任何问题,请告诉我!

除了 Jack 的解决方案之外,如果您在 iOS >11 上,则只需将 blur.layer.mask 设置为 maskLayer:

if #available(iOS 11.0, *) {
    blur.layer.mask = maskLayer
} else {
    let maskView = UIView(frame: self.view.frame)
    maskView.backgroundColor = UIColor.black
    maskView.layer.mask = borderLayer
    blur.mask = maskView
}