CameraPreview.swift (3133B)
1 // 2 // CameraPreview.swift 3 // damus 4 // 5 // Created by Suhail Saqan on 8/5/23. 6 // 7 8 import UIKit 9 import AVFoundation 10 import SwiftUI 11 12 public struct CameraPreview: UIViewRepresentable { 13 public class VideoPreviewView: UIView { 14 public override class var layerClass: AnyClass { 15 AVCaptureVideoPreviewLayer.self 16 } 17 18 var videoPreviewLayer: AVCaptureVideoPreviewLayer { 19 return layer as! AVCaptureVideoPreviewLayer 20 } 21 22 let focusView: UIView = { 23 let focusView = UIView(frame: CGRect(x: 0, y: 0, width: 30, height: 30)) 24 focusView.layer.borderColor = UIColor.white.cgColor 25 focusView.layer.borderWidth = 1.5 26 focusView.layer.cornerRadius = 15 27 focusView.layer.opacity = 0 28 focusView.backgroundColor = .clear 29 return focusView 30 }() 31 32 @objc func focusAndExposeTap(gestureRecognizer: UITapGestureRecognizer) { 33 let layerPoint = gestureRecognizer.location(in: gestureRecognizer.view) 34 35 guard layerPoint.x >= 0 && layerPoint.x <= bounds.width && 36 layerPoint.y >= 0 && layerPoint.y <= bounds.height else { 37 return 38 } 39 40 let devicePoint = videoPreviewLayer.captureDevicePointConverted(fromLayerPoint: layerPoint) 41 42 self.focusView.layer.frame = CGRect(origin: layerPoint, size: CGSize(width: 30, height: 30)) 43 44 NotificationCenter.default.post(.init(name: .init("UserDidRequestNewFocusPoint"), object: nil, userInfo: ["devicePoint": devicePoint] as [AnyHashable: Any])) 45 46 UIView.animate(withDuration: 0.3, animations: { 47 self.focusView.layer.opacity = 1 48 }) { (completed) in 49 if completed { 50 UIView.animate(withDuration: 0.3) { 51 self.focusView.layer.opacity = 0 52 } 53 } 54 } 55 } 56 57 public override func layoutSubviews() { 58 super.layoutSubviews() 59 60 videoPreviewLayer.videoGravity = .resizeAspectFill 61 62 self.layer.addSublayer(focusView.layer) 63 64 let gRecognizer = UITapGestureRecognizer(target: self, action: #selector(VideoPreviewView.focusAndExposeTap(gestureRecognizer:))) 65 self.addGestureRecognizer(gRecognizer) 66 } 67 } 68 69 public let session: AVCaptureSession 70 71 public init(session: AVCaptureSession) { 72 self.session = session 73 } 74 75 public func makeUIView(context: Context) -> VideoPreviewView { 76 let viewFinder = VideoPreviewView() 77 viewFinder.backgroundColor = .black 78 viewFinder.videoPreviewLayer.cornerRadius = 20 79 viewFinder.videoPreviewLayer.session = session 80 viewFinder.videoPreviewLayer.connection?.videoOrientation = .portrait 81 82 return viewFinder 83 } 84 85 public func updateUIView(_ uiView: VideoPreviewView, context: Context) { 86 87 } 88 } 89 90 struct CameraPreview_Previews: PreviewProvider { 91 static var previews: some View { 92 CameraPreview(session: AVCaptureSession()) 93 .frame(height: 300) 94 } 95 }