摘要:当组件被成功调用显示时,组件主要分为两块,拍照和预览。给定一个拍照照片的路径值,即组件的,如果当前组件存在一个照片的存储路径,就显示预览界面,如不存在就显示拍照界面。而的值通过拍照成功的或者取消的状态去控制创建与删除。
关联文章
从0到1打造一款react-native App(一)环境配置
从0到1打造一款react-native App(二)Navigation+Redux
项目地址:https://github.com/jiwenjiang...
拍照(摄像)需求拍照的主要需求是在拍照后,不将照片在系统相册中显示出来,android拍照后会默认存储在DCIM文件夹当中,而这次主要需要做的就是把照片放在自定义的文件夹当中。
react-native-camera拍照的第三方包有很多,比如react-native-image-picker,这个调用的是系统相机,用法比较简单,但是拓展性较差,不管是这次项目主要的需求(拍照后不在系统相册显示),还是本身拍照时的一些定制化的需求,类似微信拍照那种,都不容易实现,因此选择了react-native-camera。
最新版的react-native-camera(v 1.1.x)已经支持了人脸识别,文字识别等功能,还是很强大的,这些功能可能日后都会用得到,不过因为一些版本和平台的原因之后会换成expo的camera,这里暂时还是介绍rn的camera(v 0.7)。
组件二次封装:
import React, { Component } from "react"; import { Dimensions, StyleSheet, Button, Text, ImageBackground, View, TouchableOpacity } from "react-native"; import Camera from "react-native-camera"; import Icon from "react-native-vector-icons/MaterialIcons"; import { deleteFile, mkdir, readPath } from "../../service/utils/fileOperations"; import RNFS from "react-native-fs"; import moment from "moment/moment"; class RNCamera extends Component { constructor(props) { super(props); this.state = { hidden: false, currentImage: null }; } async takePicture() { const options = {}; const { path: currentImage } = await this.camera.capture({ metadata: options }); this.setState({ currentImage }); } back() { this.setState({ currentImage: null, hidden: true }); } async check() { const [date, unixTime] = [moment().format("YYYY/MM/DD"), moment().unix()]; const dir = `${RNFS.DocumentDirectoryPath}/photo/${date}`; await mkdir(dir); const url = `${dir}/${unixTime}.jpg`; await RNFS.moveFile(this.state.currentImage, url); console.log(await readPath(dir)); this.setState({ currentImage: null }); } cancel() { deleteFile(this.state.currentImage); this.setState({ currentImage: null }); } render() { const { currentImage, hidden } = this.state; return ({currentImage ? ); } } const styles = StyleSheet.create( { container: { flex: 1, flexDirection: "row" }, preview: { flex: 1, justifyContent: "center", flexDirection: "row", alignItems: "flex-end" }, capture: { flex: 0, backgroundColor: "rgba(255, 255, 255, 0.3)", borderRadius: 25, margin: 20, marginBottom: 30, width: 50, height: 50, alignItems: "center", justifyContent: "center", zIndex: 1 }, photo: { flex: 1, justifyContent: "center", flexDirection: "row", alignItems: "flex-end" }, hidden: { display: "none" } } ); export default RNCamera;: this.cancel()}> this.check()}> { this.camera = cam; }} style={styles.preview} aspect={Camera.constants.Aspect.fill} captureTarget={Camera.constants.CaptureTarget.temp} > }this.back()}> this.takePicture()}>
没有对react-native-camera做过多的配置,需要注意的配置是captureTarget属性。在v0.7版本的camera当中,captureTarget的可选配置项有4种。
Camera.constants.CaptureTarget.cameraRoll(默认,存储在系统相册中)
Camera.constants.CaptureTarget.disk(存储在磁盘中,这是官方推荐的存储方式,会提升拍照的响应速度)
Camera.constants.CaptureTarget.temp (存储在临时文件夹,当前项目选择方案)
Camera.constants.CaptureTarget.memory (以base64的形式存储在内存当中,这个选项在之后的版本已经被废弃了,不过0.7版本还是可以用的)
实现基本思路是,通过外层调用来控制整个组件的样式值,来管理组件的显示与隐藏,即组件state的hidden属性。当组件被成功调用显示时,组件主要分为两块,拍照和预览。给定一个拍照照片的路径值,即组件state的currentImage,如果当前组件存在一个照片的存储路径,就显示预览界面,如不存在就显示拍照界面。而currentImage的值通过拍照成功的Promise或者取消的状态去控制创建与删除。
拍照时去创建currentImage
async takePicture() { const options = {}; const { path: currentImage } = await this.camera.capture({ metadata: options }); this.setState({ currentImage }); }
隐藏组建,返回调用界面
back() { this.setState({ currentImage: null, hidden: true }); }
拍照完成后预览照片及确认存储
async check() { const [date, unixTime] = [moment().format("YYYY/MM/DD"), moment().unix()]; const dir = `${RNFS.DocumentDirectoryPath}/photo/${date}`; await mkdir(dir); const url = `${dir}/${unixTime}.jpg`; await RNFS.moveFile(this.state.currentImage, url); console.log(await readPath(dir)); this.setState({ currentImage: null }); }
存储这里用到了react-native-fs,这个第三方包就不过多介绍了,都是一些基础的文件操作,比较好理解。通过在文件路径下新建photo/xxxx-xx-xx的文件夹,确保每天拍摄的照片存放在当日的文件夹,方便后续的文件预览时的筛选。在照片拍摄完毕后,react-native-camera会将拍摄的照片存放至临时文件夹,而这里需要做的就是将临时文件夹的照片移动至我们的目标文件夹,这里顺便说一下,文件move操作的性能是优于read+write的,这里切记用move。关于android文件存储这里推荐一篇介绍的比较详细的文章https://juejin.im/post/58b557...。
拍照完成后预览照片及放弃存储
cancel() { deleteFile(this.state.currentImage); this.setState({ currentImage: null }); }
操作预览:
照片回显在照片回显时,检测文件夹,读取照片
const mkdir = async (url) => { const dirExists = await RNFS.exists(url); if (dirExists) { return new Promise(resolve => resolve(dirExists)); } await RNFS.mkdir(url); return new Promise(resolve => resolve(url)); }; async function storageFile() { const date = moment().format("YYYY/MM/DD"); const url = `${RNFS.DocumentDirectoryPath}/photo/${date}`; await mkdir(url); const files = await readPath(url); return files; }二维码扫描
react-native-camera支持对各种条形码的扫描识别,主要的属性有两个
barCodeTypes={[Camera.constants.BarCodeType.qr]} //扫码的类型
onBarCodeRead={this.props.onScanResultReceived} //扫码成功后的回调
项目这里直接把https://www.jianshu.com/p/347... 这篇文章中二次封装好的一个二维码扫描的组件复制了过来。主要是视图层的二次封装,有兴趣的同学也可以自己封装。
之后会把react-native-camera替换成expo中的camera,换完之后会继续在这篇camera的文章中更新,也欢迎正在学习的同学一起交流~
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/95520.html
摘要:今天这篇文章要介绍的是一个酷炫的进度条的设计和实现,在进度的文字内容颜色以及切换的图片等都可以自由设置。那么下面我们就开始从无到有实现一下这个酷炫的进度效果吧。三利用与来实现进度效果。四利用阻尼动画实现进度条回弹效果。 showImg(/img/remote/1460000006465670); 今天这篇文章要介绍的是一个酷炫的进度条的设计和实现,在进度的文字内容、颜色以及切换的图片等...
阅读 1999·2023-04-26 02:15
阅读 2231·2021-11-19 09:40
阅读 936·2021-10-27 14:13
阅读 3220·2021-08-23 09:44
阅读 3572·2019-12-27 12:24
阅读 587·2019-08-30 15:53
阅读 1102·2019-08-30 10:53
阅读 2105·2019-08-26 12:14