Tap-to-focus and Pinch-to-zoom
This commit is contained in:
parent
d3d60279fc
commit
be090ec70a
|
@ -0,0 +1,3 @@
|
|||
#import <UIKit/UIKit.h>
|
||||
@interface RCTCameraFocusSquare : UIView
|
||||
@end
|
|
@ -0,0 +1,28 @@
|
|||
#import "CameraFocusSquare.h"
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
const float squareLength = 80.0f;
|
||||
@implementation RCTCameraFocusSquare
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
// Initialization code
|
||||
|
||||
[self setBackgroundColor:[UIColor clearColor]];
|
||||
[self.layer setBorderWidth:2.0];
|
||||
[self.layer setCornerRadius:4.0];
|
||||
[self.layer setBorderColor:[UIColor whiteColor].CGColor];
|
||||
|
||||
CABasicAnimation* selectionAnimation = [CABasicAnimation
|
||||
animationWithKeyPath:@"borderColor"];
|
||||
selectionAnimation.toValue = (id)[UIColor blueColor].CGColor;
|
||||
selectionAnimation.repeatCount = 8;
|
||||
[self.layer addAnimation:selectionAnimation
|
||||
forKey:@"selectionAnimation"];
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@end
|
|
@ -1,11 +1,14 @@
|
|||
#import <UIKit/UIKit.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import "CameraFocusSquare.h"
|
||||
|
||||
@class RCTCameraManager;
|
||||
|
||||
@interface RCTCamera : UIView
|
||||
|
||||
@property (nonatomic) RCTCameraManager *manager;
|
||||
@property (nonatomic) RCTCameraFocusSquare *camFocus;
|
||||
@property (nonatomic) BOOL multipleTouches;
|
||||
|
||||
- (id)initWithManager:(RCTCameraManager*)manager;
|
||||
|
||||
|
|
55
RCTCamera.m
55
RCTCamera.m
|
@ -5,6 +5,7 @@
|
|||
#import "RCTUtils.h"
|
||||
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import "CameraFocusSquare.h"
|
||||
|
||||
@implementation RCTCamera
|
||||
|
||||
|
@ -64,8 +65,11 @@
|
|||
|
||||
if ((self = [super init])) {
|
||||
self.manager = manager;
|
||||
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchToZoomRecognizer:)];
|
||||
[self addGestureRecognizer:pinchGesture];
|
||||
[self.manager initializeCaptureSessionInput:AVMediaTypeVideo];
|
||||
[self.manager startSession];
|
||||
self.multipleTouches = NO;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -102,4 +106,55 @@
|
|||
[self.manager changeOrientation:orientation];
|
||||
}
|
||||
|
||||
|
||||
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
// Update the touch state.
|
||||
if ([[event touchesForView:self] count] > 1) {
|
||||
self.multipleTouches = YES;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
{
|
||||
BOOL allTouchesEnded = ([touches count] == [[event touchesForView:self] count]);
|
||||
|
||||
// Do not conflict with zooming and etc.
|
||||
if (allTouchesEnded && !self.multipleTouches) {
|
||||
UITouch *touch = [[event allTouches] anyObject];
|
||||
CGPoint touchPoint = [touch locationInView:touch.view];
|
||||
// Focus camera on this point
|
||||
[self.manager focusAtThePoint:touchPoint];
|
||||
|
||||
if (self.camFocus)
|
||||
{
|
||||
[self.camFocus removeFromSuperview];
|
||||
}
|
||||
// Show animated rectangle on the touched area
|
||||
self.camFocus = [[RCTCameraFocusSquare alloc]initWithFrame:CGRectMake(touchPoint.x-40, touchPoint.y-40, 80, 80)];
|
||||
[self.camFocus setBackgroundColor:[UIColor clearColor]];
|
||||
[self addSubview:self.camFocus];
|
||||
[self.camFocus setNeedsDisplay];
|
||||
|
||||
[UIView beginAnimations:nil context:NULL];
|
||||
[UIView setAnimationDuration:1.0];
|
||||
[self.camFocus setAlpha:0.0];
|
||||
[UIView commitAnimations];
|
||||
}
|
||||
|
||||
if (allTouchesEnded) {
|
||||
self.multipleTouches = NO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
-(void) handlePinchToZoomRecognizer:(UIPinchGestureRecognizer*)pinchRecognizer {
|
||||
if (pinchRecognizer.state == UIGestureRecognizerStateChanged) {
|
||||
[self.manager zoom:pinchRecognizer.velocity];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
0314E39D1B661A460092D183 /* CameraFocusSquare.m in Sources */ = {isa = PBXBuildFile; fileRef = 0314E39C1B661A460092D183 /* CameraFocusSquare.m */; };
|
||||
4107014D1ACB732B00C6AA39 /* RCTCamera.m in Sources */ = {isa = PBXBuildFile; fileRef = 410701481ACB732B00C6AA39 /* RCTCamera.m */; };
|
||||
4107014E1ACB732B00C6AA39 /* RCTCameraManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 4107014A1ACB732B00C6AA39 /* RCTCameraManager.m */; };
|
||||
454EBCF41B5082DC00AD0F86 /* NSMutableDictionary+ImageMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 454EBCF31B5082DC00AD0F86 /* NSMutableDictionary+ImageMetadata.m */; };
|
||||
|
@ -25,6 +26,8 @@
|
|||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0314E39B1B661A0C0092D183 /* CameraFocusSquare.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CameraFocusSquare.h; sourceTree = "<group>"; };
|
||||
0314E39C1B661A460092D183 /* CameraFocusSquare.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CameraFocusSquare.m; sourceTree = "<group>"; };
|
||||
4107012F1ACB723B00C6AA39 /* libRCTCamera.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTCamera.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
410701471ACB732B00C6AA39 /* RCTCamera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTCamera.h; sourceTree = "<group>"; };
|
||||
410701481ACB732B00C6AA39 /* RCTCamera.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTCamera.m; sourceTree = "<group>"; };
|
||||
|
@ -47,6 +50,8 @@
|
|||
410701241ACB719800C6AA39 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0314E39C1B661A460092D183 /* CameraFocusSquare.m */,
|
||||
0314E39B1B661A0C0092D183 /* CameraFocusSquare.h */,
|
||||
454EBCF31B5082DC00AD0F86 /* NSMutableDictionary+ImageMetadata.m */,
|
||||
410701471ACB732B00C6AA39 /* RCTCamera.h */,
|
||||
410701481ACB732B00C6AA39 /* RCTCamera.m */,
|
||||
|
@ -119,6 +124,7 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0314E39D1B661A460092D183 /* CameraFocusSquare.m in Sources */,
|
||||
454EBCF41B5082DC00AD0F86 /* NSMutableDictionary+ImageMetadata.m in Sources */,
|
||||
4107014E1ACB732B00C6AA39 /* RCTCameraManager.m in Sources */,
|
||||
4107014D1ACB732B00C6AA39 /* RCTCamera.m in Sources */,
|
||||
|
|
|
@ -60,6 +60,7 @@ typedef NS_ENUM(NSInteger, RCTCameraTorchMode) {
|
|||
@property (nonatomic) NSInteger videoTarget;
|
||||
@property (nonatomic, strong) RCTResponseSenderBlock videoCallback;
|
||||
|
||||
|
||||
- (void)changeAspect:(NSString *)aspect;
|
||||
- (void)changeCamera:(NSInteger)camera;
|
||||
- (void)changeOrientation:(NSInteger)orientation;
|
||||
|
@ -71,5 +72,8 @@ typedef NS_ENUM(NSInteger, RCTCameraTorchMode) {
|
|||
- (void)stopCapture;
|
||||
- (void)startSession;
|
||||
- (void)stopSession;
|
||||
- (void)focusAtThePoint:(CGPoint) atPoint;
|
||||
- (void)zoom:(CGFloat)velocity;
|
||||
|
||||
|
||||
@end
|
||||
|
|
|
@ -105,6 +105,7 @@ RCT_EXPORT_VIEW_PROPERTY(torchMode, NSInteger);
|
|||
|
||||
self.sessionQueue = dispatch_queue_create("cameraManagerQueue", DISPATCH_QUEUE_SERIAL);
|
||||
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -661,5 +662,46 @@ didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL
|
|||
});
|
||||
}
|
||||
|
||||
- (void) focusAtThePoint:(CGPoint) atPoint;
|
||||
{
|
||||
Class captureDeviceClass = NSClassFromString(@"AVCaptureDevice");
|
||||
if (captureDeviceClass != nil) {
|
||||
dispatch_async([self sessionQueue], ^{
|
||||
AVCaptureDevice *device = [[self videoCaptureDeviceInput] device];
|
||||
if([device isFocusPointOfInterestSupported] &&
|
||||
[device isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {
|
||||
CGRect screenRect = [[UIScreen mainScreen] bounds];
|
||||
double screenWidth = screenRect.size.width;
|
||||
double screenHeight = screenRect.size.height;
|
||||
double focus_x = atPoint.x/screenWidth;
|
||||
double focus_y = atPoint.y/screenHeight;
|
||||
if([device lockForConfiguration:nil]) {
|
||||
[device setFocusPointOfInterest:CGPointMake(focus_x,focus_y)];
|
||||
[device setFocusMode:AVCaptureFocusModeAutoFocus];
|
||||
if ([device isExposureModeSupported:AVCaptureExposureModeAutoExpose]){
|
||||
[device setExposureMode:AVCaptureExposureModeAutoExpose];
|
||||
}
|
||||
[device unlockForConfiguration];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (void) zoom:(CGFloat)velocity {
|
||||
const CGFloat pinchVelocityDividerFactor = 20.0f; // TODO: calibrate or make this component's property
|
||||
NSError *error = nil;
|
||||
AVCaptureDevice *device = [[self videoCaptureDeviceInput] device];
|
||||
if ([device lockForConfiguration:&error]) {
|
||||
CGFloat zoomFactor = device.videoZoomFactor + atan(velocity / pinchVelocityDividerFactor);
|
||||
device.videoZoomFactor = zoomFactor >= 1.0f ? zoomFactor : 1.0f;
|
||||
[device unlockForConfiguration];
|
||||
} else {
|
||||
NSLog(@"error: %@", error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@end
|
||||
|
|
Loading…
Reference in New Issue