mirror of
https://github.com/status-im/react-native-camera.git
synced 2025-02-24 17:58:20 +00:00
* iOS: minor focus and zoom changes RCTCameraManager focusAtThePoint improvements - Dynamicaly get size from bounds of camera view, instead of full screen, since it might not always be the case that the Camera react component is taking up the entire device screen. - Also add setting exposure to the same point of interest we are focusing on. Example - Add onFocusChanged and onZoomChanged empty callback functions by default to Example app, allowing tap-to-focus and pinch-to-zoom to be readily experienced/experimented with. - Updated react/react-native dependencies to match root package.json. TODO/Other remarks - Tap-to-focus seems to still not work perfectly... From logging, it always seems to get the right location in the view (meaning its getting the right location from the user touch and transforming it to the {0, 1} range appropriately), and does indeed engage the focus process, but it seems it sometimes refocuses on the center-ish region of what's in the camera instead of the location that was actually pressed. I thought this might be related to the subjectAreaDidChange getting called, which in turn sets the focus mode to continuous auto-focus at the view center, but from my experimenting, this method never actually gets called. I wasn't able to figure out if there's somewhere else in the library that's forcing continuous auto-focus, or if there's just some bug in our current focus procedure within focusAtThePoint. * Reset Example/package.json dependency versions to master
250 lines
5.8 KiB
JavaScript
250 lines
5.8 KiB
JavaScript
import React from 'react';
|
|
import {
|
|
Image,
|
|
StatusBar,
|
|
StyleSheet,
|
|
TouchableOpacity,
|
|
View,
|
|
} from 'react-native';
|
|
import Camera from 'react-native-camera';
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
},
|
|
preview: {
|
|
flex: 1,
|
|
justifyContent: 'flex-end',
|
|
alignItems: 'center',
|
|
},
|
|
overlay: {
|
|
position: 'absolute',
|
|
padding: 16,
|
|
right: 0,
|
|
left: 0,
|
|
alignItems: 'center',
|
|
},
|
|
topOverlay: {
|
|
top: 0,
|
|
flex: 1,
|
|
flexDirection: 'row',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
},
|
|
bottomOverlay: {
|
|
bottom: 0,
|
|
backgroundColor: 'rgba(0,0,0,0.4)',
|
|
flexDirection: 'row',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
captureButton: {
|
|
padding: 15,
|
|
backgroundColor: 'white',
|
|
borderRadius: 40,
|
|
},
|
|
typeButton: {
|
|
padding: 5,
|
|
},
|
|
flashButton: {
|
|
padding: 5,
|
|
},
|
|
buttonsSpace: {
|
|
width: 10,
|
|
},
|
|
});
|
|
|
|
export default class Example extends React.Component {
|
|
constructor(props) {
|
|
super(props);
|
|
|
|
this.camera = null;
|
|
|
|
this.state = {
|
|
camera: {
|
|
aspect: Camera.constants.Aspect.fill,
|
|
captureTarget: Camera.constants.CaptureTarget.cameraRoll,
|
|
type: Camera.constants.Type.back,
|
|
orientation: Camera.constants.Orientation.auto,
|
|
flashMode: Camera.constants.FlashMode.auto,
|
|
},
|
|
isRecording: false
|
|
};
|
|
}
|
|
|
|
takePicture = () => {
|
|
if (this.camera) {
|
|
this.camera.capture()
|
|
.then((data) => console.log(data))
|
|
.catch(err => console.error(err));
|
|
}
|
|
}
|
|
|
|
startRecording = () => {
|
|
if (this.camera) {
|
|
this.camera.capture({mode: Camera.constants.CaptureMode.video})
|
|
.then((data) => console.log(data))
|
|
.catch(err => console.error(err));
|
|
this.setState({
|
|
isRecording: true
|
|
});
|
|
}
|
|
}
|
|
|
|
stopRecording = () => {
|
|
if (this.camera) {
|
|
this.camera.stopCapture();
|
|
this.setState({
|
|
isRecording: false
|
|
});
|
|
}
|
|
}
|
|
|
|
switchType = () => {
|
|
let newType;
|
|
const { back, front } = Camera.constants.Type;
|
|
|
|
if (this.state.camera.type === back) {
|
|
newType = front;
|
|
} else if (this.state.camera.type === front) {
|
|
newType = back;
|
|
}
|
|
|
|
this.setState({
|
|
camera: {
|
|
...this.state.camera,
|
|
type: newType,
|
|
},
|
|
});
|
|
}
|
|
|
|
get typeIcon() {
|
|
let icon;
|
|
const { back, front } = Camera.constants.Type;
|
|
|
|
if (this.state.camera.type === back) {
|
|
icon = require('./assets/ic_camera_rear_white.png');
|
|
} else if (this.state.camera.type === front) {
|
|
icon = require('./assets/ic_camera_front_white.png');
|
|
}
|
|
|
|
return icon;
|
|
}
|
|
|
|
switchFlash = () => {
|
|
let newFlashMode;
|
|
const { auto, on, off } = Camera.constants.FlashMode;
|
|
|
|
if (this.state.camera.flashMode === auto) {
|
|
newFlashMode = on;
|
|
} else if (this.state.camera.flashMode === on) {
|
|
newFlashMode = off;
|
|
} else if (this.state.camera.flashMode === off) {
|
|
newFlashMode = auto;
|
|
}
|
|
|
|
this.setState({
|
|
camera: {
|
|
...this.state.camera,
|
|
flashMode: newFlashMode,
|
|
},
|
|
});
|
|
}
|
|
|
|
get flashIcon() {
|
|
let icon;
|
|
const { auto, on, off } = Camera.constants.FlashMode;
|
|
|
|
if (this.state.camera.flashMode === auto) {
|
|
icon = require('./assets/ic_flash_auto_white.png');
|
|
} else if (this.state.camera.flashMode === on) {
|
|
icon = require('./assets/ic_flash_on_white.png');
|
|
} else if (this.state.camera.flashMode === off) {
|
|
icon = require('./assets/ic_flash_off_white.png');
|
|
}
|
|
|
|
return icon;
|
|
}
|
|
|
|
render() {
|
|
return (
|
|
<View style={styles.container}>
|
|
<StatusBar
|
|
animated
|
|
hidden
|
|
/>
|
|
<Camera
|
|
ref={(cam) => {
|
|
this.camera = cam;
|
|
}}
|
|
style={styles.preview}
|
|
aspect={this.state.camera.aspect}
|
|
captureTarget={this.state.camera.captureTarget}
|
|
type={this.state.camera.type}
|
|
flashMode={this.state.camera.flashMode}
|
|
onFocusChanged={() => {}}
|
|
onZoomChanged={() => {}}
|
|
defaultTouchToFocus
|
|
mirrorImage={false}
|
|
/>
|
|
<View style={[styles.overlay, styles.topOverlay]}>
|
|
<TouchableOpacity
|
|
style={styles.typeButton}
|
|
onPress={this.switchType}
|
|
>
|
|
<Image
|
|
source={this.typeIcon}
|
|
/>
|
|
</TouchableOpacity>
|
|
<TouchableOpacity
|
|
style={styles.flashButton}
|
|
onPress={this.switchFlash}
|
|
>
|
|
<Image
|
|
source={this.flashIcon}
|
|
/>
|
|
</TouchableOpacity>
|
|
</View>
|
|
<View style={[styles.overlay, styles.bottomOverlay]}>
|
|
{
|
|
!this.state.isRecording
|
|
&&
|
|
<TouchableOpacity
|
|
style={styles.captureButton}
|
|
onPress={this.takePicture}
|
|
>
|
|
<Image
|
|
source={require('./assets/ic_photo_camera_36pt.png')}
|
|
/>
|
|
</TouchableOpacity>
|
|
||
|
|
null
|
|
}
|
|
<View style={styles.buttonsSpace} />
|
|
{
|
|
!this.state.isRecording
|
|
&&
|
|
<TouchableOpacity
|
|
style={styles.captureButton}
|
|
onPress={this.startRecording}
|
|
>
|
|
<Image
|
|
source={require('./assets/ic_videocam_36pt.png')}
|
|
/>
|
|
</TouchableOpacity>
|
|
||
|
|
<TouchableOpacity
|
|
style={styles.captureButton}
|
|
onPress={this.stopRecording}
|
|
>
|
|
<Image
|
|
source={require('./assets/ic_stop_36pt.png')}
|
|
/>
|
|
</TouchableOpacity>
|
|
}
|
|
</View>
|
|
</View>
|
|
);
|
|
}
|
|
}
|