首页 > 解决方案 > 添加一个 CAShapeLayer 很快就会越界

问题描述

我正在尝试向我的 previewLayer 添加一个暗视图,除了我的 rectOfInterest,这是我的代码。videoPreviewLayer 是我的 AVCaptureVideoPreviewLayer 和 qrCodeFrameView 是我的 rectOfInterest

let path = CGMutablePath()
        qrCodeView.clipsToBounds = true
        view.clipsToBounds = true
        path.addRect(videoPreviewLayer!.bounds)
        path.addRect(qrCodeFrameView.frame)

        let maskLayer = CAShapeLayer()
        maskLayer.path = path
        maskLayer.fillColor = UIColor.black.withAlphaComponent(0.6).cgColor
        maskLayer.fillRule = .evenOdd

        videoPreviewLayer?.addSublayer(maskLayer) 

在此处输入图像描述

但我明白了我怎样才能让 rect 保持绑定?

标签: swiftavfoundationcashapelayer

解决方案


这有点像在黑暗中拍摄。但最有可能的问题是您的视图改变了位置,而添加掩码的代码没有。

假设您当前有以下代码:

func applyMask() {
    let path = CGMutablePath()
    qrCodeView.clipsToBounds = true
    view.clipsToBounds = true
    path.addRect(videoPreviewLayer!.bounds)
    path.addRect(qrCodeFrameView.frame)

    let maskLayer = CAShapeLayer()
    maskLayer.path = path
    maskLayer.fillColor = UIColor.black.withAlphaComponent(0.6).cgColor
    maskLayer.fillRule = .evenOdd

    videoPreviewLayer?.addSublayer(maskLayer) 
}

func viewDidLoadOrSomeOtherInitKindOfMethod() {
    applyMask()
}

然后你只需要升级到

let maskLayer: CAShapeLayer?

func applyMask() {
    self.maskLayer?.removeFromSuperlayer()

    let path = CGMutablePath()
    qrCodeView.clipsToBounds = true
    view.clipsToBounds = true
    path.addRect(videoPreviewLayer!.bounds)
    path.addRect(qrCodeFrameView.frame)

    let maskLayer = CAShapeLayer()
    maskLayer.path = path
    maskLayer.fillColor = UIColor.black.withAlphaComponent(0.6).cgColor
    maskLayer.fillRule = .evenOdd

    videoPreviewLayer?.addSublayer(maskLayer) 
    
    self.maskLayer = maskLayer
}

// Relevant if doing this in view controller:
open override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    applyMask()
}

// Relevant if doing this in UIView using auto-layout
override func layoutSubviews() {
    super.layoutSubviews()
    applyMask()
}
    
// Relevant if doing this in UIView using manual setting of frame
override var frame: CGRect {
    didSet {
        applyMask()
    }
}

这里的关键是每次视图更改位置时重新创建蒙版。在重新创建掩码之前,需要保留和移除掩码。然后只需在更改视图大小的方法中调用应用掩码。


推荐阅读