当前位置: 首页 > article >正文

React Native 全栈开发实战班 -原生功能集成之相机与图片

在移动应用中,相机功能图片选择 是非常常见的需求,用户可以通过相机拍照或从相册中选择图片。React Native 提供了多种方式来实现相机和图片选择功能,包括使用第三方库(如 react-native-image-picker)和调用原生模块。本章节将详细介绍如何使用 react-native-image-picker 库来实现相机和图片选择功能,包括基本用法、图片处理、权限管理以及自定义相机界面。


2.1 相机与图片选择概述

在移动应用中,相机和图片选择功能主要用于以下场景:

  • 用户头像设置: 用户可以通过相机拍照或从相册中选择图片作为头像。
  • 图片上传: 用户可以上传图片到服务器,如发布动态、分享照片等。
  • 扫描二维码: 通过相机扫描二维码或条形码。
  • 图片编辑: 用户可以对图片进行编辑,如裁剪、旋转、添加滤镜等。

React Native 提供了多种方式来实现相机和图片选择功能:

  1. 第三方库:react-native-image-picker, react-native-camera, react-native-image-crop-picker 等,提供了封装好的 API,可以快速实现相机和图片选择功能。
  2. 原生模块: 可以通过原生代码实现自定义相机和图片选择功能,适用于需要高度定制化的场景。

本章节将重点介绍如何使用 react-native-image-picker 库来实现相机和图片选择功能。


2.2 使用 react-native-image-picker

react-native-image-picker 是一个流行的第三方库,用于实现相机和图片选择功能,支持 iOS 和 Android 平台。

2.2.1 安装 react-native-image-picker
npm install react-native-image-picker

链接原生依赖(React Native 0.60 及以上版本自动链接):

cd ios
pod install
cd ..
2.2.2 配置权限

iOS:

Info.plist 文件中添加相机和相册权限说明。

<key>NSCameraUsageDescription</key>
<string>需要访问相机以拍摄照片</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>需要访问相册以选择照片</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>需要保存照片到相册</string>

Android:

AndroidManifest.xml 文件中添加相机和存储权限。

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

注意: 对于 Android 6.0 及以上版本,还需要在代码中动态请求权限。

2.2.3 基本用法

请求相机或图片选择:

import { launchCamera, launchImageLibrary } from 'react-native-image-picker';

const handleChooseImage = () => {
  const options = {
    mediaType: 'photo',
    cameraType: 'back',
    maxWidth: 1080,
    maxHeight: 1080,
    quality: 0.8,
  };

  launchImageLibrary(options, (response) => {
    if (response.didCancel) {
      console.log('用户取消选择图片');
    } else if (response.errorCode) {
      console.error('图片选择错误:', response.errorMessage);
    } else {
      const asset = response.assets[0];
      console.log('选择的图片:', asset);
      // 处理选择的图片
    }
  });
};

const handleTakePhoto = () => {
  const options = {
    mediaType: 'photo',
    cameraType: 'back',
    saveToPhotos: true,
    maxWidth: 1080,
    maxHeight: 1080,
    quality: 0.8,
  };

  launchCamera(options, (response) => {
    if (response.didCancel) {
      console.log('用户取消拍照');
    } else if (response.errorCode) {
      console.error('拍照错误:', response.errorMessage);
    } else {
      const asset = response.assets[0];
      console.log('拍摄的图片:', asset);
      // 处理拍摄的图片
    }
  });
};

示例:

import React from 'react';
import { View, Button, Image, StyleSheet, Alert } from 'react-native';
import { launchCamera, launchImageLibrary } from 'react-native-image-picker';

const CameraExample = () => {
  const handleTakePhoto = () => {
    const options = {
      mediaType: 'photo',
      cameraType: 'back',
      saveToPhotos: true,
      maxWidth: 1080,
      maxHeight: 1080,
      quality: 0.8,
    };

    launchCamera(options, (response) => {
      if (response.didCancel) {
        console.log('用户取消拍照');
      } else if (response.errorCode) {
        Alert.alert('拍照错误', response.errorMessage);
      } else {
        const asset = response.assets[0];
        console.log('拍摄的图片:', asset);
        // 处理拍摄的图片
      }
    });
  };

  const handleChooseImage = () => {
    const options = {
      mediaType: 'photo',
      maxWidth: 1080,
      maxHeight: 1080,
      quality: 0.8,
    };

    launchImageLibrary(options, (response) => {
      if (response.didCancel) {
        console.log('用户取消选择图片');
      } else if (response.errorCode) {
        Alert.alert('图片选择错误', response.errorMessage);
      } else {
        const asset = response.assets[0];
        console.log('选择的图片:', asset);
        // 处理选择的图片
      }
    });
  };

  return (
    <View style={styles.container}>
      <Button title="拍照" onPress={handleTakePhoto} />
      <Button title="选择图片" onPress={handleChooseImage} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
});

export default CameraExample;

解释:

  • launchCamera 方法: 打开相机进行拍照。
  • launchImageLibrary 方法: 打开相册选择图片。
  • options 参数: 配置相机或图片选择选项,如媒体类型、图片尺寸、质量等。
  • 回调函数: 处理用户取消、错误或选择结果。
2.2.4 处理选择的图片

react-native-image-picker 返回的图片信息包含图片的 URI、宽度、高度、大小等信息。可以使用 react-native-fast-image 或其他图片加载库来显示图片,并根据需要进行后续处理,如上传到服务器或保存到本地。

2.2.4.1 显示选择的图片

以下是如何使用 react-native-fast-image 显示用户选择的图片:

import React from 'react';
import { View, Button, StyleSheet, Alert } from 'react-native';
import { launchCamera, launchImageLibrary } from 'react-native-image-picker';
import FastImage from 'react-native-fast-image';

const CameraExample = () => {
  const [image, setImage] = React.useState(null);

  const handleTakePhoto = () => {
    const options = {
      mediaType: 'photo',
      cameraType: 'back',
      saveToPhotos: true,
      maxWidth: 1080,
      maxHeight: 1080,
      quality: 0.8,
    };

    launchCamera(options, (response) => {
      if (response.didCancel) {
        console.log('用户取消拍照');
      } else if (response.errorCode) {
        Alert.alert('拍照错误', response.errorMessage);
      } else {
        const asset = response.assets[0];
        console.log('拍摄的图片:', asset);
        setImage(asset);
      }
    });
  };

  const handleChooseImage = () => {
    const options = {
      mediaType: 'photo',
      maxWidth: 1080,
      maxHeight: 1080,
      quality: 0.8,
    };

    launchImageLibrary(options, (response) => {
      if (response.didCancel) {
        console.log('用户取消选择图片');
      } else if (response.errorCode) {
        Alert.alert('图片选择错误', response.errorMessage);
      } else {
        const asset = response.assets[0];
        console.log('选择的图片:', asset);
        setImage(asset);
      }
    });
  };

  return (
    <View style={styles.container}>
      <View style={styles.buttonContainer}>
        <Button title="拍照" onPress={handleTakePhoto} />
        <Button title="选择图片" onPress={handleChooseImage} />
      </View>
      {image && (
        <View style={styles.imageContainer}>
          <FastImage
            source={{ uri: image.uri }}
            style={styles.image}
            resizeMode={FastImage.resizeMode.cover}
          />
        </View>
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  buttonContainer: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    width: '100%',
    marginBottom: 20,
  },
  imageContainer: {
    width: 300,
    height: 300,
    borderRadius: 10,
    overflow: 'hidden',
    marginBottom: 20,
  },
  image: {
    width: '100%',
    height: '100%',
  },
});

export default CameraExample;

解释:

  • setImage(asset): 将选择的图片信息存储在组件状态中。
  • FastImage: 使用 react-native-fast-image 显示图片,asset.uri 是图片的 URI。
  • resizeMode: 设置图片的缩放模式,如 cover, contain, stretch 等。
2.2.4.2 图片上传

用户选择或拍摄图片后,通常需要将图片上传到服务器。以下是如何实现图片上传的示例:

import React from 'react';
import { View, Button, StyleSheet, Alert } from 'react-native';
import { launchCamera, launchImageLibrary } from 'react-native-image-picker';
import axios from 'axios';

const CameraExample = () => {
  const [image, setImage] = React.useState(null);

  const handleTakePhoto = () => {
    const options = {
      mediaType: 'photo',
      cameraType: 'back',
      saveToPhotos: true,
      maxWidth: 1080,
      maxHeight: 1080,
      quality: 0.8,
    };

    launchCamera(options, (response) => {
      if (response.didCancel) {
        console.log('用户取消拍照');
      } else if (response.errorCode) {
        Alert.alert('拍照错误', response.errorMessage);
      } else {
        const asset = response.assets[0];
        setImage(asset);
        uploadImage(asset);
      }
    });
  };

  const handleChooseImage = () => {
    const options = {
      mediaType: 'photo',
      maxWidth: 1080,
      maxHeight: 1080,
      quality: 0.8,
    };

    launchImageLibrary(options, (response) => {
      if (response.didCancel) {
        console.log('用户取消选择图片');
      } else if (response.errorCode) {
        Alert.alert('图片选择错误', response.errorMessage);
      } else {
        const asset = response.assets[0];
        setImage(asset);
        uploadImage(asset);
      }
    });
  };

  const uploadImage = async (asset) => {
    const formData = new FormData();
    formData.append('file', {
      uri: asset.uri,
      type: asset.type,
      name: asset.fileName || 'image.jpg',
    });

    try {
      const response = await axios.post('https://example.com/upload', formData, {
        headers: {
          'Content-Type': 'multipart/form-data',
        },
      });
      Alert.alert('上传成功', `图片上传成功,图片ID: ${response.data.id}`);
    } catch (error) {
      Alert.alert('上传失败', '图片上传失败,请稍后重试');
    }
  };

  return (
    <View style={styles.container}>
      <View style={styles.buttonContainer}>
        <Button title="拍照" onPress={handleTakePhoto} />
        <Button title="选择图片" onPress={handleChooseImage} />
      </View>
      {image && (
        <View style={styles.imageContainer}>
          <FastImage
            source={{ uri: image.uri }}
            style={styles.image}
            resizeMode={FastImage.resizeMode.cover}
          />
        </View>
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  buttonContainer: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    width: '100%',
    marginBottom: 20,
  },
  imageContainer: {
    width: 300,
    height: 300,
    borderRadius: 10,
    overflow: 'hidden',
    marginBottom: 20,
  },
  image: {
    width: '100%',
    height: '100%',
  },
});

export default CameraExample;

解释:

  • uploadImage 函数: 使用 axios 发送 POST 请求,将图片上传到服务器。
  • FormData: 用于构建 multipart/form-data 请求体。
  • asset.uri: 图片的 URI,用于上传。
  • asset.type: 图片的 MIME 类型。
  • asset.fileName: 图片的文件名,如果未提供,则使用默认名称。
2.2.4.3 图片保存到相册

用户拍摄或选择的图片可以保存到相册中。

示例:

import { writeToFile, copyFile, saveToLibrary } from 'react-native-image-picker';

const saveImageToAlbum = async (asset) => {
  try {
    const result = await saveToLibrary(asset.uri);
    Alert.alert('保存成功', '图片已保存到相册');
  } catch (error) {
    Alert.alert('保存失败', '图片保存到相册失败');
  }
};

作者简介

前腾讯电子签的前端负责人,现 whentimes tech CTO,专注于前端技术的大咖一枚!一路走来,从小屏到大屏,从 Web 到移动,什么前端难题都见过。热衷于用技术打磨产品,带领团队把复杂的事情做到极简,体验做到极致。喜欢探索新技术,也爱分享一些实战经验,帮助大家少走弯路!

温馨提示:可搜老码小张公号联系导师


http://www.kler.cn/a/399276.html

相关文章:

  • 了解什么是Python(简介)
  • SpringBoot多环境配置的实现
  • 另外一种缓冲式图片组件的用法
  • http响应码https的区别
  • 时间序列分析——移动平均法、指数平滑法、逐步回归法、趋势外推法等(基于Python实现)
  • vue之axios根据某个接口创建实例,并设置headers和超时时间,捕捉异常
  • 希尔排序(C语言)
  • 基于STM32设计的大棚育苗管理系统(4G+华为云IOT)_265
  • 易考八股文之Elasticsearch合集
  • 微信小程序自定义顶部导航栏(适配各种机型)
  • IOException: Broken pipe与IOException: 远程主机强迫关闭了一个现有的连接
  • C语言项⽬实践-贪吃蛇
  • Asp.net Mvc 电脑销售系统
  • @ComponentScan:Spring Boot中的自动装配大师
  • Ubuntu下Xshell连接腾讯云服务器
  • 第26天进程(一)
  • 创建型设计模式与面向接口编程
  • w040基于web的社区医院信息平台
  • 【MYSQL】锁详解(全局锁、表级锁、行级锁)【快速理解】
  • STL关联式容器介绍
  • 预处理(1)(手绘)
  • 【Axure原型分享】轮播表格_开始暂停效果
  • 基于语法树的SQL自动改写工具开发系列(2)-使用PYTHON进行简单SQL改写的开发实战
  • LeetCode题解:18.四数之和【Python题解超详细】,三数之和 vs. 四数之和
  • redis类型介绍
  • docker .vhdx文件压缩