在Snapchat等相机上平移手势(按住/拖动)

时间:2019-01-29 23:57:50

标签: ios swift avfoundation zoom uipangesturerecognizer

我正在尝试复制Snapchat相机的缩放功能,一旦开始录制,您就可以上下拖动手指,它会相应地放大或缩小。我已经成功进行了捏捏缩放,但是一直坚持使用PanGestureRecognizer进行缩放。

这是我尝试过的代码,问题是我不知道如何替换用于捏捏手势识别器缩放的sender.scale。我正在使用AVFoundation。基本上,我在问如何像TikTok或Snapchat那样正确地进行保持缩放(一个手指拖动)。

let minimumZoom: CGFloat = 1.0
let maximumZoom: CGFloat = 15.0
var lastZoomFactor: CGFloat = 1.0
var latestDirection: Int = 0

@objc func panGesture(_ sender: UIPanGestureRecognizer) {

    let velocity = sender.velocity(in: doubleTapSwitchCamButton)
    var currentDirection: Int = 0

    if velocity.y > 0 || velocity.y < 0 {

                let originalCapSession = captureSession
                var devitce : AVCaptureDevice!

                let videoDeviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera, .builtInDuoCamera], mediaType: AVMediaType.video, position: .unspecified)
                let devices = videoDeviceDiscoverySession.devices
                devitce = devices.first!

                guard let device = devitce else { return }

                    // Return zoom value between the minimum and maximum zoom values
                    func minMaxZoom(_ factor: CGFloat) -> CGFloat {
                        return min(min(max(factor, minimumZoom), maximumZoom), device.activeFormat.videoMaxZoomFactor)
                        }

                        func update(scale factor: CGFloat) {
                            do {

                                try device.lockForConfiguration()
                                defer { device.unlockForConfiguration() }
                                device.videoZoomFactor = factor
                            } catch {
                                print("\(error.localizedDescription)")
                            }
                        }

//These 2 lines below are the problematic ones, pinch zoom uses this one below, and the newScaleFactor below that is a testing one that did not work.
                let newScaleFactor = minMaxZoom(sender.scale * lastZoomFactor)
                       //let newScaleFactor = CGFloat(exactly: number + lastZoomFactor)


                    switch sender.state {

                    case .began: fallthrough                
                    case .changed: update(scale: newScaleFactor!)                
                    case .ended:
                        lastZoomFactor = minMaxZoom(newScaleFactor!)
                        update(scale: lastZoomFactor)

                    default: break
                    }

        } else {

        }

        latestDirection = currentDirection

    }

1 个答案:

答案 0 :(得分:0)

您可以使用手势识别器的平移属性来计算点的位移,并将该位移标准化为缩放因子。

将其安装到您的代码中,您可以尝试:

 ... somewhere in your view setup code, i.e. viewDidLoad.... 
     let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(panGesture))
     button.addGestureRecognizer(panGestureRecognizer)

 private var initialZoom: CGFloat = 1.0
 @objc func panGesture(_ sender: UIPanGestureRecognizer) {

    // note that 'view' here is the overall video preview
    let velocity = sender.velocity(in: view)

    if velocity.y > 0 || velocity.y < 0 {

       let originalCapSession = captureSession
       var devitce : AVCaptureDevice!

       let videoDeviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera, .builtInDuoCamera], mediaType: AVMediaType.video, position: .unspecified)
       let devices = videoDeviceDiscoverySession.devices
       devitce = devices.first!

       guard let device = devitce else { return }

        let minimumZoomFactor: CGFloat = 1.0
        let maximumZoomFactor: CGFloat = min(device.activeFormat.videoMaxZoomFactor, 10.0) // artificially set a max useable zoom of 10x

        // clamp a zoom factor between minimumZoom and maximumZoom
        func clampZoomFactor(_ factor: CGFloat) -> CGFloat {
            return min(max(factor, minimumZoomFactor), maximumZoomFactor)
        }

        func update(scale factor: CGFloat) {
            do {

                try device.lockForConfiguration()
                defer { device.unlockForConfiguration() }
                device.videoZoomFactor = factor
            } catch {
                print("\(error.localizedDescription)")
            }
        }

        switch sender.state {

        case .began:
            initialZoom = device.videoZoomFactor
            startRecording() /// call to start recording your video

        case .changed:

            // distance in points for the full zoom range (e.g. min to max), could be view.frame.height
            let fullRangeDistancePoints: CGFloat = 300.0

            // extract current distance travelled, from gesture start
            let currentYTranslation: CGFloat = sender.translation(in: view).y

            // calculate a normalized zoom factor between [-1,1], where up is positive (ie zooming in)
            let normalizedZoomFactor = -1 * max(-1,min(1,currentYTranslation / fullRangeDistancePoints))

            // calculate effective zoom scale to use
            let newZoomFactor = clampZoomFactor(initialZoom + normalizedZoomFactor * (maximumZoomFactor - minimumZoomFactor))

            // update device's zoom factor'
            update(scale: newZoomFactor)

        case .ended, .cancelled:
            stopRecording() /// call to start recording your video
            break

        default:
            break
        }
    }
}