Reputation: 46
I have a simple camera view controller and I need to put a circular view in the center of the screen. I tried solutions suggested here Swift - How to create a view with a shape cropped in it but they didn't work. I need something like in the following picture, but blur effect is not necessary: Image link Here's what I tried. It shows the circle, but everything outside is just black:
class CircularCameraViewController: UIViewController {
var captureSession: AVCaptureSession!
var capturePhotoOutput: AVCapturePhotoOutput!
override func viewDidLoad() {
super.viewDidLoad()
setupCamera()
setupPhotoOutput()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
captureSession.startRunning()
}
override func viewWillDisappear(_ animated: Bool) {
captureSession.stopRunning()
}
private func setupCamera() {
let maskLayer = CALayer()
maskLayer.frame = view.bounds
let circleLayer = CAShapeLayer()
circleLayer.frame = CGRect(x: view.center.x - 100, y: view.center.y - 100, width: 200, height: 200)
let circlePath = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 200, height: 200))
circleLayer.path = circlePath.cgPath
circleLayer.fillColor = UIColor.black.cgColor
maskLayer.addSublayer(circleLayer)
view.layer.mask = maskLayer
let captureDevice = AVCaptureDevice.default(for: AVMediaType.video)
var input: AVCaptureDeviceInput
do {
input = try AVCaptureDeviceInput(device: captureDevice!)
} catch {
fatalError("Error configuring capture device: \(error)");
}
captureSession = AVCaptureSession()
captureSession.addInput(input)
// Setup the preview view.
let videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
videoPreviewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
videoPreviewLayer.frame = view.layer.bounds
view.layer.addSublayer(videoPreviewLayer)
}
private func setupPhotoOutput() {
capturePhotoOutput = AVCapturePhotoOutput()
capturePhotoOutput.isHighResolutionCaptureEnabled = true
captureSession.addOutput(capturePhotoOutput!)
}
}
Upvotes: 0
Views: 1579
Reputation: 46
I ended up using this solution https://stackoverflow.com/a/60667169/12411655
After adding AVCaptureVideoPreviewLayer to your view's layer, add a CAShapeLayer() like this:
let camPreviewBounds = view.bounds
cropRect = CGRect(
x: camPreviewBounds.minX + (camPreviewBounds.width - 150) * 0.5,
y: camPreviewBounds.minY + (camPreviewBounds.height - 150) * 0.5,
width: 150,
height: 150
)
let path = UIBezierPath(roundedRect: camPreviewBounds, cornerRadius: 0)
path.append(UIBezierPath(ovalIn: cropRect))
let layer = CAShapeLayer()
layer.path = path.cgPath
layer.fillRule = CAShapeLayerFillRule.evenOdd;
layer.fillColor = UIColor.black.cgColor
layer.opacity = 0.5;
view.layer.addSublayer(layer)
Upvotes: 1