您的位置:首页 > Web前端 > React

React Native 扫码组件react-native-camera与自定义UI界面动画套装

2018-01-19 15:24 921 查看
扫码这个功能在普通项目中用到的案例还是比较多的,签到、加好友、WebView跳转等等

针对扫码这个功能,react-native的前辈们已经封装好了可以跨平台的组件

react-native-camera

亲测是非常好用的,虽然有很多提Issue,但是最新的版本还是比较稳定的

给大家说一下我在用的时候遇到的一个自己挖的坑

因为我的项目有不止一个界面用到了这个功能,所以我在不同的导航器中用到了同一个界面,界面的key值也是相同的,导航倒是没有出现错乱,但是在打开Camera的时候会出现白屏,相机始终不能渲染出来,当然对Key值进行区分,这个问题也就解决了,刚开始以为是组件的问题,去官网一顿找相似的issue

好了,忘记这个issue继续说,UI,功能测试没问题之后发现这个customer界面是真的没做什么优化,真的很丑,所以,拿来微信的扫一扫功能来参考一下



经过对一些功能的筛选,我们对一些细节进行了模仿

先看一下效果吧



说一下具体进行的模仿模块

1、四周阴影和中间全透明的效果实现

实现这个效果我走了点弯路,实现方法也是比较麻烦,先给大家分享一下,我是将界面分成了5部分(View),中间框是一部分,四周是一部份

2、四个绿色的边框角

这四个边框角的原型是两个View,每个View是一条线

<View style={{ position: 'absolute', left: 0, top: 0 }}>
<View style={{ height: 2, width: px2dp(60), backgroundColor: '#37b44a' }} />
<View style={{ height: px2dp(60), width: 2, backgroundColor: '#37b44a' }} />
</View>


其实就是一横一竖,宽度和高度分别是2,这个是左上角的,右上角的边框是通过左上角的旋转角度而来

<View style={{ position: 'absolute', right: 1, top: -1, transform: [{rotate: '90deg'}] }}>
<View style={{ height: 2, width: px2dp(60), backgroundColor: '#37b44a' }} />
<View style={{ height: px2dp(60), width: 2, backgroundColor: '#37b44a' }} />
</View>


其他的处理方法类似

3、扫描线

扫描线就是一条线,然后赋予动画,

<Animated.View style={{ width: px2dp(500),
height: px2dp(2),
backgroundColor: '#37b44a',
transform: [{
translateY: this.state.top.interpolate({
inputRange: [0, 1],
outputRange: [0, px2dp(500)]
})
}]}}
/>


而且这个动画是由setInterval定时器进行驱动的

setInterval(function () {
Animated.timing(that.state.top, {
toValue: 1,
duration: 2200
}).start(() => that.setState({ top: new Animated.Value(0) }))
}, 2260)


接下来我把项目代码脱敏之后给大家共享出来,供参考

class ScannerCodeScreen extends Component {
static navigationOptions = ({ navigation }) => {
return ({
title: '二维码扫描',
...ApplicationStyles.blackHeaderStyle,
headerLeft: <HeaderLeft navigation={navigation} color={Colors.C8} />
})
}

constructor (props) {
super(props)
this.state = {
firstLoad: true,
top: new Animated.Value(0),
isSigned: false
}
/** object */
this.resultUrl = null
/** function */
this.onBarCodeRead = this.onBarCodeRead.bind(this)
this.interval = null
}

componentDidMount () {
}

componentWillReceiveProps (nextProps) {
if (!this.props.isFocused && nextProps.isFocused) {
this.onFocus()
}
if (this.props.isFocused && !nextProps.isFocused) {
this.onBlur()
}
}

onFocus () {
this.props.toggleTabBarAction(false)
/** 获取视频、现场首页信息 */
if (this.state.firstLoad) {
this.setState({ firstLoad: false })
}
/** 定时器触发动画 */
const that = this
this.interval =
setInterval(function () { Animated.timing(that.state.top, { toValue: 1, duration: 2200 }).start(() => that.setState({ top: new Animated.Value(0) })) }, 2260)
}

onBlur () {
/** 清除定时任务 */
clearInterval(this.interval)
}

getQueryString (url, name) {
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i')
var r = url.substr(1).match(reg)
if (r != null) {
return unescape(r[2])
}
return null
}

onBarCodeRead (e) {
/** 避免多次提交 */
console.log(e)
if (!this.resultUrl || this.resultUrl !== e.data) {
if (e.data.indexOf('http://www.baidu.com/') !== 0) {
this.props.toastAction('请扫描正确的二维码')
} else {
this.resultUrl = e.data
const id = this.getQueryString(e.data, 'id')
this.props.navigation.navigate('applicationMessage', { receiver: id })
this.resultUrl = null
}
}
}

barcodeReceived (e) {
console.log('Barcode: ' + e.data)
console.log('Type: ' + e.type)
}

render () {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }} >
<View>
<Camera
ref={(cam) => {
this.camera = cam
}}
onBarCodeRead={this.onBarCodeRead.bind(this)}
style={{ width, height, marginTop: 40 }}
aspect={Camera.constants.Aspect.fill}
/>
<View style={{ position: 'absolute', left: 0, right: 0, top: 0, bottom: 0 }}>
<View style={{ height: (height - px2dp(600)) / 2, backgroundColor: 'black', opacity: 0.5 }} />
<View style={{ flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'center' }}>
<View style={{ height: px2dp(500), width: (width - px2dp(500)) / 2, backgroundColor: 'black', opacity: 0.5 }} />
<View style={{ height: px2dp(500), width: px2dp(500) }} >
<View style={{ position: 'absolute', left: 0, top: 0 }}> <View style={{ height: 2, width: px2dp(60), backgroundColor: '#37b44a' }} /> <View style={{ height: px2dp(60), width: 2, backgroundColor: '#37b44a' }} /> </View>
<View style={{ position: 'absolute', right: 1, top: -1, transform: [{rotate: '90deg'}] }}> <View style={{ height: 2, width: px2dp(60), backgroundColor: '#37b44a' }} /> <View style={{ height: px2dp(60), width: 2, backgroundColor: '#37b44a' }} /> </View>
<View style={{ position: 'absolute', left: 1, bottom: -1, transform: [{rotateZ: '-90deg'}] }}>
<View style={{ height: 2, width: px2dp(60), backgroundColor: '#37b44a' }} />
<View style={{ height: px2dp(60), width: 2, backgroundColor: '#37b44a' }} />
</View>
<View style={{ position: 'absolute', right: 0, bottom: 0, transform: [{rotateZ: '180deg'}] }}>
<View style={{ height: 2, width: px2dp(60), backgroundColor: '#37b44a' }} />
<View style={{ height: px2dp(60), width: 2, backgroundColor: '#37b44a' }} />
</View>
<Animated.View style={{ width: px2dp(500),
height: px2dp(2),
backgroundColor: '#37b44a',
transform: [{
translateY: this.state.top.interpolate({
inputRange: [0, 1],
outputRange: [0, px2dp(500)]
})
}]}} />
</View>
<View style={{ height: px2dp(500), width: (width - px2dp(500)) / 2, backgroundColor: 'black', opacity: 0.5 }} />
</View>
<View style={{ flex: 1, backgroundColor: 'black', opacity: 0.5, alignItems: 'center' }} >
<Text style={{ fontSize: FontSize(28), color: Colors.C5, marginTop: px2dp(40) }}>将二维码放入框内,即可自动扫描</Text>
</View>
</View>
</View>
</View>
)
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  react-native 扫码 动画