React Native Android 全屏相机,同时保持正确的比例

时间:2021-05-27 15:41:30

标签: javascript android reactjs react-native android-camera

我想实现让相机预览占据整个屏幕的齐平外观,就像 Snapchat 对他们的应用程序所做的那样。问题是在预览接管屏幕时保持屏幕比例不变。有没有办法在本机反应中做到这一点?我的代码波纹管在底部生成一个带有黑条的预览,我必须保留它以便为相机预览提供正确的纵横比。 我假设我必须将预览的宽度负移出框架才能实现这一点,但我没有尝试过,我不确定这是否是正确的方法?


const { height, width } = Dimensions.get('window')

const CameraScreen = ({ navigation, route }) => {
    let checkMarkSet = null
    if (route.params) {
        checkMarkSet = true
    }

    // RATIO SETTER
    const [imagePadding, setImagePadding] = useState(0)
    const [ratio, setRatio] = useState('4:3') // default is 4:3
    const screenRatio = height / width
    const [isRatioSet, setIsRatioSet] = useState(false)
    async function prepareRatio() {
        let desiredRatio = '4:3' // Start with the system default
        // This issue only affects Android
        if (Platform.OS === 'android') {
            const ratios = await cameraRef.current.getSupportedRatiosAsync()
            let distances = {}
            let realRatios = {}
            let minDistance = null
            for (const ratio of ratios) {
                const parts = ratio.split(':')
                const ratioHeight = parseInt(parts[0])
                const ratioWidth = parseInt(parts[1])
                const realRatio = ratioHeight / ratioWidth
                realRatios[ratio] = realRatio
                // ratio can't be taller than screen, so we don't want an abs()
                const distance = screenRatio - realRatio
                distances[ratio] = realRatio
                if (minDistance == null) {
                    minDistance = ratio
                } else {
                    if (distance >= 0 && distance < distances[minDistance]) {
                        minDistance = ratio
                    }
                }
            }
            // set the best match
            desiredRatio = minDistance

            //  calculate the difference between the camera width and the screen height
            const remainder = Math.floor(
                (height - realRatios[desiredRatio] * width) / 2
            )

            // set the preview padding and preview ratio
            setImagePadding(remainder / 2)
            console.log(`okay look ${remainder / 2}`)
            setRatio(desiredRatio)
            // Set a flag so we don't do this
            // calculation each time the screen refreshes
            setIsRatioSet(true)
        }
    }

    const setCameraReady = async () => {
        if (!isRatioSet) {
            await prepareRatio()
        }
    }
    // RATIO SETTER

    const [type, setType] = useState(Camera.Constants.Type.back)
    const [activateCamera, setActivateCamera] = useState(false)
    const [video, setVideo] = useState('')
    const [showVideoModal, setShowVideoModal] = useState(false)
    const insets = useSafeAreaInsets()

    useFocusEffect(() => {
        if (navigation.isFocused()) {
            setActivateCamera(true)
        }
    })

    const [pic, setPic] = useState(null)

    const [showModal, setShowModal] = useState(false)

    const cameraRef = useRef()



    return (
        <View
            style={{
                ...styles.container,
                // paddingTop: Platform.OS === 'android' ? insets.top : null,
            }}
        >
            <StatusBar
                style=""
                translucent
                backgroundColor="rgba(255,255,255,0)"
            />
            <PinchGestureHandler onGestureEvent={onPinchGesture}>
                <Reanimated.View
                    style={{
                        flex: 1,
                        backgroundColor: 'black',
                        justifyContent: 'flex-start',
                        paddingBottom: imagePadding * 4,
                    }}
                >
                    {activateCamera && (
                        <Camera
                            style={{
                                // marginTop: imagePadding,
                                // marginBottom: imagePadding,
                                flex: 1,
                                // height: 733,
                            }}
                            ref={cameraRef}
                            type={type}
                            flashMode={flashMode}
                            zoom={zooming}
                            onCameraReady={setCameraReady}
                            ratio={ratio}
                            maxDuration={10000}
                            autoFocus="on"
                        >
                            <View
                                style={[
                                    styles.contentContainer,
                                    {
                                        paddingTop: insets.top,
                                        paddingBottom: insets.bottom,
                                        top: insets.top,
                                        bottom: insets.bottom,
                                    },
                                ]}
                            >
                                <View style={styles.topLeftCont}>
                                    <TouchableOpacity
                                        onPress={flipCameraHandler}
                                    >
                                        <Entypo
                                            name="loop"
                                            size={27}
                                            color="white"
                                            style={styles.flipIcon}
                                        />
                                    </TouchableOpacity>

                                    <TouchableOpacity
                                        onPress={flashSwitchHandler}
                                    >
                                        <Ionicons
                                            name={
                                                flashMode !== 'off'
                                                    ? 'flash'
                                                    : 'flash-off'
                                            }
                                            size={27}
                                            color="white"
                                            style={styles.cameraSettingsButton}
                                        />
                                    </TouchableOpacity>
                                </View>

                                <CameraButton
                                    style={{
                                        ...styles.floatingPlusCont,
                                        left: width / 2 - 45,
                                    }}
                                    onLongPress={beginRecording}
                                    onEndPress={endRecording}
                                    onTap={takePictureHandler}
                                />
                            </View>
                        </Camera>
                    )}
                </Reanimated.View>
            </PinchGestureHandler>
    )
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'flex-start',
    },
    contentContainer: {
        flex: 1,
        position: 'absolute',
        right: 0,
        left: 0,
    },
    camera: {
        flex: 1,
        flexDirection: 'row',
    },

    topLeftCont: {
        position: 'absolute',
        width: 45,
        top: 0,
        right: 10,
        borderRadius: 20,
        backgroundColor: 'rgba(184,184,184,0.42)',
        alignItems: 'center',
        justifyContent: 'space-between',
        // flexDirection: 'row',
        padding: 5,
    },
    flipIcon: {
        marginVertical: 7,
        transform: [
            {
                rotate: '90deg',
            },
        ],
    },
    cameraSettingsButton: { marginVertical: 7 },
    modal: {
        flex: 1,
        position: 'absolute',
        top: 0,
        right: 0,
        left: 0,
        bottom: 0,
    },
    takenImage: { flex: 1 },
    bottomCont: {
        flex: 1,
        justifyContent: 'flex-end',
        padding: 10,
    },
    bottomButtonsCont: {
        width: '100%',
        justifyContent: 'space-between',
        flexDirection: 'row',
        paddingHorizontal: 5,
    },
    floatingPlusCont: {
        bottom: 25,
        position: 'absolute',
        width: 90,
        height: 90,
        borderRadius: 45,
    },
    loadingView: {
        backgroundColor: 'rgba(0,0,0,0.4)',
        justifyContent: 'center',
        alignItems: 'center',
    },
})

export default CameraScreen

enter image description here

0 个答案:

没有答案
相关问题