@react-native-ohos/react-native-qr-decode-image-camera
Version:
Decode react native from gallery and camera
282 lines (264 loc) • 9.02 kB
JSX
import React, { PureComponent, Component } from "react";
import { RNCamera } from "react-native-camera";
import PropTypes from "prop-types";
import {
StyleSheet,
View,
Text,
Vibration,
Platform,
} from "react-native";
import QRScannerView from "./QRScannerView";
import QRScannerHarmony from "./QRScanner.harmony.jsx"
/**
* Scan interface
*/
export default class QRScanner extends Component {
constructor(props) {
super(props);
this.state = {
scanning: false,
barCodeSize: {}
};
}
static defaultProps = {
onRead: () => { },
renderTopView: () => { },
renderBottomView: () => (
<View style={{ flex: 1, backgroundColor: "#0000004D" }} />
),
rectHeight: 200,
rectWidth: 200,
flashMode: false, // Flashlight mode
finderX: 0, // Viewfinder X-axis offset
finderY: 0, // Viewfinder Y-axis offset
zoom: 0.2, // Zoom range 0 - 1
translucent: false,
isRepeatScan: false,
cameraType: "back",
notAuthorizedView: () => (
<View style={styles.authorizationContainer}>
<Text style={styles.notAuthorizedText}>Camera not authorized</Text>
</View>
),
vibrate: true,
};
render() {
if (Platform.OS == 'harmony') {
return (
<QRScannerHarmony {...this.props} />
)
} else {
return (
<View
style={{
flex: 1
}}
>
<RNCamera
style={{
flex: 1
}}
captureAudio={false}
onBarCodeRead={this._handleBarCodeRead}
androidCameraPermissionOptions={null}
androidRecordAudioPermissionOptions={null}
notAuthorizedView={this.props.notAuthorizedView()}
barCodeTypes={[RNCamera.Constants.BarCodeType.qr]}
flashMode={
!this.props.flashMode
? RNCamera.Constants.FlashMode.off
: RNCamera.Constants.FlashMode.torch
}
zoom={this.props.zoom}
type={this.props.cameraType}
>
<View style={[styles.topButtonsContainer, this.props.topViewStyle]}>
{this.props.renderTopView()}
</View>
<QRScannerView
maskColor={this.props.maskColor}
cornerColor={this.props.cornerColor}
borderColor={this.props.borderColor}
rectHeight={this.props.rectHeight}
rectWidth={this.props.rectWidth}
borderWidth={this.props.borderWidth}
cornerBorderWidth={this.props.cornerBorderWidth}
cornerBorderLength={this.props.cornerBorderLength}
cornerOffsetSize={this.props.cornerOffsetSize}
isCornerOffset={this.props.isCornerOffset}
bottomHeight={this.props.bottomHeight}
scanBarAnimateTime={this.props.scanBarAnimateTime}
scanBarColor={this.props.scanBarColor}
scanBarHeight={this.props.scanBarHeight}
scanBarMargin={this.props.scanBarMargin}
hintText={this.props.hintText}
hintTextStyle={this.props.hintTextStyle}
scanBarImage={this.props.scanBarImage}
hintTextPosition={this.props.hintTextPosition}
isShowScanBar={this.props.isShowScanBar}
finderX={this.props.finderX}
finderY={this.props.finderY}
returnSize={this.barCodeSize}
/>
<View
style={[styles.bottomButtonsContainer, this.props.bottomViewStyle]}
>
{this.props.renderBottomView()}
</View>
</RNCamera>
</View>
);
}
}
isShowCode = false;
barCodeSize = size => this.setState({ barCodeSize: size });
returnMax = (a, b) => (a > b ? a : b);
returnMin = (a, b) => (a < b ? a : b);
iosBarCode = e => {
let x = Number(e.bounds.origin.x);
let y = Number(e.bounds.origin.y);
let width = e.bounds.size.width;
let height = e.bounds.size.height;
let viewMinX = this.state.barCodeSize.x - this.props.finderX;
let viewMinY = this.state.barCodeSize.y - this.props.finderY;
let viewMaxX =
this.state.barCodeSize.x +
this.state.barCodeSize.width -
width -
this.props.finderX;
let viewMaxY =
this.state.barCodeSize.y +
this.state.barCodeSize.height -
height -
this.props.finderY;
if (x > viewMinX && y > viewMinY && x < viewMaxX && y < viewMaxY) {
if (this.props.isRepeatScan) {
if (this.props.vibrate) {
Vibration.vibrate();
}
this.props.onRead(e);
} else {
if (!this.isShowCode) {
this.isShowCode = true;
if (this.props.vibrate) {
Vibration.vibrate();
}
this.props.onRead(e);
}
}
}
};
androidBarCode = e => {
// if (!e.bounds[0] || !e.bounds[1] || !e.bounds[2] || !e.bounds[3]) return null;
// const leftBottom = {x: e.bounds[0].x / pixelRatio, y: e.bounds[0].y / pixelRatio}
// const leftTop= {x: e.bounds[1].x / pixelRatio, y: e.bounds[1].y / pixelRatio}
// const rightTop = {x: e.bounds[2].x / pixelRatio, y: e.bounds[2].y / pixelRatio}
// const rightBottom = {x: e.bounds[3].x / pixelRatio, y: e.bounds[3].y / pixelRatio}
// let x = this.returnMin(leftTop.x, leftBottom.x);
// let y = this.returnMin(leftTop.y, rightTop.y);
// let width = this.returnMax(rightTop.x - leftTop.x, rightBottom.x - leftBottom.x)
// let height = this.returnMax(leftBottom.y - leftTop.y , rightBottom.y - rightTop.y)
// let viewMinX = this.state.barCodeSize.x - this.props.finderX * 4 / pixelRatio - (this.props.finderX > 0 ? this.props.finderX/10 : 0)
// let viewMinY = this.state.barCodeSize.y - this.props.finderY * 4 / pixelRatio - (this.props.translucent ? 0 : StatusBar.currentHeight)*2/pixelRatio - (this.props.finderY > 0 ? this.props.finderY/3 : this.props.finderY/10*(-1))
// let viewMaxX = this.state.barCodeSize.x + 20 + this.state.barCodeSize.width*2 / pixelRatio - width - this.props.finderX *4/pixelRatio - (this.props.finderX < 0 ? 0 : this.props.finderX/5)
// let viewMaxY = this.state.barCodeSize.y + this.state.barCodeSize.height*2 / pixelRatio - height - this.props.finderY *4/pixelRatio - (this.props.translucent ? 0 : StatusBar.currentHeight)*2/pixelRatio - (this.props.finderY < 0 ? this.props.finderY/5 : 0 )
// if(x&&y) {
// if ((x > viewMinX && y > viewMinY) && (x < viewMaxX && y < viewMaxY)) {
// if (this.props.isRepeatScan) {
// Vibration.vibrate();
// this.props.onRead(e)
// } else {
// if (!this.isShowCode) {
// this.isShowCode = true;
// Vibration.vibrate();
// this.props.onRead(e)
// }
// }
// }
// }
// The following are unrestricted scanning areas
if (this.props.isRepeatScan) {
Vibration.vibrate();
this.props.onRead(e);
} else {
if (!this.isShowCode) {
this.isShowCode = true;
Vibration.vibrate();
this.props.onRead(e);
}
}
};
_handleBarCodeRead = e => {
switch (Platform.OS) {
case "ios":
this.iosBarCode(e);
break;
case "android":
this.androidBarCode(e);
break;
default:
break;
}
};
}
const styles = StyleSheet.create({
topButtonsContainer: {
position: "absolute",
height: 100,
top: 0,
left: 0,
right: 0
},
bottomButtonsContainer: {
position: "absolute",
height: 100,
bottom: 0,
left: 0,
right: 0
},
authorizationContainer: {
flex: 1,
alignItems: "center",
justifyContent: "center"
},
notAuthorizedText: {
textAlign: "center",
fontSize: 16
}
});
QRScanner.propTypes = {
isRepeatScan: PropTypes.bool,
onRead: PropTypes.func,
maskColor: PropTypes.string,
borderColor: PropTypes.string,
cornerColor: PropTypes.string,
borderWidth: PropTypes.number,
cornerBorderWidth: PropTypes.number,
cornerBorderLength: PropTypes.number,
rectHeight: PropTypes.number,
rectWidth: PropTypes.number,
isCornerOffset: PropTypes.bool, //Whether the corners are offset
cornerOffsetSize: PropTypes.number,
bottomHeight: PropTypes.number,
scanBarAnimateTime: PropTypes.number,
scanBarColor: PropTypes.string,
scanBarImage: PropTypes.any,
scanBarHeight: PropTypes.number,
scanBarMargin: PropTypes.number,
hintText: PropTypes.string,
hintTextStyle: PropTypes.object,
hintTextPosition: PropTypes.number,
renderTopView: PropTypes.func,
renderBottomView: PropTypes.func,
isShowScanBar: PropTypes.bool,
topViewStyle: PropTypes.object,
bottomViewStyle: PropTypes.object,
flashMode: PropTypes.bool,
finderX: PropTypes.number,
finderY: PropTypes.number,
zoom: PropTypes.number,
translucent: PropTypes.bool,
cameraType: PropTypes.string,
vibrate: PropTypes.bool,
};