【问题标题】:How to add a rectangle mask inside the camera custom view in swift?如何快速在相机自定义视图中添加矩形蒙版?
【发布时间】:2023-03-19 01:06:01
【问题描述】:

我有一个自定义视图,我将其添加为相机层顶部的视图。

我只想捕捉一张适合矩形的图片。但是我不知道如何将该矩形添加为相机层内的透明蒙版。

任何建议或代码 sn-ps 将不胜感激!

【问题讨论】:

  • 您可能有兴趣阅读有关 AVCaptureMetadataOutputObjectsDelegate 的信息,这里有一个教程,其中一个绿色框显示在 QR 码周围:appcoda.com/barcode-reader-swift
  • @DevB2F 我看过这个教程,但它对实现我想要的没有那么有帮助

标签: ios swift user-interface layout camera


【解决方案1】:

这是带有圆角和边框的矩形掩码

var overlay: UIView = UIView()

func createOverlay() -> UIView {
    
    let overlayView = UIView(frame: view.frame)
    overlayView.backgroundColor = UIColor.black.withAlphaComponent(0.4)



    let path = CGMutablePath()

    path.addRoundedRect(in: CGRect(x: 15, y: overlayView.center.y-100, width: overlayView.frame.width-30, height: 200), cornerWidth: 5, cornerHeight: 5)

    
    path.closeSubpath()
    
    let shape = CAShapeLayer()
    shape.path = path
    shape.lineWidth = 3.0
    shape.strokeColor = UIColor.blue.cgColor
    shape.fillColor = UIColor.blue.cgColor
    
    overlayView.layer.addSublayer(shape)
    
    path.addRect(CGRect(origin: .zero, size: overlayView.frame.size))

    let maskLayer = CAShapeLayer()
    maskLayer.backgroundColor = UIColor.black.cgColor
    maskLayer.path = path
    maskLayer.fillRule = CAShapeLayerFillRule.evenOdd

    overlayView.layer.mask = maskLayer
    overlayView.clipsToBounds = true
    
    return overlayView
}

func addTransparentOverlayWithCirlce(){
    overlay = createOverlay()
    view.addSubview(overlay)
    self.view.sendSubviewToBack(overlay)
}

【讨论】:

    【解决方案2】:

    为方便起见,我在 viewDidLoad 方法中实现了这一点,并使用了圆形而不是矩形。我也在解决你提到的问题;

    但是我不知道如何将该矩形添加为透明 相机层内的蒙版。

    这是我的完整代码。

    import UIKit
    import AVFoundation
    
    class ViewController: UIViewController {
    
        @IBOutlet weak var cameraPreviewView: UIView!
        @IBOutlet weak var overlayView: UIView!
    
        var session: AVCaptureSession?
        var stillImageOutput: AVCapturePhotoOutput?
        var videoPreviewLayer: AVCaptureVideoPreviewLayer?
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            session = AVCaptureSession()
            session?.sessionPreset = AVCaptureSession.Preset.photo
    
            let backCamera =  AVCaptureDevice.default(for: AVMediaType.video)
            var error: NSError?
            var input: AVCaptureDeviceInput!
    
            do {
                input = try AVCaptureDeviceInput(device: backCamera!)
            } catch let error1 as NSError {
                error = error1
                input = nil
            }
    
            if error == nil && (session?.canAddInput(input))! {
                session?.addInput(input)
                stillImageOutput = AVCapturePhotoOutput()
            }
    
            if (session?.canAddOutput(stillImageOutput!))! {
                session?.addOutput(stillImageOutput!)
                videoPreviewLayer = AVCaptureVideoPreviewLayer(session: session!)
                videoPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspect
                videoPreviewLayer?.connection?.videoOrientation = AVCaptureVideoOrientation.portrait
                cameraPreviewView.layer.addSublayer(videoPreviewLayer!)
                session?.startRunning()
    
                // I'm adding a circle not a rectangle. Make that adjustment in your code.
                let radius : CGFloat = 50.0
                let xOffset : CGFloat = 100 //  Position according to your wish
                let yOffset : CGFloat = 100 //  Position according to your wish
    
                let path = CGMutablePath()
    
                path.addArc(center: CGPoint(x: xOffset, y: yOffset),
                            radius: radius,
                            startAngle: 0.0,
                            endAngle: 2.0 * .pi,
                            clockwise: false)
    
                path.addRect(CGRect(origin: .zero, size: overlayView.frame.size))
    
                let maskLayer = CAShapeLayer()
                maskLayer.backgroundColor = UIColor.black.cgColor
                maskLayer.path = path
                maskLayer.fillRule = .evenOdd
    
                overlayView.layer.mask = maskLayer
                overlayView.clipsToBounds = true
            }
        }
    
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
            videoPreviewLayer?.frame = cameraPreviewView.bounds
        }
    }
    

    确保在您的 info.plist 文件中添加隐私 - 相机使用说明

    【讨论】:

      【解决方案3】:

      我实现了@Sasha 的答案,以便在自定义相机中使用。下面是我创建蒙版的函数。

       func createOverlay() -> UIView {
              
              let overlayView = UIView(frame: view.frame)
              overlayView.backgroundColor = UIColor.black.withAlphaComponent(0.7)
      
      
      
              let path = CGMutablePath()
      
              path.addRoundedRect(in: CGRect(x: 50, y: 100, width: overlayView.frame.width-100, height: overlayView.frame.height - 300), cornerWidth: 5, cornerHeight: 5)
      
              
              path.closeSubpath()
              
              let shape = CAShapeLayer()
              shape.path = path
              shape.lineWidth = 5.0
              shape.strokeColor = UIColor.white.cgColor
              shape.fillColor = UIColor.white.cgColor
              
              overlayView.layer.addSublayer(shape)
              
              path.addRect(CGRect(origin: .zero, size: overlayView.frame.size))
      
              let maskLayer = CAShapeLayer()
              maskLayer.backgroundColor = UIColor.black.cgColor
              maskLayer.path = path
              maskLayer.fillRule = CAShapeLayerFillRule.evenOdd
      
              overlayView.layer.mask = maskLayer
              overlayView.clipsToBounds = true
              
              return overlayView
          }

      我使用此功能将它添加到我的自定义相机预览层:

          func setupPreviewLayer()
          {
              self.cameraPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
              self.cameraPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
              self.cameraPreviewLayer?.connection?.videoOrientation = AVCaptureVideoOrientation.portrait
              self.cameraPreviewLayer?.frame = self.view.bounds
              self.view.layer.insertSublayer(cameraPreviewLayer!, at: 0)
              let overlay = createOverlay()
              self.view.addSubview(overlay)
          }

      最终产品如下所示: Object Detection Frame

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-09-18
        • 2020-07-06
        • 1970-01-01
        • 2017-07-01
        • 1970-01-01
        • 2017-05-18
        • 2014-07-20
        相关资源
        最近更新 更多