add onZoomChanged, onFocusChanged, set new default behavior,

This commit is contained in:
Dmitriy Loktev 2015-08-11 19:23:06 +06:00
parent be090ec70a
commit 4456ce4a80
5 changed files with 96 additions and 22 deletions

View File

@ -51,7 +51,10 @@ var Camera = React.createClass({
torchMode: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number
])
]),
defaultTouchToFocus: PropTypes.bool,
onFocusChanged: PropTypes.func,
onZoomChanged: PropTypes.func
},
mixins: [NativeMethodsMixin],
@ -205,7 +208,10 @@ var RCTCamera = createReactNativeComponentClass({
type: true,
orientation: true,
flashMode: true,
torchMode: true
torchMode: true,
onFocusChanged: true,
onZoomChanged: true,
defaultTouchToFocus: true
}),
uiViewClassName: 'RCTCamera',
});

View File

@ -7,9 +7,9 @@
@interface RCTCamera : UIView
@property (nonatomic) RCTCameraManager *manager;
@property (nonatomic) RCTBridge *bridge;
@property (nonatomic) RCTCameraFocusSquare *camFocus;
@property (nonatomic) BOOL multipleTouches;
- (id)initWithManager:(RCTCameraManager*)manager;
- (id)initWithManager:(RCTCameraManager*)manager bridge:(RCTBridge *)bridge;
@end

View File

@ -3,11 +3,20 @@
#import "RCTCameraManager.h"
#import "RCTLog.h"
#import "RCTUtils.h"
#import "RCTEventDispatcher.h"
#import "UIView+React.h"
#import <AVFoundation/AVFoundation.h>
#import "CameraFocusSquare.h"
@implementation RCTCamera
{
BOOL _multipleTouches;
BOOL _onFocusChanged;
BOOL _defaultTouchToFocus;
BOOL _onZoomChanged;
}
- (void)setAspect:(NSInteger)aspect
{
@ -60,16 +69,41 @@
[self.manager changeTorchMode:torchMode];
}
- (id)initWithManager:(RCTCameraManager*)manager
- (void)setOnFocusChanged:(BOOL)enabled
{
if (_onFocusChanged != enabled) {
_onFocusChanged = enabled;
}
}
- (void)setDefaultTouchToFocus:(BOOL)enabled
{
if (_defaultTouchToFocus != enabled) {
_defaultTouchToFocus = enabled;
}
}
- (void)setOnZoomChanged:(BOOL)enabled
{
if (_onZoomChanged != enabled) {
_onZoomChanged = enabled;
}
}
- (id)initWithManager:(RCTCameraManager*)manager bridge:(RCTBridge *)bridge
{
if ((self = [super init])) {
self.manager = manager;
self.bridge = bridge;
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchToZoomRecognizer:)];
[self addGestureRecognizer:pinchGesture];
[self.manager initializeCaptureSessionInput:AVMediaTypeVideo];
[self.manager startSession];
self.multipleTouches = NO;
_multipleTouches = NO;
_onFocusChanged = NO;
_defaultTouchToFocus = YES;
_onZoomChanged = NO;
}
return self;
}
@ -111,17 +145,19 @@
{
// Update the touch state.
if ([[event touchesForView:self] count] > 1) {
self.multipleTouches = YES;
_multipleTouches = YES;
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if (!_onFocusChanged) return;
BOOL allTouchesEnded = ([touches count] == [[event touchesForView:self] count]);
// Do not conflict with zooming and etc.
if (allTouchesEnded && !self.multipleTouches) {
if (allTouchesEnded && !_multipleTouches) {
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchPoint = [touch locationInView:touch.view];
// Focus camera on this point
@ -131,28 +167,41 @@
{
[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];
NSDictionary *event = @{
@"target": self.reactTag,
@"touchPoint": @{
@"x": [NSNumber numberWithDouble:touchPoint.x],
@"y": [NSNumber numberWithDouble:touchPoint.y]
}
};
[self.bridge.eventDispatcher sendInputEventWithName:@"focusChanged" body:event];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[self.camFocus setAlpha:0.0];
[UIView commitAnimations];
// Show animated rectangle on the touched area
if (_defaultTouchToFocus) {
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;
_multipleTouches = NO;
}
}
-(void) handlePinchToZoomRecognizer:(UIPinchGestureRecognizer*)pinchRecognizer {
if (!_onZoomChanged) return;
if (pinchRecognizer.state == UIGestureRecognizerStateChanged) {
[self.manager zoom:pinchRecognizer.velocity];
[self.manager zoom:pinchRecognizer.velocity reactTag:self.reactTag];
}
}

View File

@ -73,7 +73,7 @@ typedef NS_ENUM(NSInteger, RCTCameraTorchMode) {
- (void)startSession;
- (void)stopSession;
- (void)focusAtThePoint:(CGPoint) atPoint;
- (void)zoom:(CGFloat)velocity;
- (void)zoom:(CGFloat)velocity reactTag:(NSNumber *)reactTag;
@end

View File

@ -16,7 +16,7 @@ RCT_EXPORT_MODULE();
- (UIView *)view
{
return [[RCTCamera alloc] initWithManager:self];
return [[RCTCamera alloc] initWithManager:self bridge:self.bridge];
}
RCT_EXPORT_VIEW_PROPERTY(aspect, NSInteger);
@ -93,6 +93,18 @@ RCT_EXPORT_VIEW_PROPERTY(torchMode, NSInteger);
];
}
RCT_EXPORT_VIEW_PROPERTY(defaultTouchToFocus, BOOL);
RCT_EXPORT_VIEW_PROPERTY(onFocusChanged, BOOL)
RCT_EXPORT_VIEW_PROPERTY(onZoomChanged, BOOL)
- (NSDictionary *)customDirectEventTypes
{
return @{
@"focusChanged": @{ @"registrationName": @"onFocusChanged" },
@"zoomChanged": @{ @"registrationName": @"onZoomChanged" },
};
}
- (id)init {
if ((self = [super init])) {
@ -688,12 +700,19 @@ didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL
}
}
- (void) zoom:(CGFloat)velocity {
- (void) zoom:(CGFloat)velocity reactTag:(NSNumber *)reactTag{
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);
NSDictionary *event = @{
@"target": reactTag,
@"zoomFactor": [NSNumber numberWithDouble:zoomFactor],
@"velocity": [NSNumber numberWithDouble:velocity]
};
[self.bridge.eventDispatcher sendInputEventWithName:@"zoomChanged" body:event];
device.videoZoomFactor = zoomFactor >= 1.0f ? zoomFactor : 1.0f;
[device unlockForConfiguration];
} else {