2015-10-16 17 views
7

Ich versuche eine Prise Zoom-Kamera zu machen, aber ich habe zwei Probleme. Erstens erlaubt es dem Benutzer, viel zu viel und viel zu weit zu zoomen. Zweitens, wenn ich ein Bild mache, nimmt es nicht die vergrößerte Ansicht. Hier ist mein Code für die Pinch-Funktion ...Prise, um die Kamera zu zoomen

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

} 

Sag mir, wenn Sie mehr Code sehen müssen. Vielen Dank!

Antwort

7

Ich habe die gleichen Probleme mit der Kamera-Implementierung erlebt. Um das zu lösen, müssen Sie zwei Dinge wissen.

  • Die maximalen und minimalen Zoom hat in einem Wert sein oder sonst führt es in die Kamera im Weg Zoomen zu viel.
  • Wie mit dem tatsächlichen Bild, das das gezoomte Bild nicht speichert, ist es ein allgemeiner Fehler, den viele Lösungen online nicht abdecken. Das ist eigentlich so, weil Sie nur den Zoom der Ansicht ändern und nicht den eigentlichen AVCaptureDevice Zoom.

Um die beiden Dinge, die Sie so etwas wie dieses brauchen zu ändern:

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 _{ 

     } 
} 

Wie Sie verwende ich eine Klassenvariable für das Videogerät (videoDevice) Spur der Fangeinrichtung zu halten, sehen kann ich bin mit für visuelle Komponente. Ich beschränke den Zoom auf einen bestimmten Bereich und verändere die Zoom-Eigenschaft auf dem Gerät und nicht die Ansicht selbst!

+3

Es gibt eine Sache fehlt. Sie müssen den aktuellen Zoomfaktor verfolgen und in den Berechnungen für den Zoomfaktor verwenden, der eingestellt werden soll. Aber danke für die tolle Antwort! – stonecompass

1
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 _{ 

    } 
0

Wenn Sie eine manuelle zoomTo benötigen (2.0) Funktion können Sie verwenden, um dies

// 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 _{ 
    } 
} 
1

erweitern auf Ritvik Upadhyaya des Antwort, müssen Sie auch den vorherigen Zoomfaktor speichern zu berechnen Bei der neuen Version sollten Sie nicht jedes Mal, wenn Sie die Finger hochheben und wieder zoomen, auf Zoomen setzen.

// 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

Hallo. Würde die App nicht abstürzen, wenn vZoomFactor kleiner als 1.0 ist? –

14

Swift 3,0

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

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 
    } 
} 
+0

Das hat bei mir funktioniert, danke! – Kushagra

+0

Ehrfürchtig beantwortet +1 ... vielen dank –

+0

danke mann. Perfekte Antwort...! –

Verwandte Themen