简体   繁体   English

如何在 UIVisualEffectView 中打一个透明的洞?

[英]How to make a transparent hole in UIVisualEffectView?

I have a simple UIViewController with UIVisualEffectView presented over another controller using overCurrentContext .我有一个简单的 UIViewController ,其中 UIVisualEffectView 使用overCurrentContext呈现在另一个控制器上。

在此处输入图像描述

and it is fine.这很好。

now I try to make a hole inside that view the following way:现在我尝试通过以下方式在该视图内打一个洞:

class CoverView: UIView {
    private let blurView: UIVisualEffectView = {
        UIVisualEffectView(effect: UIBlurEffect(style: .dark))
    }()

    // MARK: - Internal

    func setup() {
        addSubview(blurView)
        blurView.snp.makeConstraints { maker in
            maker.edges.equalToSuperview()
        }
        blurView.makeClearHole(rect: CGRect(x: 100, y: 100, width: 100, height: 230))
    }
}

extension UIView {
    func makeClearHole(rect: CGRect) {
        let maskLayer = CAShapeLayer()
        maskLayer.fillRule = CAShapeLayerFillRule.evenOdd
        maskLayer.fillColor = UIColor.black.cgColor

        let pathToOverlay = UIBezierPath(rect: bounds)
        pathToOverlay.append(UIBezierPath(rect: rect))
        pathToOverlay.usesEvenOddFillRule = true
        maskLayer.path = pathToOverlay.cgPath

        layer.mask = maskLayer
    }
}

But the effect is reversed than I expected, why?但是效果却出乎我的意料,为什么呢?

在此处输入图像描述

I need everything around blurred the way how rectangle currently is.我需要周围的一切都像现在的矩形一样模糊。 And the rect inside should be transparent.里面的矩形应该是透明的。

EDIT::编辑::

I have studied everything from comments below, and tried another answer, but result is still the same.我从下面的评论中研究了所有内容,并尝试了另一个答案,但结果仍然相同。 Why?;) I have no idea what is wrong.为什么?;)我不知道出了什么问题。

private func makeClearHole(rect: CGRect) {
    let maskLayer = CAShapeLayer()
    maskLayer.fillColor = UIColor.black.cgColor

    let pathToOverlay = CGMutablePath()
    pathToOverlay.addRect(blurView.bounds)
    pathToOverlay.addRect(rect)
    maskLayer.path = pathToOverlay
    maskLayer.fillRule = .evenOdd
    blurView.layer.mask = maskLayer
}

Well I tested your code and the original code with makeClearHole function in the extension works fine!好吧,我测试了您的代码,并且在扩展中使用 makeClearHole 函数的原始代码工作正常! The problem lies somewhere else.问题出在其他地方。

1- Change the CoverView as following * 1- 改变 CoverView 如下*

class CoverView: UIView {
    private lazy var blurView: UIVisualEffectView = {
        let bv = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
        bv.frame = bounds
        return bv
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // MARK: - Internal

    func setup() {
        addSubview(blurView)
        blurView.snp.makeConstraints { maker in
            maker.edges.equalToSuperview()
        }
        blurView.makeClearHole(rect: CGRect(x: 100, y: 100, width: 100, height: 230))
    }
}

2- Give a frame to coverView in your view controller The view controller you have is different. 2- 在您的视图控制器中为coverView 提供一个框架您拥有的视图控制器是不同的。 But you should give the CoverView instance a frame.但是你应该给 CoverView 实例一个框架。 This is how: (again, this is how I tested but your view controller is definitely different)这是如何:(再次,这是我测试的方式,但你的视图控制器肯定是不同的)

class ViewController: UIViewController {

    var label: UILabel!
    var coverView: CoverView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        label = UILabel()
        label.text = "HELLO WORLD"
        label.font = UIFont.systemFont(ofSize: 40, weight: .black)
        
        
        coverView = CoverView(frame: CGRect(x: 20, y: 200, width: 300, height: 400))
        
        view.addSubview(label)
        view.addSubview(coverView)
        
        label.snp.makeConstraints { make in
            make.center.equalTo(view)
        }
        
        coverView.snp.makeConstraints { make in
            make.width.equalTo(coverView.bounds.width)
            make.height.equalTo(coverView.bounds.height)
            make.leading.equalTo(view).offset(coverView.frame.minX)
            make.top.equalTo(view).offset(coverView.frame.minY)
        }
    }


}

** Result** ** 结果**

模糊视图内的透明矩形

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM