Пан жест (удержание / перетаскивание) зум на камеру, как Snapchat - PullRequest
0 голосов
/ 30 января 2019

Я пытаюсь воспроизвести функцию масштабирования камеры 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 голосов
/ 05 февраля 2019

Вы можете использовать свойство перевода распознавателя жестов, чтобы рассчитать смещение в точках и нормализовать это смещение как коэффициент масштабирования.

Встраивая это в свой код, вы можете попробовать:

 ... 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
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...