Last active
September 29, 2020 06:30
-
-
Save jqn/9b1bc690eebf601df17ef5e6e708e82f to your computer and use it in GitHub Desktop.
RN Camera with rotating icons
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import React, {Component} from 'react'; | |
| import {View, TouchableOpacity, Dimensions, Text} from 'react-native'; | |
| import Orientation from 'react-native-orientation-locker'; | |
| import FontAwesome from 'react-native-vector-icons/FontAwesome'; | |
| import {RNCamera} from 'react-native-camera'; | |
| import * as Animatable from 'react-native-animatable'; | |
| const SCREEN_HEIGHT = Dimensions.get('window').height; | |
| const SCREEN_WIDTH = Dimensions.get('window').width; | |
| export default class App extends Component { | |
| constructor() { | |
| super(); | |
| this.state = { | |
| orientation: 'PORTRAIT', | |
| barcode: '', | |
| }; | |
| } | |
| componentDidMount() { | |
| Orientation.lockToPortrait(); | |
| Orientation.addDeviceOrientationListener( | |
| this._addDeviceOrientationListener.bind(this), | |
| ); | |
| Orientation.addOrientationListener(this._onOrientationDidChange); | |
| } | |
| componentWillUnmount() { | |
| Orientation.removeDeviceOrientationListener( | |
| this._addDeviceOrientationListener, | |
| ); | |
| Orientation.removeOrientationListener(this._onOrientationDidChange); | |
| } | |
| _addDeviceOrientationListener(deviceOrientation) { | |
| console.log( | |
| 'App -> _addDeviceOrientationListener -> deviceOrientation', | |
| deviceOrientation, | |
| ); | |
| this.setState({orientation: deviceOrientation}); | |
| } | |
| _onOrientationDidChange = (orientation) => { | |
| console.log('App -> _onOrientationDidChange -> orientation', orientation); | |
| if (orientation == 'LANDSCAPE-LEFT') { | |
| //do something with landscape left layout | |
| } else { | |
| //do something with portrait layout | |
| } | |
| }; | |
| makeSlideOutTranslation(translationType, fromValue) { | |
| return { | |
| from: { | |
| [translationType]: SCREEN_WIDTH * -0.18, | |
| }, | |
| to: { | |
| [translationType]: fromValue, | |
| }, | |
| }; | |
| } | |
| onBarCodeRead = (e) => { | |
| this.setState({barcode: e.data}); | |
| }; | |
| render() { | |
| return ( | |
| <View style={style.container}> | |
| <RNCamera | |
| onBarCodeRead={this.onBarCodeRead} | |
| ref={(ref) => { | |
| this.camera = ref; | |
| }} | |
| style={{ | |
| flex: 1, | |
| width: '100%', | |
| }}> | |
| <Text | |
| style={{ | |
| ...style.scanText, | |
| top: | |
| this.state.orientation == 'LANDSCAPE-LEFT' || | |
| this.state.orientation == 'LANDSCAPE-RIGHT' | |
| ? '45%' | |
| : '25%', | |
| left: | |
| this.state.orientation == 'LANDSCAPE-LEFT' | |
| ? '75%' | |
| : this.state.orientation == 'LANDSCAPE-RIGHT' | |
| ? '-5%' | |
| : '35%', | |
| transform: [ | |
| { | |
| rotate: | |
| this.state.orientation == 'LANDSCAPE-LEFT' | |
| ? '90deg' | |
| : this.state.orientation == 'LANDSCAPE-RIGHT' | |
| ? '270deg' | |
| : '0deg', | |
| }, | |
| ], | |
| }}> | |
| Scan QRCODE | |
| </Text> | |
| <View style={style.scanView}> | |
| <Animatable.View | |
| style={style.scanBar} | |
| direction="alternate-reverse" | |
| iterationCount="infinite" | |
| duration={1700} | |
| easing="linear" | |
| animation={this.makeSlideOutTranslation( | |
| 'translateY', | |
| SCREEN_WIDTH * -0.54, | |
| )} | |
| /> | |
| </View> | |
| <Text | |
| style={{ | |
| alignSelf: 'center', | |
| fontSize: 25, | |
| color: '#000', | |
| justifyContent: 'center', | |
| top: | |
| this.state.orientation == 'LANDSCAPE-LEFT' || | |
| this.state.orientation == 'LANDSCAPE-RIGHT' | |
| ? SCREEN_HEIGHT / 2 | |
| : '80%', | |
| left: | |
| this.state.orientation == 'LANDSCAPE-LEFT' | |
| ? '-40%' | |
| : this.state.orientation == 'LANDSCAPE-RIGHT' | |
| ? '40%' | |
| : '0%', | |
| transform: [ | |
| { | |
| rotate: | |
| this.state.orientation == 'LANDSCAPE-LEFT' | |
| ? '90deg' | |
| : this.state.orientation == 'LANDSCAPE-RIGHT' | |
| ? '270deg' | |
| : '0deg', | |
| }, | |
| ], | |
| }}> | |
| {this.state.barcode} | |
| </Text> | |
| </RNCamera> | |
| <View style={style.cameraIcon}> | |
| <TouchableOpacity | |
| style={{ | |
| ...style.capture, | |
| transform: [ | |
| { | |
| rotate: | |
| this.state.orientation == 'LANDSCAPE-LEFT' | |
| ? '90deg' | |
| : this.state.orientation == 'LANDSCAPE-RIGHT' | |
| ? '270deg' | |
| : '0deg', | |
| }, | |
| ], | |
| }}> | |
| <FontAwesome name="camera" color={'white'} size={50} /> | |
| </TouchableOpacity> | |
| </View> | |
| <View style={style.flashIcon}> | |
| <TouchableOpacity | |
| style={{ | |
| ...style.capture, | |
| transform: [ | |
| { | |
| rotate: | |
| this.state.orientation == 'LANDSCAPE-LEFT' | |
| ? '90deg' | |
| : this.state.orientation == 'LANDSCAPE-RIGHT' | |
| ? '270deg' | |
| : '0deg', | |
| }, | |
| ], | |
| }}> | |
| <FontAwesome name="bolt" color={'white'} size={50} /> | |
| </TouchableOpacity> | |
| </View> | |
| </View> | |
| ); | |
| } | |
| } | |
| const style = { | |
| container: { | |
| flex: 1, | |
| flexDirection: 'column', | |
| backgroundColor: 'black', | |
| }, | |
| scanBar: { | |
| width: '78%', | |
| height: 1, | |
| backgroundColor: 'red', | |
| marginLeft: 30, | |
| marginTop: 300, | |
| }, | |
| scanText: { | |
| position: 'absolute', | |
| fontSize: 25, | |
| color: '#000', | |
| justifyContent: 'center', | |
| }, | |
| scanView: { | |
| borderWidth: 2, | |
| position: 'absolute', | |
| top: '30%', | |
| left: '20%', | |
| borderColor: '#F00', | |
| justifyContent: 'center', | |
| backgroundColor: 'rgba(255, 255, 255, 0.9)', | |
| padding: 10, | |
| width: '65%', | |
| height: '35%', | |
| backgroundColor: 'transparent', | |
| }, | |
| preview: { | |
| flex: 1, | |
| justifyContent: 'flex-end', | |
| alignItems: 'center', | |
| }, | |
| capture: { | |
| flex: 0, | |
| padding: 15, | |
| alignSelf: 'center', | |
| margin: 20, | |
| }, | |
| cameraIcon: { | |
| position: 'absolute', | |
| bottom: 0, | |
| left: '33%', | |
| }, | |
| flashIcon: { | |
| position: 'absolute', | |
| bottom: 0, | |
| left: '70%', | |
| }, | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import React, {Component} from 'react'; | |
| import {View, TouchableOpacity, Dimensions, Text} from 'react-native'; | |
| import Orientation from 'react-native-orientation-locker'; | |
| import FontAwesome from 'react-native-vector-icons/FontAwesome'; | |
| import {RNCamera} from 'react-native-camera'; | |
| import * as Animatable from 'react-native-animatable'; | |
| const SCREEN_HEIGHT = Dimensions.get('window').height; | |
| const SCREEN_WIDTH = Dimensions.get('window').width; | |
| export default class App extends Component { | |
| constructor() { | |
| super(); | |
| this.state = { | |
| orientation: 'PORTRAIT', | |
| barcode: '', | |
| }; | |
| } | |
| componentDidMount = () => { | |
| Orientation.lockToPortrait(); | |
| Orientation.addDeviceOrientationListener( | |
| this._addDeviceOrientationListener, | |
| ); | |
| }; | |
| componentWillUnmount = () => { | |
| Orientation.removeDeviceOrientationListener( | |
| this._addDeviceOrientationListener, | |
| ); | |
| }; | |
| _addDeviceOrientationListener = (deviceOrientation) => { | |
| console.log( | |
| 'App -> _addDeviceOrientationListener -> deviceOrientation', | |
| deviceOrientation, | |
| ); | |
| this.setState({orientation: deviceOrientation}); | |
| }; | |
| makeSlideOutTranslation(translationType, fromValue) { | |
| return { | |
| from: { | |
| [translationType]: SCREEN_WIDTH * -0.18, | |
| }, | |
| to: { | |
| [translationType]: fromValue, | |
| }, | |
| }; | |
| } | |
| onBarCodeRead = (e) => { | |
| this.setState({barcode: e.data}); | |
| }; | |
| render() { | |
| return ( | |
| <View style={style.container}> | |
| <RNCamera | |
| onBarCodeRead={this.onBarCodeRead} | |
| captureAudio={false} | |
| ref={(ref) => { | |
| this.camera = ref; | |
| }} | |
| style={{ | |
| flex: 1, | |
| width: '100%', | |
| }}> | |
| <Text | |
| style={{ | |
| ...style.scanText, | |
| top: | |
| this.state.orientation == 'LANDSCAPE-LEFT' || | |
| this.state.orientation == 'LANDSCAPE-RIGHT' | |
| ? '45%' | |
| : '25%', | |
| left: | |
| this.state.orientation == 'LANDSCAPE-LEFT' | |
| ? '75%' | |
| : this.state.orientation == 'LANDSCAPE-RIGHT' | |
| ? '-5%' | |
| : '35%', | |
| transform: [ | |
| { | |
| rotate: | |
| this.state.orientation == 'LANDSCAPE-LEFT' | |
| ? '90deg' | |
| : this.state.orientation == 'LANDSCAPE-RIGHT' | |
| ? '270deg' | |
| : '0deg', | |
| }, | |
| ], | |
| }}> | |
| Scan QRCODE | |
| </Text> | |
| <View style={style.scanView}> | |
| <Animatable.View | |
| style={style.scanBar} | |
| direction="alternate-reverse" | |
| iterationCount="infinite" | |
| duration={1700} | |
| easing="linear" | |
| animation={this.makeSlideOutTranslation( | |
| 'translateY', | |
| SCREEN_WIDTH * -0.54, | |
| )} | |
| /> | |
| </View> | |
| <Text | |
| style={{ | |
| alignSelf: 'center', | |
| fontSize: 25, | |
| color: '#000', | |
| justifyContent: 'center', | |
| top: | |
| this.state.orientation == 'LANDSCAPE-LEFT' || | |
| this.state.orientation == 'LANDSCAPE-RIGHT' | |
| ? SCREEN_HEIGHT / 2 | |
| : '80%', | |
| left: | |
| this.state.orientation == 'LANDSCAPE-LEFT' | |
| ? '-40%' | |
| : this.state.orientation == 'LANDSCAPE-RIGHT' | |
| ? '40%' | |
| : '0%', | |
| transform: [ | |
| { | |
| rotate: | |
| this.state.orientation == 'LANDSCAPE-LEFT' | |
| ? '90deg' | |
| : this.state.orientation == 'LANDSCAPE-RIGHT' | |
| ? '270deg' | |
| : '0deg', | |
| }, | |
| ], | |
| }}> | |
| {this.state.barcode} | |
| </Text> | |
| </RNCamera> | |
| <View style={style.cameraIcon}> | |
| <TouchableOpacity | |
| style={{ | |
| ...style.capture, | |
| transform: [ | |
| { | |
| rotate: | |
| this.state.orientation == 'LANDSCAPE-LEFT' | |
| ? '90deg' | |
| : this.state.orientation == 'LANDSCAPE-RIGHT' | |
| ? '270deg' | |
| : '0deg', | |
| }, | |
| ], | |
| }}> | |
| <FontAwesome name="camera" color={'white'} size={50} /> | |
| </TouchableOpacity> | |
| </View> | |
| <View style={style.flashIcon}> | |
| <TouchableOpacity | |
| style={{ | |
| ...style.capture, | |
| transform: [ | |
| { | |
| rotate: | |
| this.state.orientation == 'LANDSCAPE-LEFT' | |
| ? '90deg' | |
| : this.state.orientation == 'LANDSCAPE-RIGHT' | |
| ? '270deg' | |
| : '0deg', | |
| }, | |
| ], | |
| }}> | |
| <FontAwesome name="bolt" color={'white'} size={50} /> | |
| </TouchableOpacity> | |
| </View> | |
| </View> | |
| ); | |
| } | |
| } | |
| const style = { | |
| container: { | |
| flex: 1, | |
| flexDirection: 'column', | |
| backgroundColor: 'black', | |
| }, | |
| scanBar: { | |
| width: '78%', | |
| height: 1, | |
| backgroundColor: 'red', | |
| marginLeft: 30, | |
| marginTop: 300, | |
| }, | |
| scanText: { | |
| position: 'absolute', | |
| fontSize: 25, | |
| color: '#000', | |
| justifyContent: 'center', | |
| }, | |
| scanView: { | |
| borderWidth: 2, | |
| position: 'absolute', | |
| top: '30%', | |
| left: '20%', | |
| borderColor: '#F00', | |
| justifyContent: 'center', | |
| backgroundColor: 'rgba(255, 255, 255, 0.9)', | |
| padding: 10, | |
| width: '65%', | |
| height: '35%', | |
| backgroundColor: 'transparent', | |
| }, | |
| preview: { | |
| flex: 1, | |
| justifyContent: 'flex-end', | |
| alignItems: 'center', | |
| }, | |
| capture: { | |
| flex: 0, | |
| padding: 15, | |
| alignSelf: 'center', | |
| margin: 20, | |
| }, | |
| cameraIcon: { | |
| position: 'absolute', | |
| bottom: 0, | |
| left: '33%', | |
| }, | |
| flashIcon: { | |
| position: 'absolute', | |
| bottom: 0, | |
| left: '70%', | |
| }, | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment