From bd5a0f193b708c5949f153e1ae92aae7c47ce404 Mon Sep 17 00:00:00 2001 From: Andrew Walz Date: Wed, 11 Jan 2017 20:13:41 -0700 Subject: [PATCH] Updating tapToFocus --- CHANGELOG.md | 4 + .../focus.imageset/Contents.json | 22 ++++ .../focus.imageset/focus@2x.png | Bin 0 -> 2461 bytes .../focus.imageset/focus@3x.png | Bin 0 -> 3906 bytes .../DemoSwiftyCam/ViewController.swift | 17 ++- README.md | 2 +- Source/SwiftyCamViewController.swift | 103 +++++++++++------- 7 files changed, 106 insertions(+), 42 deletions(-) create mode 100644 DemoSwiftyCam/DemoSwiftyCam/Assets.xcassets/focus.imageset/Contents.json create mode 100644 DemoSwiftyCam/DemoSwiftyCam/Assets.xcassets/focus.imageset/focus@2x.png create mode 100644 DemoSwiftyCam/DemoSwiftyCam/Assets.xcassets/focus.imageset/focus@3x.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 25d5991..0059b42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## Version 1.5.0 +- Added support for front-facing camera tap to adjust exposure +- Updated demo application with tap animation + ## Version 1.4.0 - Added support for background audio during video capture - Added allowBackgroundAudio property diff --git a/DemoSwiftyCam/DemoSwiftyCam/Assets.xcassets/focus.imageset/Contents.json b/DemoSwiftyCam/DemoSwiftyCam/Assets.xcassets/focus.imageset/Contents.json new file mode 100644 index 0000000..5f4d857 --- /dev/null +++ b/DemoSwiftyCam/DemoSwiftyCam/Assets.xcassets/focus.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "focus@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "focus@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DemoSwiftyCam/DemoSwiftyCam/Assets.xcassets/focus.imageset/focus@2x.png b/DemoSwiftyCam/DemoSwiftyCam/Assets.xcassets/focus.imageset/focus@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..db68a8d2c3ac3cde48dc9077a28c19c8f302fb2c GIT binary patch literal 2461 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, with event: UIEvent?) { - guard tapToFocus == true && currentCamera == .rear else { - // Ignore taps - return - } - - let screenSize = previewLayer!.bounds.size - if let touchPoint = touches.first { - let x = touchPoint.location(in: previewLayer!).y / screenSize.height - let y = 1.0 - touchPoint.location(in: previewLayer!).x / screenSize.width - let focusPoint = CGPoint(x: x, y: y) - - if let device = videoDevice { - do { - try device.lockForConfiguration() - - device.focusPointOfInterest = focusPoint - device.focusMode = .autoFocus - device.exposurePointOfInterest = focusPoint - device.exposureMode = AVCaptureExposureMode.continuousAutoExposure - device.unlockForConfiguration() - //Call delegate function and pass in the location of the touch - - DispatchQueue.main.async { - self.cameraDelegate?.SwiftyCamDidFocusAtPoint(focusPoint: touchPoint.location(in: self.previewLayer)) - } - } - catch { - // just ignore - } - } - } - } // MARK: Private Functions @@ -741,8 +708,54 @@ open class SwiftyCamViewController: UIViewController { } } + /// Handle single tap gesture + + @objc fileprivate func singleTapGesture(tap: UITapGestureRecognizer) { + guard tapToFocus == true else { + // Ignore taps + return + } + + let screenSize = previewLayer!.bounds.size + let tapPoint = tap.location(in: previewLayer!) + let x = tapPoint.y / screenSize.height + let y = 1.0 - tapPoint.x / screenSize.width + let focusPoint = CGPoint(x: x, y: y) + + if let device = videoDevice { + do { + try device.lockForConfiguration() + + if device.isFocusPointOfInterestSupported == true { + device.focusPointOfInterest = focusPoint + device.focusMode = .autoFocus + } + device.exposurePointOfInterest = focusPoint + device.exposureMode = AVCaptureExposureMode.continuousAutoExposure + device.unlockForConfiguration() + //Call delegate function and pass in the location of the touch + + DispatchQueue.main.async { + self.cameraDelegate?.SwiftyCamDidFocusAtPoint(focusPoint: tapPoint) + } + } + catch { + // just ignore + } + } + } + + /// Handle double tap gesture + + @objc fileprivate func doubleTapGesture(tap: UITapGestureRecognizer) { + guard doubleTapCameraSwitch == true else { + return + } + switchCamera() + } + /** - Add pinch gesture recognizer to currentView + Add pinch gesture recognizer and double tap gesture recognizer to currentView - Parameter view: View to add gesture recognzier @@ -752,6 +765,16 @@ open class SwiftyCamViewController: UIViewController { let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(zoomGesture(pinch:))) pinchGesture.delegate = self view.addGestureRecognizer(pinchGesture) + + let singleTapGesture = UITapGestureRecognizer(target: self, action: #selector(singleTapGesture(tap:))) + singleTapGesture.numberOfTapsRequired = 1 + singleTapGesture.delegate = self + view.addGestureRecognizer(singleTapGesture) + + let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(doubleTapGesture(tap:))) + doubleTapGesture.numberOfTapsRequired = 2 + doubleTapGesture.delegate = self + view.addGestureRecognizer(doubleTapGesture) } /// Handle Denied App Privacy Settings