1import { BarCodeScanner } from 'expo-barcode-scanner'; 2import * as Permissions from 'expo-permissions'; 3import * as ScreenOrientation from 'expo-screen-orientation'; 4import React from 'react'; 5import { Button, Platform, StyleSheet, Text, View } from 'react-native'; 6import * as Svg from 'react-native-svg'; 7import { NavigationEvents } from 'react-navigation'; 8 9const BUTTON_COLOR = Platform.OS === 'ios' ? '#fff' : '#666'; 10 11interface State { 12 isPermissionsGranted: boolean; 13 type: any; 14 cornerPoints?: any[]; 15 alerting: boolean; 16 haveDimensions: boolean; 17 canvasHeight?: number; 18 canvasWidth?: number; 19 boundingBox?: { 20 origin: { 21 x: number; 22 y: number; 23 }; 24 size: { 25 width: number; 26 height: number; 27 }; 28 }; 29} 30 31export default class BarcodeScannerExample extends React.Component<object, State> { 32 static navigationOptions = { 33 title: '<BarCodeScanner />', 34 }; 35 36 canChangeOrientation = false; 37 38 readonly state: State = { 39 isPermissionsGranted: false, 40 type: BarCodeScanner.Constants.Type.back, 41 alerting: false, 42 haveDimensions: false, 43 }; 44 45 componentDidFocus = async () => { 46 const { status } = await Permissions.askAsync(Permissions.CAMERA); 47 this.setState({ isPermissionsGranted: status === 'granted' }); 48 }; 49 50 toggleAlertingAboutResult = () => { 51 this.setState({ alerting: !this.state.alerting }); 52 }; 53 54 toggleScreenOrientationState = () => { 55 if (this.canChangeOrientation) { 56 ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT_UP); 57 } else { 58 ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.ALL); 59 } 60 this.canChangeOrientation = !this.canChangeOrientation; 61 }; 62 63 setCanvasDimensions = (e: any) => { 64 this.setState({ 65 canvasWidth: e.nativeEvent.layout.width, 66 canvasHeight: e.nativeEvent.layout.height, 67 haveDimensions: true, 68 }); 69 }; 70 71 render() { 72 if (!this.state.isPermissionsGranted) { 73 return ( 74 <View style={styles.container}> 75 <NavigationEvents onDidFocus={this.componentDidFocus} /> 76 <Text>You have not granted permission to use the camera on this device!</Text> 77 </View> 78 ); 79 } 80 81 const circles = []; 82 83 if (this.state.cornerPoints) { 84 for (const point of this.state.cornerPoints) { 85 circles.push( 86 <Svg.Circle 87 cx={point.x} 88 cy={point.y} 89 r={2} 90 strokeWidth={0.1} 91 stroke="gray" 92 fill="green" 93 /> 94 ); 95 } 96 } 97 98 return ( 99 <View style={styles.container}> 100 <BarCodeScanner 101 onLayout={this.setCanvasDimensions} 102 onBarCodeScanned={this.handleBarCodeScanned} 103 barCodeTypes={[ 104 BarCodeScanner.Constants.BarCodeType.qr, 105 BarCodeScanner.Constants.BarCodeType.pdf417, 106 BarCodeScanner.Constants.BarCodeType.code128, 107 BarCodeScanner.Constants.BarCodeType.code39, 108 ]} 109 type={this.state.type} 110 style={styles.preview} 111 /> 112 113 {this.state.haveDimensions && ( 114 <Svg.Svg 115 height={this.state.canvasHeight} 116 width={this.state.canvasWidth} 117 style={styles.svg}> 118 <Svg.Circle 119 cx={this.state.canvasWidth! / 2} 120 cy={this.state.canvasHeight! / 2} 121 r={2} 122 strokeWidth={2.5} 123 stroke="#e74c3c" 124 fill="#f1c40f" 125 /> 126 {this.state.boundingBox && ( 127 <Svg.Rect 128 x={this.state.boundingBox.origin.x} 129 y={this.state.boundingBox.origin.y} 130 width={this.state.boundingBox.size.width} 131 height={this.state.boundingBox.size.height} 132 strokeWidth={2} 133 stroke="#9b59b6" 134 fill="none" 135 /> 136 )} 137 {circles} 138 </Svg.Svg> 139 )} 140 141 <View style={styles.toolbar}> 142 <Button color={BUTTON_COLOR} title="Direction" onPress={this.toggleType} /> 143 <Button 144 color={BUTTON_COLOR} 145 title="Orientation" 146 onPress={this.toggleScreenOrientationState} 147 /> 148 <Button color={BUTTON_COLOR} title="Alerting" onPress={this.toggleAlertingAboutResult} /> 149 </View> 150 </View> 151 ); 152 } 153 154 toggleType = () => 155 this.setState({ 156 type: 157 this.state.type === BarCodeScanner.Constants.Type.back 158 ? BarCodeScanner.Constants.Type.front 159 : BarCodeScanner.Constants.Type.back, 160 }); 161 162 handleBarCodeScanned = (data: any) => { 163 if (this.state.alerting) { 164 requestAnimationFrame(() => { 165 alert(JSON.stringify(data)); 166 }); 167 } 168 this.setState({ cornerPoints: data.cornerPoints, boundingBox: data.bounds }); 169 }; 170} 171 172const styles = StyleSheet.create({ 173 container: { 174 flex: 1, 175 }, 176 preview: { 177 ...StyleSheet.absoluteFillObject, 178 backgroundColor: 'black', 179 }, 180 toolbar: { 181 position: 'absolute', 182 bottom: 0, 183 left: 0, 184 right: 0, 185 paddingVertical: 10, 186 paddingHorizontal: 10, 187 flexDirection: 'row', 188 justifyContent: 'space-between', 189 backgroundColor: 'rgba(255,255,255,0.2)', 190 }, 191 svg: { 192 position: 'absolute', 193 borderWidth: 2, 194 borderColor: 'red', 195 }, 196}); 197