如何在 UIVisualEffectView 中打一个透明孔?
How to make a transparent hole in UIVisualEffectView?
我有一个简单的 UIViewController,其中 UIVisualEffectView 使用 overCurrentContext
在另一个控制器上显示。
还好。
现在我尝试通过以下方式在该视图中打一个洞:
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
}
}
但是效果却出乎我的意料,为什么?
我需要周围的一切都像矩形当前那样模糊。而且里面的rect应该是透明的。
编辑::
我研究了下面的评论,并尝试了另一个答案,但结果还是一样。为什么?;)我不知道哪里出了问题。
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
}
好吧,我测试了您的代码,并且扩展中带有 makeClearHole 函数的原始代码工作正常!问题出在其他地方。
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- 在您的视图控制器中为 coverView 提供框架
您拥有的视图控制器不同。但是你应该给 CoverView 实例一个框架。这是这样的:(同样,这是我测试的方式,但你的视图控制器肯定不同)
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)
}
}
}
** 结果**
我有一个简单的 UIViewController,其中 UIVisualEffectView 使用 overCurrentContext
在另一个控制器上显示。
还好。
现在我尝试通过以下方式在该视图中打一个洞:
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
}
}
但是效果却出乎我的意料,为什么?
我需要周围的一切都像矩形当前那样模糊。而且里面的rect应该是透明的。
编辑::
我研究了下面的评论,并尝试了另一个答案,但结果还是一样。为什么?;)我不知道哪里出了问题。
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
}
好吧,我测试了您的代码,并且扩展中带有 makeClearHole 函数的原始代码工作正常!问题出在其他地方。
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- 在您的视图控制器中为 coverView 提供框架 您拥有的视图控制器不同。但是你应该给 CoverView 实例一个框架。这是这样的:(同样,这是我测试的方式,但你的视图控制器肯定不同)
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)
}
}
}
** 结果**