如何使用react-native-image-crop-picker建立一个图像采集器

1,042 阅读5分钟

在我使用React Native的经验中,我发现自己最常做的任务之一是建立从用户设备上传图片的功能。如果你以前没有做过,这可能是一个挑战。

在本教程中,我们将演示如何使用React Native Image Crop Picker,使你的用户能够从他们的设备中选择图片,或使用设备的摄像头来捕捉和上传实时照片到你的应用程序。

为了展示react-native-image-crop-picker ,我们将创建一个可重复使用的图像采摘器组件,处理从媒体库中选择图像或使用相机拍摄新图像的权限。

在本教程结束时,你应该像这样使用图像挑选器组件。

import * as React from 'react';
import {View} from 'react-native';
import {ImageOrVideo} from 'react-native-image-crop-picker';
import {Avatar} from './Avatar';

export const Profile = () => {
  const onAvatarChange = (image: ImageOrVideo) => {
    console.log(image);
    // upload image to server here 
  };
  return (
        <Avatar
          onChange={onAvatarChange}
          source={require('./avatar-placeholder.png')}
        />
  );
};

下面是一个完成结果的简单演示。

Demo of Final Result

选择合适的React Native图像采集器

有两个流行的库,你可以用来实现图像采集器组件。[react-native-image-picker](https://github.com/react-native-image-picker/react-native-image-picker)react-native-image-crop-picker 。React Native Image Picker是另一个React Native模块,用于从设备库或相机中选择媒体。那么,为什么要使用React Native Image Crop Picker?

使用react-native-image-crop-picker 的好处是,与react-native-image-picker 不同,它能让你对图片进行裁剪和压缩。这在构建iOS应用时尤其关键,因为上传大文件可能会带来性能问题。压缩和裁剪图片对网速低的用户也有帮助。

安装react-native-image-crop-picker

让我们使用TypeScript模板创建一个新的React Native项目。

npx react-native init ImagePickerDemo  --template react-native-template-typescript

接下来,安装react-native-image-crop-picker

yarn add react-native-image-crop-picker 

因为react-native-image-crop-picker 自带一些原生依赖,我们需要安装pod ,并重建应用程序。

cd ios && pod install && cd ..

要使用react-native-image-crop-picker ,你应该在info.plist ,添加以下配置。

<key>NSPhotoLibraryUsageDescription</key>
<string>$(PRODUCT_NAME) would like to upload photos from your photo gallery</string>
<key>NSCameraUsageDescription</key>
<string>$(PRODUCT_NAME) requires to access camera for uploading photos to your profile or posts</string>
<key>NSMicrophoneUsageDescription</key>
<string>$(PRODUCT_NAME) requires to access Audio recording to record and uplod videos</string>

NSPhotoLibraryUsageDescription 配置描述了你为什么需要访问用户照片,以及你为什么要访问相机。如果你只想访问设备库中的图片,你不需要添加NSMicrophoneUsageDescriptionNSCameraUsageDescription 键。

现在我们准备好构建和打开应用程序了。

yarn ios 

安卓配置

react-native-image-crop-picker 的安卓配置如下。

首先,添加useSupportLibrary (android/app/build.gradle)。

android {
    ...

    defaultConfig {
        ...
        vectorDrawables.useSupportLibrary = true
        ...
    }
    ...
}

如果你想在你的项目中使用相机选取器,请在app/src/main/AndroidManifest.xml 中添加以下内容。

    • <uses-permission android:name="android.permission.CAMERA"/>

如果你想让用户使用他们的前置摄像头,你也应该添加以下内容到app/src/main/ AndroidManifest.xml

    • <uses-feature android:name="android.hardware.camera" android:required="false" />
    • <uses-feature android:name="android.hardware.camera.front" android:required="false" />

值得一提的是,你需要升级到Android SDK 26+。如果你使用React Native 0.64,你就安全了。如果不是这样的话,请确保更新android/app/build.gradle

android {
    compileSdkVersion 27
    buildToolsVersion "27.0.3"
    ...

    defaultConfig {
      ...
      targetSdkVersion 27
      ...
    }
    ...
}

构建一个头像资料更新

在本节中,我们将建立一个简单的屏幕来更新用户的头像。我们的想法是创建一个图片选择器组件,让用户上传一个新的头像。头像组件应该从Image 组件中扩展其prop ,我们将添加onChange ,以处理从用户设备上传新图片。

我们将用一个可按组件来包装我们的图片,以便在用户按下他们的个人资料图片时打开照片库。打开图片库就像从react-native-image-crop-picker 中调用openPicker 函数一样容易。

让我们添加一个裁剪功能,让用户在上传前对所选图片进行裁剪。

import React from 'react';
import {Image, ImageProps, StyleSheet, TouchableOpacity} from 'react-native';
import ImagePicker, {ImageOrVideo} from 'react-native-image-crop-picker';

interface AvatarProps extends ImageProps {
  onChange?: (image: ImageOrVideo) => void;
}

export const Avatar = (props: AvatarProps) => {
  const [uri, setUri] = React.useState(props.source?.uri || undefined);

  const pickPicture = () => {
    ImagePicker.openPicker({
      width: 300,
      height: 400,
      cropping: true,
    }).then(image => {
      setUri(image.path);
      props.onChange?.(image);
    });
  };
  return (
    <TouchableOpacity onPress={pickPicture}>
      <Image
          style={styles.avatar}
          {...props}
          source={uri ? {uri} : props.source}
        />
    </TouchableOpacity>
  );
};

const styles = StyleSheet.create({
  avatar: {
    paddingTop: 20,
    height: 100,
    width: 100,
    borderRadius: 100,
    padding: 20,
  },
});

现在我们的头像组件已经可以使用了,让我们创建一个个人资料屏幕,并更新用户的个人资料图片。

import * as React from 'react';
import {StatusBar, StyleSheet, View} from 'react-native';
import {ImageOrVideo} from 'react-native-image-crop-picker';
import {Avatar} from './Avatar';
import {UserInfo} from './UserInfo';

export const Profile = () => {
  const onAvatarChange = (image: ImageOrVideo) => {
    console.log(image);
    // upload image to server here 
  };
  return (
    <View style={styles.scroll}>
      <StatusBar barStyle="dark-content" />
      <View style={styles.userRow}>
        <Avatar
          onChange={onAvatarChange}
          source={require('./avatar-placeholder.png')}
        />
        <UserInfo />
      </View>
      <View style={styles.content} />
    </View>
  );
};

const styles = StyleSheet.create({
  scroll: {
    backgroundColor: 'white',
    flex: 1,
  },
  userRow: {
    alignItems: 'center',
    padding: 15,
    marginTop: 70,
  },
  content: {
    flex: 1,
    backgroundColor: '#d8d8db',
  },
});

这里我们把onChange 道具添加到头像上。这将为我们提供所有的文件信息,我们可以很容易地用它来上传至我们的服务器。下面是结果。

Onchange Prop Added to Avatar

使用设备摄像头拍摄照片

假设我们想让用户能够从他们的相机中拍一张照片并上传。我们还应该让用户选择从资料库中选择一张照片或使用他们的设备摄像头拍摄一张新的照片。

注意,openCamera 不会在iOS模拟器上工作。要测试它,你应该在一个真实的设备上运行该应用程序。

为了使用相机,我们只需要调用openCamera 函数,而不是openPicker

import React from 'react';
import {
  Image,
  ImageProps,
  Pressable,
  SafeAreaView,
  StyleSheet,
  Text,
  TouchableOpacity,
} from 'react-native';
import ImagePicker, {ImageOrVideo} from 'react-native-image-crop-picker';
import Modal from 'react-native-modal';
import {CameraIcon, ImageIcon} from './icons';

interface AvatarProps extends ImageProps {
  onChange?: (file: ImageOrVideo) => void;
}

export const Avatar = (props: AvatarProps) => {
  const [uri, setUri] = React.useState(props.source?.uri || undefined);
  const [visible, setVisible] = React.useState(false);
  const close = () => setVisible(false);
  const open = () => setVisible(true);
  const chooseImage = () => {
    ImagePicker.openPicker({
      width: 300,
      height: 400,
      cropping: true,
    })
      .then(image => {
        setUri(image.path);
        props.onChange?.(image);
      })
      .finally(close);
  };

  const openCamera = () => {
    ImagePicker.openCamera({
      width: 300,
      height: 400,
      cropping: true,
    })
      .then(image => {
        setUri(image.path);
        props.onChange?.(image);
      })
      .finally(close);
  };

  return (
    <>
      <TouchableOpacity onPress={chooseImage}>
        <Image
          style={styles.avatar}
          {...props}
          source={uri ? {uri} : props.source}
        />
      </TouchableOpacity>
      <Modal
        isVisible={visible}
        onBackButtonPress={close}
        onBackdropPress={close}
        style={{justifyContent: 'flex-end', margin: 0}}>
        <SafeAreaView style={styles.options}>
          <Pressable style={styles.option} onPress={chooseImage}>
            <ImageIcon />
            <Text>Library </Text>
          </Pressable>
          <Pressable style={styles.option} onPress={openCamera}>
            <CameraIcon />
            <Text>Camera</Text>
          </Pressable>
        </SafeAreaView>
      </Modal>
    </>
  );
};

const styles = StyleSheet.create({
  avatar: {
    paddingTop: 20,
    height: 100,
    width: 100,
    borderRadius: 100,
    padding: 20,
  },

  options: {
    backgroundColor: 'white',
    flexDirection: 'row',
    borderTopRightRadius: 30,
    borderTopLeftRadius: 30,
  },
  option: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
});

下面是我们完成的React Native应用程序的演示。

Demo of Final Result

结语

现在,只要你需要在React Native应用中建立一个图片上传功能,你就可以复制粘贴这个图片采集器组件。

如果你想玩这个项目,完整的代码可以在这个Github repo中找到。

The postHow to build an image picker using react-native-image-crop-pickerappeared first onLogRocket Blog.