AVFoundation tap to focus feedback rectangle

后端 未结 5 571
执笔经年
执笔经年 2021-01-30 07:22

I am developing an iphone application where I directly use AVFoundation to capture videos via the camera.

I\'ve implemented a feature to enable the tap to focus

5条回答
  •  后悔当初
    2021-01-30 07:58

    Here's a basic Swift view that will show an animated focus square. Just add it to your camera view and hook it up to the focus callback from a tap gesture recognizer.

    @objc func didTapToFocus(gesture: UITapGestureRecognizer) {
        let pointInViewCoordinates = gesture.location(in: gesture.view)
        let pointInCameraCoordinates = cameraView.videoPreviewLayer.captureDevicePointConverted(fromLayerPoint: pointInViewCoordinates)
        camera.focusOn(pointInCameraCoordinates: pointInCameraCoordinates)
        cameraView.showFocusBox(at: pointInViewCoordinates)
    }
    

    Focus view:

    final class CameraFocusBoxView: UIView {
    
        // MARK: - Instantiation
    
        init() {
            super.init(frame: .zero)
    
            backgroundColor = .clear
            layer.addSublayer(focusBoxLayer)
        }
    
        // MARK: - API
    
        /// This zooms/fades in a focus square and blinks it a few times, then slowly fades it out
        func showBox(at point: CGPoint) {
            focusBoxLayer.removeAllAnimations()
            let scaleKey = "zoom in focus box"
            let fadeInKey = "fade in focus box"
            let pulseKey = "pulse focus box"
            let fadeOutKey = "fade out focus box"
            guard focusBoxLayer.animation(forKey: scaleKey) == nil,
                  focusBoxLayer.animation(forKey: fadeInKey) == nil,
                  focusBoxLayer.animation(forKey: pulseKey) == nil,
                  focusBoxLayer.animation(forKey: fadeOutKey) == nil
                else { return }
    
            CATransaction.begin()
            CATransaction.setDisableActions(true)
            focusBoxLayer.position = point
            CATransaction.commit()
    
            let scale = CABasicAnimation(keyPath: "transform.scale")
            scale.fromValue = 1
            scale.toValue = 0.375
            scale.duration = 0.3
            scale.isRemovedOnCompletion = false
            scale.fillMode = .forwards
    
            let opacityFadeIn = CABasicAnimation(keyPath: "opacity")
            opacityFadeIn.fromValue = 0
            opacityFadeIn.toValue = 1
            opacityFadeIn.duration = 0.3
            opacityFadeIn.isRemovedOnCompletion = false
            opacityFadeIn.fillMode = .forwards
    
            let pulsing = CABasicAnimation(keyPath: "borderColor")
            pulsing.toValue = UIColor(white: 1, alpha: 0.5).cgColor
            pulsing.repeatCount = 2
            pulsing.duration = 0.2
            pulsing.beginTime = CACurrentMediaTime() + 0.3 // wait for the fade in to occur
    
            let opacityFadeOut = CABasicAnimation(keyPath: "opacity")
            opacityFadeOut.fromValue = 1
            opacityFadeOut.toValue = 0
            opacityFadeOut.duration = 0.5
            opacityFadeOut.beginTime = CACurrentMediaTime() + 2 // seconds
            opacityFadeOut.isRemovedOnCompletion = false
            opacityFadeOut.fillMode = .forwards
    
            focusBoxLayer.add(scale, forKey: scaleKey)
            focusBoxLayer.add(opacityFadeIn, forKey: fadeInKey)
            focusBoxLayer.add(pulsing, forKey: pulseKey)
            focusBoxLayer.add(opacityFadeOut, forKey: fadeOutKey)
        }
    
        // MARK: - Private Properties
    
        private lazy var focusBoxLayer: CALayer = {
            let box = CALayer()
            box.bounds = CGRect(x: 0, y: 0, width: 200, height: 200)
            box.borderWidth = 2
            box.borderColor = UIColor.white.cgColor
            box.opacity = 0
            return box
        }()
    
        // MARK: - Unsupported Initializers
    
        required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }
    
    }
    

提交回复
热议问题