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

news2024/11/22 23:32:02

在移动应用中,相机功能图片选择 是非常常见的需求,用户可以通过相机拍照或从相册中选择图片。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.coloradmin.cn/o/2245618.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

湛江市社保卡申领指南:手机获取电子照片回执单号

在湛江市&#xff0c;社保卡的申领流程已经实现了数字化&#xff0c;为市民带来了极大的便利。特别是通过手机获取数码照片回执单号&#xff0c;这一环节更是简化了申领过程。今天&#xff0c;我们将详细介绍如何不去照相馆&#xff0c;利用手机来获取数码照片回执单号&#xf…

第27天 安全开发-PHP应用TP 框架路由访问对象操作内置过滤绕过核心漏洞

时间轴 演示案例 TP 框架-开发-配置架构&路由&MVC 模型 TP 框架-安全-不安全写法&版本过滤绕过 TP 框架-开发-配置架构&路由&MVC 模型 参考&#xff1a; https://www.kancloud.cn/manual/thinkphp5_1 1、配置架构-导入使用 去thinkphp官网可以看到&…

【自动驾驶】数据集合集!

本文将为您介绍经典、热门的数据集&#xff0c;希望对您在选择适合的数据集时有所帮助。 1 Automatic-driving-Test 更新时间&#xff1a;2024-07-26 访问地址: GitHub 描述&#xff1a; 该模型使用 ultralytics yolo v8 和 deepsort 方法来检测车道与车轮的碰撞并跟踪车辆。…

Leetcode 完全二叉树的节点个数

不讲武德的解法 java 实现 class Solution {public int countNodes(TreeNode root) {if(root null) return 0;return countNodes(root.left) countNodes(root.right) 1;} }根据完全二叉树和满二叉树的性质做 class Solution {public int countNodes(TreeNode root) {if (r…

力扣面试题 - 24 插入

题目&#xff1a; 给定两个整型数字 N 与 M&#xff0c;以及表示比特位置的 i 与 j&#xff08;i < j&#xff0c;且从 0 位开始计算&#xff09;。 编写一种方法&#xff0c;使 M 对应的二进制数字插入 N 对应的二进制数字的第 i ~ j 位区域&#xff0c;不足之处用 0 补齐…

Elasticsearch 中的热点以及如何使用 AutoOps 解决它们

作者&#xff1a;来自 Elastic Sachin Frayne 探索 Elasticsearch 中的热点以及如何使用 AutoOps 解决它。 Elasticsearch 集群中出现热点的方式有很多种。有些我们可以控制&#xff0c;比如吵闹的邻居&#xff0c;有些我们控制得较差&#xff0c;比如 Elasticsearch 中的分片分…

Matlab多输入单输出之倾斜手写数字识别

本文主要介绍使用matlab构建多输入单输出的网络架构&#xff0c;来实现倾斜的手写数字识别&#xff0c;使用concatenationLayer来拼接特征&#xff0c;实现网络输入多个特征。 1.加载训练数据 加载数据&#xff1a;手写数字的图像、真实数字标签和数字顺时针旋转的角度。 lo…

Nacos实现IP动态黑白名单过滤

一些恶意用户&#xff08;可能是黑客、爬虫、DDoS 攻击者&#xff09;可能频繁请求服务器资源&#xff0c;导致资源占用过高。因此我们需要一定的手段实时阻止可疑或恶意的用户&#xff0c;减少攻击风险。 本次练习使用到的是Nacos配合布隆过滤器实现动态IP黑白名单过滤 文章…

如何在Word文件中设置水印以及如何禁止修改水印

在日常办公和学习中&#xff0c;我们经常需要在Word文档中设置水印&#xff0c;以保护文件的版权或标明文件的机密性。水印可以是文字形式&#xff0c;也可以是图片形式&#xff0c;能够灵活地适应不同的需求。但仅仅设置水印是不够的&#xff0c;有时我们还需要确保水印不被随…

测试工程师如何在面试中脱颖而出

目录 1.平时工作中是怎么去测的&#xff1f; 2.B/S架构和C/S架构区别 3.B/S架构的系统从哪些点去测&#xff1f; 4.你为什么能够做测试这一行&#xff1f;&#xff08;根据个人情况分析理解&#xff09; 5.你认为测试的目的是什么&#xff1f; 6.软件测试的流程&#xff…

jenkins的安装(War包安装)

‌Jenkins是一个开源的持续集成工具&#xff0c;基于Java开发&#xff0c;主要用于监控持续的软件版本发布和测试项目。‌ 它提供了一个开放易用的平台&#xff0c;使软件项目能够实现持续集成。Jenkins的功能包括持续的软件版本发布和测试项目&#xff0c;以及监控外部调用执行…

无线感知会议系列【15】DPSense-2

接&#xff1a; 无线感知会议系列【15】DPSense-1 目录&#xff1a; 实验 讨论 结论 附录 一 实验 在本节中&#xff0c;我们通过全面的实验验证了所提出的DPSense系统的有效性。首先&#xff0c;我们将我们的方法与三种最先进的技术进行了比较。然后&#xff0c…

AI编程入门指南002:API、数据库和应用部署

进阶概念教程&#xff1a;API、数据库和应用部署 在学习了编程的基础概念后&#xff0c;我们将进入更高级的内容。本文将详细介绍API、数据库和应用部署三个进阶概念&#xff0c;并通过丰富的示例和形象的说明帮助你更好地理解这些内容。 1. API&#xff08;应用程序接口&#…

Docker3:docker基础1

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…

《Django 5 By Example》阅读笔记:p645-p650

《Django 5 By Example》学习第8天&#xff0c;p645-p650总结&#xff0c;总计6页。 一、技术总结 1.django-rest-framework (1)serializer p648, Serializer: Provides serialization for normal Python class instances。Serializer又细分为Serializer, ModelSerializer,…

【机器学习】回归模型(线性回归+逻辑回归)原理详解

线性回归 Linear Regression 1 概述 线性回归类似高中的线性规划题目。线性回归要做的是就是找到一个数学公式能相对较完美地把所有自变量组合&#xff08;加减乘除&#xff09;起来&#xff0c;得到的结果和目标接近。 线性回归分为一元线性回归和多元线性回归。 2 一元线…

【大模型推理】vLLM 源码学习

强烈推荐 https://zhuanlan.zhihu.com/p/680153425 sequnceGroup 存储了相同的prompt对应的不同的sequence, 所以用字典存储 同一个Sequence可能占据多个逻辑Block&#xff0c; 所以在Sequence 中用列表存储 同一个block 要维护tokens_id 列表, 需要添加操作。 还需要判断blo…

FIFO和LRU算法实现操作系统中主存管理

FIFO&#xff0c;用数组实现 1和2都是使用nextReplace实现新页面位置的更新 1、不精确时间&#xff1a;用ctime输出运行时间都是0.00秒 #include <iostream> #include <iomanip> #include<ctime>//用于计算时间 using namespace std;// 页访问顺序 int pa…

【Ubuntu24.04】VirtualBox安装ubuntu-live-server24.04

目录 0 背景1 下载镜像2 安装虚拟机3 安装UbuntuServer24.044 配置基本环境5 总结0 背景 有了远程连接工具之后,似乎作为服务器的Ubuntu24.04桌面版有点备受冷落了,桌面版的Ubuntu24.04的优势是图形化桌面,是作为一个日常工作的系统来用的,就像Windows,如果要作为服务器来…

《SpringBoot、Vue 组装exe与套壳保姆级教学》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…