web-dev-qa-db-ja.com

ピンチしてズームカメラ

ピンチしてズームカメラを作ろうとしていますが、2つの問題が発生しています。 1つ目は、ユーザーがズームインとズームアウトをやりすぎてしまうことです。2つ目は、写真を撮ったときに、ズームインしたビューでは撮影されないことです。これがピンチ機能の私のコードです...

func pinch(pinch: UIPinchGestureRecognizer) {
    if let view = cameraView {
        view.transform = CGAffineTransformScale(view.transform,
            pinch.scale, pinch.scale)
            pinch.scale = 1
    }

}

これ以上コードを表示する必要があるかどうか教えてください。ありがとう!

12
John Doe

私はカメラの実装で同じ問題を経験しました。これを解決するには、2つのことを知る必要があります。

  • 最大ズームと最小ズームは値の範囲内である必要があります。そうしないと、カメラのズームが大きくなりすぎます。
  • ズームインした画像を保存しない実際の画像と同様に、オンラインの多くのソリューションではカバーされていない一般的なバグです。これは実際には、ビューのズームのみを変更しており、実際のAVCaptureDeviceのズームは変更していないためです。

2つのことを変更するには、次のようなものが必要です。

func pinch(pinch: UIPinchGestureRecognizer) {
   var device: AVCaptureDevice = self.videoDevice
   var vZoomFactor = ((gestureRecognizer as! UIPinchGestureRecognizer).scale)
   var error:NSError!
        do{
            try device.lockForConfiguration()
            defer {device.unlockForConfiguration()}
            if (vZoomFactor <= device.activeFormat.videoMaxZoomFactor){
                device.videoZoomFactor = vZoomFactor
            }else{
            NSLog("Unable to set videoZoom: (max %f, asked %f)", device.activeFormat.videoMaxZoomFactor, vZoomFactor);
            }
        }catch error as NSError{
             NSLog("Unable to set videoZoom: %@", error.localizedDescription);
        }catch _{

        }
}

ご覧のとおり、ビデオデバイスのクラス変数(videoDevice)を使用して、ビジュアルコンポーネントに使用しているキャプチャデバイスを追跡しています。ズームを特定の範囲に制限し、ビュー自体ではなく、デバイスのズームプロパティを変更します。

13

Swift 3.0 || 4.0 4.0


1。ズームレベルを定義します。

let minimumZoom: CGFloat = 1.0
let maximumZoom: CGFloat = 3.0
var lastZoomFactor: CGFloat = 1.0


2。 CameraViewにピンチジェスチャを追加します。

let pinchRecognizer = UIPinchGestureRecognizer(target: self, action:#selector(pinch(_:)))        
            self.viewCamera.addGestureRecognizer(pinchRecognizer)


3。 zoominおよびzoom outのロジックを使用したピンチアクションメソッド

func pinch(_ pinch: UIPinchGestureRecognizer) {
        guard let device = videoDeviceInput.device 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)")
            }
        }

        let newScaleFactor = minMaxZoom(pinch.scale * lastZoomFactor)

        switch pinch.state {
        case .began: fallthrough
        case .changed: update(scale: newScaleFactor)
        case .ended:
            lastZoomFactor = minMaxZoom(newScaleFactor)
            update(scale: lastZoomFactor)
        default: break
        }
    }


ありがとう。ハッピーコーディング????????

32
Hanny

手動のzoomTo(2.0)関数が必要な場合は、これを使用できます

// Create listener for Pinch to Zoom
let pinchRecognizer = UIPinchGestureRecognizer(target: self, action:#selector(FSCameraView.pinchToZoom(_:)))
pinchRecognizer.delegate = self
self.previewViewContainer.addGestureRecognizer(pinchRecognizer)

// set the zoom to a zoomed in mode from start
setZoom(CGFloat(2.0)



// and the functions
func pinchToZoom(sender:UIPinchGestureRecognizer) {
    var vZoomFactor = ((sender as! UIPinchGestureRecognizer).scale)
    setZoom(vZoomFactor)
}

func setZoom(zoomFactor:CGFloat) {
    var device: AVCaptureDevice = self.device!
    var error:NSError!
    do{
        try device.lockForConfiguration()
        defer {device.unlockForConfiguration()}
        if (zoomFactor <= device.activeFormat.videoMaxZoomFactor) {

            let desiredZoomFactor:CGFloat = zoomFactor + atan2(sender.velocity, 5.0);
            device.videoZoomFactor = max(1.0, min(desiredZoomFactor, device.activeFormat.videoMaxZoomFactor));
        }
        else {
            NSLog("Unable to set videoZoom: (max %f, asked %f)", device.activeFormat.videoMaxZoomFactor, zoomFactor);
        }
    }
    catch error as NSError{
        NSLog("Unable to set videoZoom: %@", error.localizedDescription);
    }
    catch _{
    }
}
2
Thyselius
    var device: AVCaptureDevice = self.backCamera
    var vZoomFactor = sender.scale
    var error:NSError!
    do{
        try device.lockForConfiguration()
        defer {device.unlockForConfiguration()}
        if (vZoomFactor <= device.activeFormat.videoMaxZoomFactor) {

            let desiredZoomFactor:CGFloat = vZoomFactor + atan2(sender.velocity, 5.0);
            device.videoZoomFactor = max(1.0, min(desiredZoomFactor, device.activeFormat.videoMaxZoomFactor));
        }
        else {

            NSLog("Unable to set videoZoom: (max %f, asked %f)", device.activeFormat.videoMaxZoomFactor, vZoomFactor);
        }
    }
    catch error as NSError{

        NSLog("Unable to set videoZoom: %@", error.localizedDescription);
    }
    catch _{

    }
1
Chathurka

Ritvik Upadhyaya'sの答えを拡張するには、前のズーム係数を保存して新しいズーム係数を計算する必要があります。指を離して試すたびにズームが通常にリセットされることは望ましくありません。再びズームします。

// To track the zoom factor
var prevZoomFactor: CGFloat = 1

func pinch(pinch: UIPinchGestureRecognizer) {
    var device: AVCaptureDevice = self.videoDevice

    // Here we multiply vZoomFactor with the previous zoom factor if it exist. 
    // Else just multiply by 1
    var vZoomFactor = pinch.scale * prevZoomFactor

    // If the pinching has ended, update prevZoomFactor.
    // Note that we set the limit at 1, because zoom factor cannot be less than 1 or the setting device.videoZoomFactor will crash
    if sender.state == .ended {
        prevZoomFactor = zoomFactor >= 1 ? zoomFactor : 1
    }

    do {
        try device.lockForConfiguration()
        defer {device.unlockForConfiguration()}
        if (vZoomFactor <= device.activeFormat.videoMaxZoomFactor) {
            device.videoZoomFactor = vZoomFactor
        } else {
            print("Unable to set videoZoom: (max \(device.activeFormat.videoMaxZoomFactor), asked \(vZoomFactor))")
      }
    } catch {
        print("\(error.localizedDescription)")
    }
}
1
Chan Jing Hong

次のようにUIPinchGestureRecognizer.scaleを1にリセットするだけで、prevZoomFactorの保存を回避できます。

    @IBAction func pinchAction(_ sender: UIPinchGestureRecognizer) {
        guard let device = currentCaptureDevice else {return}
        var zoom = device.videoZoomFactor * sender.scale
        sender.scale = 1.0
        var error:NSError!
        do{
            try device.lockForConfiguration()
            defer {device.unlockForConfiguration()}
            if zoom >= device.minAvailableVideoZoomFactor && zoom <= device.maxAvailableVideoZoomFactor {
                device.videoZoomFactor = zoom
            }else{
                NSLog("Unable to set videoZoom: (max %f, asked %f)", device.activeFormat.videoMaxZoomFactor, zoom);
            }
        }catch error as NSError{
            NSLog("Unable to set videoZoom: %@", error.localizedDescription);
        }catch _{
        }
    }

これは、ジェスチャーレコグナイザーが最初に登場したときに私が参加したWWDCイベントでAppleによって推奨されました。

0
Sherwin Zadeh