react-native中基于react-native-camera的扫一扫功能

react-native中基于react-native-camera的扫一扫功能

效果示例图

在这里插入图片描述

示例代码

/* eslint-disable react-native/no-inline-styles */
import React, {
  createRef,
  forwardRef,
  useEffect,
  useImperativeHandle,
  useRef,
  useState,
} from 'react';
import {
  StyleSheet,
  View,
  Modal,
  Image,
  TouchableOpacity,
  Text,
  ImageBackground,
  Animated,
  NativeModules,
  Platform,
  StatusBar,
} from 'react-native';
import { RNCamera } from 'react-native-camera';
import { pxToPd, pxToPdT } from '../../common/js/device';

const { StatusBarManager } = NativeModules;
// 状态栏高度
const StatusBarHeight = Platform.select({
  ios: StatusBarManager.HEIGHT,
  android: StatusBar.currentHeight,
});

const ScanQRCodeComponent = forwardRef((props, ref) => {
  const animation = useRef(new Animated.Value(0)).current;

  const [visible, setVisible] = useState(false);
  const [options, setOptions] = useState({
    success: null,
  });

  const hide = (type, value = '') => {
    setVisible(false);
    options.success({
      type: type,
      data: value,
    });
  };
  const show = params => {
    setOptions({
      ...options,
      success: params.success,
    });
    setVisible(true);
  };
  //点击关闭
  const closeCameraHandle = () => {
    console.log('[关闭]');
    hide('close', null);
  };

  const handleBarcodeScanned = ({ data }) => {
    hide('submit', data);
  };

  const translateY = animation.interpolate({
    inputRange: [0, 1],
    outputRange: [20, 170], // Instead of percentages, use actual pixel values.
  });

  useImperativeHandle(ref, () => ({
    show,
  }));

  useEffect(() => {
    Animated.loop(
      Animated.sequence([
        Animated.timing(animation, {
          toValue: 1,
          duration: 1500,
          useNativeDriver: true,
        }),
        Animated.timing(animation, {
          toValue: 0,
          duration: 1500,
          useNativeDriver: true,
        }),
      ]),
    ).start();
  }, [visible]);

  return (
    <>
      <Modal visible={visible} animationType="fade" transparent>
        <View style={styles.cameraWrap}>
          <View style={styles.cameraBlock}>
            {/* 自定义头部 */}
            <View style={{ width: '100%', backgroundColor: '#000' }}>
              <View style={{ width: '100%', height: StatusBarHeight }} />
              <View style={{ width: '100%' }}>
                <View
                  style={{
                    width: '93.6%',
                    height: pxToPd(70),
                    marginLeft: '3.2%',
                    flexDirection: 'row',
                  }}>
                  <View style={{ width: '25%', position: 'relative' }}>
                    <TouchableOpacity onPress={closeCameraHandle}>
                      <Image
                        style={{
                          width: pxToPd(38),
                          height: pxToPd(38),
                          position: 'absolute',
                          left: pxToPd(0),
                          top: pxToPd(16),
                        }}
                        source={require('../../common/images/back_white.png')}
                      />
                    </TouchableOpacity>
                  </View>
                  <View style={{ width: '50%' }}>
                    <Text
                      style={{
                        lineHeight: pxToPd(70),
                        textAlign: 'center',
                        fontSize: pxToPdT(36),
                        color: '#fff',
                        fontWeight: 'bold',
                      }}>
                      扫一扫
                    </Text>
                  </View>
                  <View
                    style={{
                      width: '25%',
                      alignItems: 'flex-end',
                      justifyContent: 'center',
                    }}
                  />
                </View>
              </View>
            </View>

            {/* 摄像机 */}
            <RNCamera
              style={styles.camera}
              onBarCodeRead={handleBarcodeScanned}
              captureAudio={false}
            />
            {/* 相框 */}
            <View style={styles.scanBox}>
              <ImageBackground
                style={styles.scanBoxBg}
                source={require('../../common/images/scan_box.png')}>
                <View style={styles.scanBlock}>
                  <Animated.View
                    style={[styles.scanLine, { transform: [{ translateY }] }]}
                  />
                </View>
              </ImageBackground>
            </View>
          </View>
        </View>
      </Modal>
    </>
  );
});
const styles = StyleSheet.create({
  cameraWrap: {
    flex: 1,
    position: 'absolute',
    top: 0,
    bottom: 0,
    left: 0,
    right: 0,
    zIndex: 9999,
    backgroundColor: 'rgba(0,0,0,0.6)',
  },
  cameraBlock: {
    flex: 1,
    position: 'relative',
  },
  closeCamera: {
    borderRadius: pxToPd(30),
    width: pxToPd(80),
    height: pxToPd(80),
    position: 'absolute',
    top: '10%',
    left: '3.2%',
    zIndex: 99,
  },
  camera: {
    width: '100%',
    height: '100%',
  },
  // 相框
  scanBox: {
    width: 200,
    height: 200,
    position: 'absolute',
    top: '50%',
    left: '50%',
    marginTop: -100,
    marginLeft: -100,
  },
  scanBoxBg: {
    width: '100%',
    height: '100%',
  },
  scanBlock: {
    width: '100%',
    height: '100%',
    position: 'relative',
    overflow: 'hidden',
  },
  scanLine: {
    position: 'absolute',
    height: pxToPd(24),
    width: '80%',
    left: '10%',
    backgroundColor: '#fff',
    borderRadius: pxToPd(6),
  },
});

export const scanCodeRef = createRef();

export default ScanQRCodeComponent;

页面中引入组件使用

 <ScanQRCodeComponent ref={scanCodeRef} />
scanCodeRef.current?.show({
      success: res => {
        console.log('{]', res);
        if (res.type === 'submit') {
          let code = res.data;
          if (code && code !== 'NaN') {
            console.log(code);
          } else {
            showToastRef.current.show({
              type: 'fail', //类型:success:成功;fail:失败
              title: '请正确扫码',
              content: '',
              success: () => {},
            });
          }
        }
      },
    });

版本

 "react": "18.2.0",
 "react-native": "0.72.3",
 "react-native-camera": "^4.2.1",
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值