您好,登錄后才能下訂單哦!
這篇文章主要講解了“react如何實現(xiàn)圖片選擇”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“react如何實現(xiàn)圖片選擇”吧!
react實現(xiàn)圖片選擇的方法:1、使用import引入“react-native-image-picker”插件;2、使用“
{this.setState({uploadImgs: urls})}}src={uploadImgs}/>”調(diào)用實現(xiàn)圖片選擇上傳即可。
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
我只要一個多圖片上傳功能,所以就寫簡單一點
效果
已上傳狀態(tài)
上傳中狀態(tài)
步驟
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<any>(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<any>(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<any>((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是資源服務(wù)器域名前綴
};
}else {
return null
}
} catch (error) {
return null;
}
},
...
3、多圖上傳組件封裝
(這里Base、Image、ActionSheet都是封裝過的,需看情況調(diào)整)
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<ViewStyle>
itemStyle?: StyleProp<ViewStyle>
itemWidth?: number
itemHeight?: number //默認正方形
onChange?: (e) => void
}
interface State {
imageUploading: boolean
images: string[]
}
/**
* 多圖上傳組件
* * type?: 'video'
* * src?: string[] //圖片數(shù)據(jù),可用于初始數(shù)據(jù)
* * count?: number //數(shù)量
* * btnPath?: ImageURISource //占位圖
* * itemStyle?: item樣式,width, height單獨設(shè)
* * itemWidth?: number
* * itemHeight?: number //默認正方形
* * onChange?: (e:string[]) => void
**/
export default class Uploader extends Base<Props, State> {
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 (
<React.Fragment>
<View style={[styles.uploaderBox, style]}>
{images.length > 0 && images.map((res, ind) => (
<View style={[styles.item, itemStyle]} key={res}>
<View style={styles.imgItem}>
<Image
source={{uri: res}}
width={this.itemW}
height={this.itemH}
onPress={() => {
this.singleEditInd = ind;
this.handleShowActionSheet()
}}
/>
<Text style={styles.del} onPress={this.handleDelete.bind(null, ind)}>刪除</Text>
</View>
</View>
))}
{images.length < countNumber &&
<View style={[styles.item, itemStyle]}>
{imageUploading? (
<View style={[{
width: this.itemW,
height: this.itemH,
}, styles.loading]}>
<ActivityIndicator size={this.itemW*0.4}></Loading>
<Text style={{
fontSize: 14,
color: '#888',
marginTop: 5
}}>
上傳中...
</Text>
</View>
): (
<View style={styles.btn}>
<Image
source={btnPath || this.assets.uploadIcon}
width={this.itemW}
height={this.itemH}
onPress={() => {
this.singleEditInd = undefined;
this.handleShowActionSheet()
}}
/>
</View>
)}
</View>
}
</View>
<ActionSheet
name="uploaderActionSheet"
options={[{
name: type == 'video'? '拍攝': '拍照',
onClick: () => {
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()
}
}
}]}
></ActionSheet>
</React.Fragment>
);
}
private get itemW() {
return this.props.itemWidth || 92
}
private get itemH() {
return this.props.itemHeight || this.itemW;
}
private isEqual = (firstValue, secondValue) => {
/** 判斷兩個值(數(shù)組)是否相等 **/
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、最后調(diào)用
import Uploader from "@/components/Uploader";
...
<Uploader
count={6}
onChange={urls => {
this.setState({
uploadImgs: urls
})
}}
src={uploadImgs}
/>
...
感謝各位的閱讀,以上就是“react如何實現(xiàn)圖片選擇”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對react如何實現(xiàn)圖片選擇這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。