0

0

react怎么实现图片选择

藏色散人

藏色散人

发布时间:2023-01-19 14:21:40

|

1588人浏览过

|

来源于php中文网

原创

react实现图片选择的方法:1、使用import引入“react-native-image-picker”插件;2、使用“{this.setState({uploadImgs: urls})}}src={uploadImgs}/>”调用实现图片选择上传即可。

react怎么实现图片选择

本教程操作环境:Windows10系统、react18.0.0版、Dell G3电脑。

react怎么实现图片选择?

React Native七牛上传+本地图片选择

参考:

react-native-image-crop-picker图片选择并裁减 //这个看需求使用
https://github.com/ivpusic/react-native-image-crop-picker
react-native-image-picker图片选择
https://github.com/react-native-image-picker/react-native-image-picker
react-native-qiniu
https://github.com/buhe/react-native-qiniu

我只要一个多图片上传功能,所以就写简单一点

效果

272c9e4e9370c56b75329fa12000ebf.jpg

已上传状态

8a71bfdf34877db7133cf01a8362a08.jpg

上传中状态

CSS3 3D魔方旋转图片切换查看特效
CSS3 3D魔方旋转图片切换查看特效

CSS3 3D魔方旋转图片切换查看特效是一款鼠标选择任意图片,都可自动实现360度超炫3D旋转立方体的动画特效。

下载

步骤

1、手机图片、视频选择功能

用react-native-image-picker插件

yarn add react-native-image-picker;ios需要pod install;

import {launchCamera, launchImageLibrary, ImageLibraryOptions, PhotoQuality} from 'react-native-image-picker';
/**
 * 从相册选择图片;
 * sourceType: 'camera'  打开相机拍摄图片
**/
export async function chooseImage(options: {
  count?: number,
  quality?: PhotoQuality
  sourceType?: 'camera',  //默认'album'
} = {}) {
  return new Promise(async(resolve, reject) => {
    const Opts: ImageLibraryOptions = {
      mediaType: 'photo',
      quality: options.quality || 1,
      selectionLimit: options.count || 1
    };
    const result = options.sourceType == 'camera'? 
      await launchCamera(Opts) : 
      await launchImageLibrary(Opts);
    resolve(result)
  })
}
/**
 * 从相册选择视频;
 * sourceType: 'camera'  打开相机拍摄视频
**/
export async function chooseVideo(options: {
  count?: number,
  quality?: 'low' | 'high'
  sourceType?: 'camera',  //默认'album'
} = {}) {
  return new Promise(async(resolve, reject) => {
    const Opts: ImageLibraryOptions = {
      mediaType: 'video',
      videoQuality: options.quality,
      selectionLimit: options.count || 1
    };
    const result = options.sourceType == 'camera'? 
      await launchCamera(Opts) : 
      await launchImageLibrary(Opts);
    resolve(result)
  })
}

2、七牛上传文件功能

class qiniuUpload {
  private UP_HOST = 'http://upload.qiniu.com';
  // private RS_HOST = 'http://rs.qbox.me';
  // private RSF_HOST = 'http://rsf.qbox.me';
  // private API_HOST = 'http://api.qiniu.com';
  public upload = async(uri:string, key:string, token:string) => {
    return new Promise((resolve, reject) => {
      let formData = new FormData();
      formData.append('file', {uri: uri, type: 'application/octet-stream', name: key});
      formData.append('key', key);
      formData.append('token', token);
    
      let options:any = {
        body: formData,
        method: 'post',
      };
      fetch(this.UP_HOST, options).then((response) => {
        resolve(response)
      }).catch(error => {
        console.error(error)
        resolve(null)
      });  
    })
  }
   //...后面再加别的功能
}
const qiniu = new qiniuUpload();
export default qiniu;
import qiniu from '@/modules/qiniu/index'
...
  /**
   * 上传视频图片
   */
  uploadFile: async (filePath: string) => {
    const res = await createBaseClient('GET', '/v1/file')();  //这是接口请求方法,用来拿后端的七牛token、key
    
    if( !res ) {
      return res;
    }
    const { key, token } = res;
    const fileSegments = filePath.split('.');
    const fileKey = key + '.' + fileSegments[fileSegments.length - 1];
    try {
      const result = await qiniu.upload(filePath, fileKey, token)
      if(result && result.ok) {
        return {
          url: ASSET_HOST + '/' + fileKey,  //ASSET_HOST是资源服务器域名前缀
        };
      }else {
        return null
      }
    } catch (error) {
      return null;
    }
  },
...

3、多图上传组件封装

(这里Base、Image、ActionSheet都是封装过的,需看情况调整)

import React from 'react'
import {
  ViewStyle,
  StyleProp,
  ImageURISource,
  ActivityIndicator
} from 'react-native'
import Base from '@/components/Base';
import { Image, View, Text } from '@/components';   //Image封装过的,所以有些属性不一样
import ActionSheet from "@/components/Feedback/ActionSheet";  //自己封装
import styles from './styleCss';  //样式就不放上来了
interface Props {
  type?: 'video'
  src?: string[]
  count?: number
  btnPath?: ImageURISource
  style?: StyleProp
  itemStyle?: StyleProp
  itemWidth?: number
  itemHeight?: number  //默认正方形
  onChange?: (e) => void
}
interface State {
  imageUploading: boolean
  images: string[]
}
/**
 * 多图上传组件
 * * type?: 'video'
 * * src?: string[]   //图片数据,可用于初始数据
 * * count?: number    //数量
 * * btnPath?: ImageURISource   //占位图
 * * itemStyle?: item样式,width, height单独设
 * * itemWidth?: number
 * * itemHeight?: number  //默认正方形
 * * onChange?: (e:string[]) => void
**/
export default class Uploader extends Base {
  public state: State = {
    imageUploading: false,
    images: []
  };
  public didMount() {
    this.initSrc(this.props.src)
  }
  public componentWillReceiveProps(nextProps){
    if(nextProps.hasOwnProperty('src') && !!nextProps.src){
      this.initSrc(nextProps.src)
    }
  }
  /**
   *初始化以及改动图片
  **/
  private initSrc = (srcProp:any) => {
    if(!this.isEqual(srcProp, this.state.images)) {
      this.setState({
        images: srcProp
      })
    }
  }
  
  public render() {
    const { style, btnPath, count, itemStyle, itemWidth, itemHeight, type } = this.props;
    const { imageUploading, images } = this.state;
    let countNumber = count? count: 1
    return (
      
        
          {images.length > 0 && images.map((res, ind) => (
            
              
                 {
                    this.singleEditInd = ind;
                    this.handleShowActionSheet()
                  }}
                />
                删除
              
            
          ))}
          {images.length < countNumber  &&
             
              {imageUploading? (
                
                  
                  
                    上传中...
                  
                
              ): (
                
                   {
                      this.singleEditInd = undefined;
                      this.handleShowActionSheet()
                    }}
                  />
                
              )}
              
            
          }
          
        
         {
              if(type == 'video') {
                this.handleChooseVideo('camera')
              }else if(this.singleEditInd !== undefined) {
                this.handleChooseSingle('camera')
              }else {
                this.handleChooseImage('camera')
              }
            }
          }, {
            name: '相册',
            onClick: () => {
              if(type == 'video') {
                this.handleChooseVideo()
              }else if(this.singleEditInd !== undefined) {
                this.handleChooseSingle()
              }else {
                this.handleChooseImage()
              }
            }
          }]}
        >
      
    );
  }
  private get itemW() {
    return this.props.itemWidth || 92
  }
  private get itemH() {
    return this.props.itemHeight || this.itemW;
  }
  
  private isEqual = (firstValue, secondValue) => {
    /** 判断两个值(数组)是否相等 **/
    if (Array.isArray(firstValue)) {
      if (!Array.isArray(secondValue)) {
        return false;
      }
      if(firstValue.length != secondValue.length) {
        return false;
      }
      return firstValue.every((item, index) => {
        return item === secondValue[index];
      });
    }
    return firstValue === secondValue;
  }
  private handleShowActionSheet = () => {
    this.feedback.showFeedback('uploaderActionSheet');  //这是显示ActionSheet选择弹窗。。。
  }
  private handleChooseImage = async (sourceType?: 'camera') => {
    const { imageUploading, images } = this.state;
    const { count } = this.props
    if (imageUploading) {
      return;
    }
    let countNumber = count? count: 1
    const { assets } = await this.interface.chooseImage({  //上面封装的选择图片方法
      count: countNumber,
      sourceType: sourceType || undefined,
    });
    
    if(!assets) {
      return;
    }
    this.setState({
      imageUploading: true,
    });
    
    let request:any = []
    assets.map(res => {
      let req = this.apiClient.uploadFile(res.uri)   //上面封装的七牛上传方法
      request.push(req)
    })
    Promise.all(request).then(res => {
      let imgs:any = []
      res.map((e:any) => {
        if(e && e.url){
          imgs.push(e.url)
        }
      })
      imgs = [...images, ...imgs];
      this.setState({
        images: imgs.splice(0,countNumber),
        imageUploading: false,
      },
        this.handleChange
      );
    })
    
  }
  private singleEditInd?: number;  //修改单个时的索引值
  private handleChooseSingle = async(sourceType?: 'camera') => {
    let { imageUploading, images } = this.state;
    if (imageUploading) {
      return;
    }
    
    const { assets } = await this.interface.chooseImage({   //上面封装的选择图片方法
      count: 1,
      sourceType: sourceType || undefined,
    });
    if(!assets) {
      return;
    }
    this.setState({
      imageUploading: true,
    });
    const res = await this.apiClient.uploadFile(assets[0].uri)   //上面封装的七牛上传方法
    if(res && res.url && this.singleEditInd){
      images[this.singleEditInd] = res.url
    }
    this.setState({
      images: [...images],
      imageUploading: false,
    },
      this.handleChange
    );
    
  }
  private handleChooseVideo = async(sourceType?: 'camera') => {
    const { onChange } = this.props
    let { imageUploading } = this.state;
    if (imageUploading) {
      return;
    }
    
    const { assets } = await this.interface.chooseVideo({
      sourceType: sourceType
    });
    if(!assets) {
      return;
    }
    this.setState({
      imageUploading: true,
    });
    const res = await this.apiClient.uploadFile(assets[0].uri)   //上面封装的七牛上传方法
    if(res && res.url){
      //视频就不在组件中展示了,父组件处理
      if(onChange) {
        onChange(res.url)
      }
    }
    this.setState({
      imageUploading: false,
    });
    
  }
  private handleDelete = (ind:number) => {
    let { images } = this.state
    images.splice(ind,1)
    this.setState({
      images: [...images]
    },
      this.handleChange
    )
  }
  private handleChange = () => {
    const { onChange } = this.props
    const { images } = this.state
    if(onChange) {
      onChange(images)
    }
  }
}

4、最后调用

import Uploader from "@/components/Uploader";
...
           {
              this.setState({
                uploadImgs: urls
              })
            }}
            src={uploadImgs}
          />
...

推荐学习:《react视频教程

相关文章

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

37

2026.01.14

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

19

2026.01.13

PHP 高性能
PHP 高性能

本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

37

2026.01.13

MySQL数据库报错常见问题及解决方法大全
MySQL数据库报错常见问题及解决方法大全

本专题整合了MySQL数据库报错常见问题及解决方法,阅读专题下面的文章了解更多详细内容。

19

2026.01.13

PHP 文件上传
PHP 文件上传

本专题整合了PHP实现文件上传相关教程,阅读专题下面的文章了解更多详细内容。

16

2026.01.13

PHP缓存策略教程大全
PHP缓存策略教程大全

本专题整合了PHP缓存相关教程,阅读专题下面的文章了解更多详细内容。

6

2026.01.13

jQuery 正则表达式相关教程
jQuery 正则表达式相关教程

本专题整合了jQuery正则表达式相关教程大全,阅读专题下面的文章了解更多详细内容。

3

2026.01.13

交互式图表和动态图表教程汇总
交互式图表和动态图表教程汇总

本专题整合了交互式图表和动态图表的相关内容,阅读专题下面的文章了解更多详细内容。

45

2026.01.13

nginx配置文件详细教程
nginx配置文件详细教程

本专题整合了nginx配置文件相关教程详细汇总,阅读专题下面的文章了解更多详细内容。

9

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 3.6万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1.0万人学习

React核心原理新老生命周期精讲
React核心原理新老生命周期精讲

共12课时 | 1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号