feat(android): autoFocusPointOfInterest, Camera & Camera2 (#1974)
* Android autoFocusPointOfInterest, Camera & Camera2 * updated example with touch to focus
This commit is contained in:
parent
d8922ac90e
commit
7bb9a1205c
@ -17,11 +17,13 @@
|
||||
package com.google.android.cameraview;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.hardware.Camera;
|
||||
import android.media.CamcorderProfile;
|
||||
import android.media.MediaRecorder;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.support.v4.util.SparseArrayCompat;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceHolder;
|
||||
@ -30,6 +32,7 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
@ -63,6 +66,12 @@ class Camera1 extends CameraViewImpl implements MediaRecorder.OnInfoListener,
|
||||
WB_MODES.put(Constants.WB_INCANDESCENT, Camera.Parameters.WHITE_BALANCE_INCANDESCENT);
|
||||
}
|
||||
|
||||
private static final int FOCUS_AREA_SIZE_DEFAULT = 300;
|
||||
private static final int FOCUS_METERING_AREA_WEIGHT_DEFAULT = 1000;
|
||||
private static final int DELAY_MILLIS_BEFORE_RESETTING_FOCUS = 3000;
|
||||
|
||||
private Handler mHandler = new Handler();
|
||||
|
||||
private int mCameraId;
|
||||
|
||||
private final AtomicBoolean isPictureCaptureInProgress = new AtomicBoolean(false);
|
||||
@ -712,6 +721,105 @@ class Camera1 extends CameraViewImpl implements MediaRecorder.OnInfoListener,
|
||||
}
|
||||
}
|
||||
|
||||
// Most credit: https://github.com/CameraKit/camerakit-android/blob/master/camerakit-core/src/main/api16/com/wonderkiln/camerakit/Camera1.java
|
||||
void setFocusArea(float x, float y) {
|
||||
if (mCamera != null) {
|
||||
Camera.Parameters parameters = mCamera.getParameters();
|
||||
if (parameters == null) return;
|
||||
|
||||
String focusMode = parameters.getFocusMode();
|
||||
Rect rect = calculateFocusArea(x, y);
|
||||
|
||||
List<Camera.Area> meteringAreas = new ArrayList<>();
|
||||
meteringAreas.add(new Camera.Area(rect, FOCUS_METERING_AREA_WEIGHT_DEFAULT));
|
||||
if (parameters.getMaxNumFocusAreas() != 0 && focusMode != null &&
|
||||
(focusMode.equals(Camera.Parameters.FOCUS_MODE_AUTO) ||
|
||||
focusMode.equals(Camera.Parameters.FOCUS_MODE_MACRO) ||
|
||||
focusMode.equals(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) ||
|
||||
focusMode.equals(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO))
|
||||
) {
|
||||
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
|
||||
parameters.setFocusAreas(meteringAreas);
|
||||
if (parameters.getMaxNumMeteringAreas() > 0) {
|
||||
parameters.setMeteringAreas(meteringAreas);
|
||||
}
|
||||
if (!parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
|
||||
return; //cannot autoFocus
|
||||
}
|
||||
mCamera.setParameters(parameters);
|
||||
mCamera.autoFocus(new Camera.AutoFocusCallback() {
|
||||
@Override
|
||||
public void onAutoFocus(boolean success, Camera camera) {
|
||||
resetFocus(success, camera);
|
||||
}
|
||||
});
|
||||
} else if (parameters.getMaxNumMeteringAreas() > 0) {
|
||||
if (!parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
|
||||
return; //cannot autoFocus
|
||||
}
|
||||
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
|
||||
parameters.setFocusAreas(meteringAreas);
|
||||
parameters.setMeteringAreas(meteringAreas);
|
||||
|
||||
mCamera.setParameters(parameters);
|
||||
mCamera.autoFocus(new Camera.AutoFocusCallback() {
|
||||
@Override
|
||||
public void onAutoFocus(boolean success, Camera camera) {
|
||||
resetFocus(success, camera);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
mCamera.autoFocus(new Camera.AutoFocusCallback() {
|
||||
@Override
|
||||
public void onAutoFocus(boolean success, Camera camera) {
|
||||
mCamera.cancelAutoFocus();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resetFocus(final boolean success, final Camera camera) {
|
||||
mHandler.removeCallbacksAndMessages(null);
|
||||
mHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mCamera != null) {
|
||||
mCamera.cancelAutoFocus();
|
||||
Camera.Parameters parameters = mCamera.getParameters();
|
||||
if (parameters == null) return;
|
||||
|
||||
if (parameters.getFocusMode() != Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) {
|
||||
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
|
||||
parameters.setFocusAreas(null);
|
||||
parameters.setMeteringAreas(null);
|
||||
mCamera.setParameters(parameters);
|
||||
}
|
||||
|
||||
mCamera.cancelAutoFocus();
|
||||
}
|
||||
}
|
||||
}, DELAY_MILLIS_BEFORE_RESETTING_FOCUS);
|
||||
}
|
||||
|
||||
private Rect calculateFocusArea(float x, float y) {
|
||||
int padding = FOCUS_AREA_SIZE_DEFAULT / 2;
|
||||
int centerX = (int) (x * 2000);
|
||||
int centerY = (int) (y * 2000);
|
||||
|
||||
int left = centerX - padding;
|
||||
int top = centerY - padding;
|
||||
int right = centerX + padding;
|
||||
int bottom = centerY + padding;
|
||||
|
||||
if (left < 0) left = 0;
|
||||
if (right > 2000) right = 2000;
|
||||
if (top < 0) top = 0;
|
||||
if (bottom > 2000) bottom = 2000;
|
||||
|
||||
return new Rect(left - 1000, top - 1000, right - 1000, bottom - 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate display orientation
|
||||
* https://developer.android.com/reference/android/hardware/Camera.html#setDisplayOrientation(int)
|
||||
|
||||
@ -26,9 +26,12 @@ import android.hardware.camera2.CameraCaptureSession;
|
||||
import android.hardware.camera2.CameraCharacteristics;
|
||||
import android.hardware.camera2.CameraDevice;
|
||||
import android.hardware.camera2.CameraManager;
|
||||
import android.hardware.camera2.CameraMetadata;
|
||||
import android.hardware.camera2.CaptureFailure;
|
||||
import android.hardware.camera2.CaptureRequest;
|
||||
import android.hardware.camera2.CaptureResult;
|
||||
import android.hardware.camera2.TotalCaptureResult;
|
||||
import android.hardware.camera2.params.MeteringRectangle;
|
||||
import android.hardware.camera2.params.StreamConfigurationMap;
|
||||
import android.media.CamcorderProfile;
|
||||
import android.media.Image;
|
||||
@ -74,6 +77,10 @@ class Camera2 extends CameraViewImpl implements MediaRecorder.OnInfoListener, Me
|
||||
*/
|
||||
private static final int MAX_PREVIEW_HEIGHT = 1080;
|
||||
|
||||
private static final int FOCUS_AREA_SIZE_DEFAULT = 300;
|
||||
|
||||
private static final int FOCUS_METERING_AREA_WEIGHT_DEFAULT = 1000;
|
||||
|
||||
private final CameraManager mCameraManager;
|
||||
|
||||
private final CameraDevice.StateCallback mCameraDeviceCallback
|
||||
@ -1036,6 +1043,87 @@ class Camera2 extends CameraViewImpl implements MediaRecorder.OnInfoListener, Me
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Auto focus on input coordinates
|
||||
*/
|
||||
|
||||
// Much credit - https://gist.github.com/royshil/8c760c2485257c85a11cafd958548482
|
||||
void setFocusArea(float x, float y) {
|
||||
CameraCaptureSession.CaptureCallback captureCallbackHandler = new CameraCaptureSession.CaptureCallback() {
|
||||
@Override
|
||||
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
|
||||
super.onCaptureCompleted(session, request, result);
|
||||
|
||||
if (request.getTag() == "FOCUS_TAG") {
|
||||
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, null);
|
||||
try {
|
||||
mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), null, null);
|
||||
} catch (CameraAccessException e) {
|
||||
Log.e(TAG, "Failed to manual focus.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request, CaptureFailure failure) {
|
||||
super.onCaptureFailed(session, request, failure);
|
||||
Log.e(TAG, "Manual AF failure: " + failure);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
mCaptureSession.stopRepeating();
|
||||
|
||||
} catch (CameraAccessException e) {
|
||||
Log.e(TAG, "Failed to manual focus.", e);
|
||||
}
|
||||
|
||||
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
|
||||
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF);
|
||||
try {
|
||||
mCaptureSession.capture(mPreviewRequestBuilder.build(), captureCallbackHandler, null);
|
||||
} catch (CameraAccessException e) {
|
||||
Log.e(TAG, "Failed to manual focus.", e);
|
||||
}
|
||||
|
||||
if (isMeteringAreaAFSupported()) {
|
||||
MeteringRectangle focusAreaTouch = calculateFocusArea(x, y);
|
||||
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, new MeteringRectangle[]{focusAreaTouch});
|
||||
}
|
||||
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
|
||||
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
|
||||
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
|
||||
mPreviewRequestBuilder.setTag("FOCUS_TAG");
|
||||
|
||||
try {
|
||||
mCaptureSession.capture(mPreviewRequestBuilder.build(), captureCallbackHandler, null);
|
||||
} catch (CameraAccessException e) {
|
||||
Log.e(TAG, "Failed to manual focus.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isMeteringAreaAFSupported() {
|
||||
return mCameraCharacteristics.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AF) >= 1;
|
||||
}
|
||||
|
||||
private MeteringRectangle calculateFocusArea(float x, float y) {
|
||||
final Rect sensorArraySize = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
|
||||
|
||||
// Current iOS spec has a requirement on sensor orientation that doesn't change, spec followed here.
|
||||
final int xCoordinate = (int)(y * (float)sensorArraySize.height());
|
||||
final int yCoordinate = (int)(x * (float)sensorArraySize.width());
|
||||
final int halfTouchWidth = 150; //TODO: this doesn't represent actual touch size in pixel. Values range in [3, 10]...
|
||||
final int halfTouchHeight = 150;
|
||||
MeteringRectangle focusAreaTouch = new MeteringRectangle(Math.max(yCoordinate - halfTouchWidth, 0),
|
||||
Math.max(xCoordinate - halfTouchHeight, 0),
|
||||
halfTouchWidth * 2,
|
||||
halfTouchHeight * 2,
|
||||
MeteringRectangle.METERING_WEIGHT_MAX - 1);
|
||||
|
||||
return focusAreaTouch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures a still picture.
|
||||
*/
|
||||
|
||||
@ -18,6 +18,8 @@ package com.google.android.cameraview;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.Camera;
|
||||
import android.media.CamcorderProfile;
|
||||
import android.os.Build;
|
||||
import android.os.Parcel;
|
||||
@ -29,6 +31,7 @@ import android.support.v4.os.ParcelableCompat;
|
||||
import android.support.v4.os.ParcelableCompatCreatorCallbacks;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.graphics.SurfaceTexture;
|
||||
@ -492,6 +495,16 @@ public class CameraView extends FrameLayout {
|
||||
public int getCameraOrientation() {
|
||||
return mImpl.getCameraOrientation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the auto focus point.
|
||||
*
|
||||
* @param x sets the x coordinate for camera auto focus
|
||||
* @param y sets the y coordinate for camera auto focus
|
||||
*/
|
||||
public void setAutoFocusPointOfInterest(float x, float y) {
|
||||
mImpl.setFocusArea(x, y);
|
||||
}
|
||||
|
||||
public void setFocusDepth(float value) {
|
||||
mImpl.setFocusDepth(value);
|
||||
|
||||
@ -92,6 +92,8 @@ abstract class CameraViewImpl {
|
||||
abstract void setDisplayOrientation(int displayOrientation);
|
||||
|
||||
abstract void setDeviceOrientation(int deviceOrientation);
|
||||
|
||||
abstract void setFocusArea(float x, float y);
|
||||
|
||||
abstract void setFocusDepth(float value);
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ package org.reactnative.camera;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.common.MapBuilder;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.ViewGroupManager;
|
||||
@ -97,6 +98,13 @@ public class CameraViewManager extends ViewGroupManager<RNCameraView> {
|
||||
view.setFocusDepth(depth);
|
||||
}
|
||||
|
||||
@ReactProp(name = "autoFocusPointOfInterest")
|
||||
public void setAutoFocusPointOfInterest(RNCameraView view, ReadableMap coordinates) {
|
||||
float x = (float) coordinates.getDouble("x");
|
||||
float y = (float) coordinates.getDouble("y");
|
||||
view.setAutoFocusPointOfInterest(x, y);
|
||||
}
|
||||
|
||||
@ReactProp(name = "zoom")
|
||||
public void setZoom(RNCameraView view, float zoom) {
|
||||
view.setZoom(zoom);
|
||||
|
||||
@ -179,7 +179,7 @@ Most cameras have a Auto Focus feature. It adjusts your camera lens position aut
|
||||
|
||||
Use the `autoFocus` property to specify the auto focus setting of your camera. `RNCamera.Constants.AutoFocus.on` turns it ON, `RNCamera.Constants.AutoFocus.off` turns it OFF.
|
||||
|
||||
#### `iOS` `autoFocusPointOfInterest`
|
||||
#### `autoFocusPointOfInterest`
|
||||
|
||||
Values: Object `{ x: 0.5, y: 0.5 }`.
|
||||
|
||||
@ -187,6 +187,9 @@ Setting this property causes the auto focus feature of the camera to attempt to
|
||||
|
||||
Coordinates values are measured as floats from `0` to `1.0`. `{ x: 0, y: 0 }` will focus on the top left of the image, `{ x: 1, y: 1 }` will be the bottom right. Values are based on landscape mode with the home button on the right—this applies even if the device is in portrait mode.
|
||||
|
||||
Hint:
|
||||
for portrait orientation, apply 90° clockwise rotation + translation: [Example](https://gist.github.com/Craigtut/6632a9ac7cfff55e74fb561862bc4edb)
|
||||
|
||||
#### `captureAudio`
|
||||
|
||||
Values: boolean `true` (default) | `false`
|
||||
|
||||
@ -1,6 +1,14 @@
|
||||
/* eslint-disable no-console */
|
||||
import React from 'react';
|
||||
import { StyleSheet, Text, View, TouchableOpacity, Slider } from 'react-native';
|
||||
import {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
TouchableOpacity,
|
||||
Slider,
|
||||
TouchableWithoutFeedback,
|
||||
Dimensions,
|
||||
} from 'react-native';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { RNCamera } from 'react-native-camera';
|
||||
|
||||
@ -27,6 +35,13 @@ export default class CameraScreen extends React.Component {
|
||||
flash: 'off',
|
||||
zoom: 0,
|
||||
autoFocus: 'on',
|
||||
autoFocusPoint: {
|
||||
normalized: { x: 0.5, y: 0.5 }, // normalized values required for autoFocusPointOfInterest
|
||||
drawRectPosition: {
|
||||
x: Dimensions.get('window').width * 0.5 - 32,
|
||||
y: Dimensions.get('window').height * 0.5 - 32,
|
||||
},
|
||||
},
|
||||
depth: 0,
|
||||
type: 'back',
|
||||
whiteBalance: 'auto',
|
||||
@ -69,6 +84,28 @@ export default class CameraScreen extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
touchToFocus(event) {
|
||||
const { pageX, pageY } = event.nativeEvent;
|
||||
const screenWidth = Dimensions.get('window').width;
|
||||
const screenHeight = Dimensions.get('window').height;
|
||||
const isPortrait = screenHeight > screenWidth;
|
||||
|
||||
let x = pageX / screenWidth;
|
||||
let y = pageY / screenHeight;
|
||||
// Coordinate transform for portrait. See autoFocusPointOfInterest in docs for more info
|
||||
if (isPortrait) {
|
||||
x = pageY / screenHeight;
|
||||
y = -(pageX / screenWidth) + 1;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
autoFocusPoint: {
|
||||
normalized: { x, y },
|
||||
drawRectPosition: { x: pageX, y: pageY },
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
zoomOut() {
|
||||
this.setState({
|
||||
zoom: this.state.zoom - 0.1 < 0 ? 0 : this.state.zoom - 0.1,
|
||||
@ -236,6 +273,11 @@ export default class CameraScreen extends React.Component {
|
||||
|
||||
renderCamera() {
|
||||
const { canDetectFaces, canDetectText, canDetectBarcode } = this.state;
|
||||
|
||||
const drawFocusRingPosition = {
|
||||
top: this.state.autoFocusPoint.drawRectPosition.y - 32,
|
||||
left: this.state.autoFocusPoint.drawRectPosition.x - 32,
|
||||
};
|
||||
return (
|
||||
<RNCamera
|
||||
ref={ref => {
|
||||
@ -243,10 +285,12 @@ export default class CameraScreen extends React.Component {
|
||||
}}
|
||||
style={{
|
||||
flex: 1,
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
type={this.state.type}
|
||||
flashMode={this.state.flash}
|
||||
autoFocus={this.state.autoFocus}
|
||||
autoFocusPointOfInterest={this.state.autoFocusPoint.normalized}
|
||||
zoom={this.state.zoom}
|
||||
whiteBalance={this.state.whiteBalance}
|
||||
ratio={this.state.ratio}
|
||||
@ -262,9 +306,19 @@ export default class CameraScreen extends React.Component {
|
||||
onTextRecognized={canDetectText ? this.textRecognized : null}
|
||||
onGoogleVisionBarcodesDetected={canDetectBarcode ? this.barcodeRecognized : null}
|
||||
>
|
||||
<View style={StyleSheet.absoluteFill}>
|
||||
<View style={[styles.autoFocusBox, drawFocusRingPosition]} />
|
||||
<TouchableWithoutFeedback onPress={this.touchToFocus.bind(this)}>
|
||||
<View style={{ flex: 1 }} />
|
||||
</TouchableWithoutFeedback>
|
||||
</View>
|
||||
<View
|
||||
style={{
|
||||
flex: 0.5,
|
||||
height: 72,
|
||||
backgroundColor: 'transparent',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-around',
|
||||
}}
|
||||
>
|
||||
<View
|
||||
@ -308,82 +362,84 @@ export default class CameraScreen extends React.Component {
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
<View
|
||||
style={{
|
||||
flex: 0.4,
|
||||
backgroundColor: 'transparent',
|
||||
flexDirection: 'row',
|
||||
alignSelf: 'flex-end',
|
||||
}}
|
||||
>
|
||||
<Slider
|
||||
style={{ width: 150, marginTop: 15, alignSelf: 'flex-end' }}
|
||||
onValueChange={this.setFocusDepth.bind(this)}
|
||||
step={0.1}
|
||||
disabled={this.state.autoFocus === 'on'}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={{
|
||||
flex: 0.1,
|
||||
backgroundColor: 'transparent',
|
||||
flexDirection: 'row',
|
||||
alignSelf: 'flex-end',
|
||||
}}
|
||||
>
|
||||
<TouchableOpacity
|
||||
style={[
|
||||
styles.flipButton,
|
||||
{
|
||||
flex: 0.3,
|
||||
alignSelf: 'flex-end',
|
||||
backgroundColor: this.state.isRecording ? 'white' : 'darkred',
|
||||
},
|
||||
]}
|
||||
onPress={this.state.isRecording ? () => {} : this.takeVideo.bind(this)}
|
||||
<View style={{ bottom: 0 }}>
|
||||
<View
|
||||
style={{
|
||||
height: 20,
|
||||
backgroundColor: 'transparent',
|
||||
flexDirection: 'row',
|
||||
alignSelf: 'flex-end',
|
||||
}}
|
||||
>
|
||||
{this.state.isRecording ? (
|
||||
<Text style={styles.flipText}> ☕ </Text>
|
||||
) : (
|
||||
<Text style={styles.flipText}> REC </Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
{this.state.zoom !== 0 && (
|
||||
<Text style={[styles.flipText, styles.zoomText]}>Zoom: {this.state.zoom}</Text>
|
||||
)}
|
||||
<View
|
||||
style={{
|
||||
flex: 0.1,
|
||||
backgroundColor: 'transparent',
|
||||
flexDirection: 'row',
|
||||
alignSelf: 'flex-end',
|
||||
}}
|
||||
>
|
||||
<TouchableOpacity
|
||||
style={[styles.flipButton, { flex: 0.1, alignSelf: 'flex-end' }]}
|
||||
onPress={this.zoomIn.bind(this)}
|
||||
<Slider
|
||||
style={{ width: 150, marginTop: 15, alignSelf: 'flex-end' }}
|
||||
onValueChange={this.setFocusDepth.bind(this)}
|
||||
step={0.1}
|
||||
disabled={this.state.autoFocus === 'on'}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={{
|
||||
height: 56,
|
||||
backgroundColor: 'transparent',
|
||||
flexDirection: 'row',
|
||||
alignSelf: 'flex-end',
|
||||
}}
|
||||
>
|
||||
<Text style={styles.flipText}> + </Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={[styles.flipButton, { flex: 0.1, alignSelf: 'flex-end' }]}
|
||||
onPress={this.zoomOut.bind(this)}
|
||||
<TouchableOpacity
|
||||
style={[
|
||||
styles.flipButton,
|
||||
{
|
||||
flex: 0.3,
|
||||
alignSelf: 'flex-end',
|
||||
backgroundColor: this.state.isRecording ? 'white' : 'darkred',
|
||||
},
|
||||
]}
|
||||
onPress={this.state.isRecording ? () => {} : this.takeVideo.bind(this)}
|
||||
>
|
||||
{this.state.isRecording ? (
|
||||
<Text style={styles.flipText}> ☕ </Text>
|
||||
) : (
|
||||
<Text style={styles.flipText}> REC </Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
{this.state.zoom !== 0 && (
|
||||
<Text style={[styles.flipText, styles.zoomText]}>Zoom: {this.state.zoom}</Text>
|
||||
)}
|
||||
<View
|
||||
style={{
|
||||
height: 56,
|
||||
backgroundColor: 'transparent',
|
||||
flexDirection: 'row',
|
||||
alignSelf: 'flex-end',
|
||||
}}
|
||||
>
|
||||
<Text style={styles.flipText}> - </Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={[styles.flipButton, { flex: 0.25, alignSelf: 'flex-end' }]}
|
||||
onPress={this.toggleFocus.bind(this)}
|
||||
>
|
||||
<Text style={styles.flipText}> AF : {this.state.autoFocus} </Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={[styles.flipButton, styles.picButton, { flex: 0.3, alignSelf: 'flex-end' }]}
|
||||
onPress={this.takePicture.bind(this)}
|
||||
>
|
||||
<Text style={styles.flipText}> SNAP </Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={[styles.flipButton, { flex: 0.1, alignSelf: 'flex-end' }]}
|
||||
onPress={this.zoomIn.bind(this)}
|
||||
>
|
||||
<Text style={styles.flipText}> + </Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={[styles.flipButton, { flex: 0.1, alignSelf: 'flex-end' }]}
|
||||
onPress={this.zoomOut.bind(this)}
|
||||
>
|
||||
<Text style={styles.flipText}> - </Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={[styles.flipButton, { flex: 0.25, alignSelf: 'flex-end' }]}
|
||||
onPress={this.toggleFocus.bind(this)}
|
||||
>
|
||||
<Text style={styles.flipText}> AF : {this.state.autoFocus} </Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={[styles.flipButton, styles.picButton, { flex: 0.3, alignSelf: 'flex-end' }]}
|
||||
onPress={this.takePicture.bind(this)}
|
||||
>
|
||||
<Text style={styles.flipText}> SNAP </Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
{!!canDetectFaces && this.renderFaces()}
|
||||
{!!canDetectFaces && this.renderLandmarks()}
|
||||
@ -417,6 +473,15 @@ const styles = StyleSheet.create({
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
autoFocusBox: {
|
||||
position: 'absolute',
|
||||
height: 64,
|
||||
width: 64,
|
||||
borderRadius: 12,
|
||||
borderWidth: 2,
|
||||
borderColor: 'white',
|
||||
opacity: 0.4,
|
||||
},
|
||||
flipText: {
|
||||
color: 'white',
|
||||
fontSize: 15,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user