效果圖,
支持默認圖片,上傳中的狀態,最大上傳數量,預覽大圖等功能
import React, { Component } from "react";
import {
StyleSheet,
View,
Text,
Image,
TouchableOpacity,
Modal,
Platform
} from "react-native";
import { scaleSizeW, setSpText, uploadImag } from "../utils/util";
import ToastBox from "../utils/Toast";
import ActionSheet from "react-native-actionsheet";
import Toast from "../utils/Toast";
import config from "../utils/config";
import ImageViewer from "react-native-image-zoom-viewer";
/*
* maxNum (number)上傳的最大數量
* onChange (fun) 返回文件列表arrary
* actionText + 下面的文字
* noRequire 選傳
* initList 已有的圖片數組
*/
export default class ImgUpLoad extends Component {
constructor(props) {
super(props);
this.state = {
flieLists: [],
visible: false,
upLoadState: 2 //1上傳中 2上傳完成
};
}
componentWillMount() {
const { initList, size } = this.props;
console.log(initList);
let flieLists = initList ? initList : [];
this.setState({
flieLists
});
}
feedBack = () => {
// this.props.onChange && this.props.onChange(this.state.flieLists);
if (this.props.onChange) {
let arr = [...this.state.flieLists];
// console.log("feedBack: ",arr)
this.props.onChange(arr);
}
};
// 打開相冊
selectFromAblum(type) {
const { userInfo, setUserInfo } = this.props;
uploadImag(type, image => {
// const param = `data:${image.mime};base64,${image.data}`;
console.log(image);
let maxSize = image.size / 1024 / 1024, // MB
minSize = image.size / 1024; // KB
if (maxSize > 1) {
ToastBox.showTop("圖片大小不符合要求,請重新選擇");
return;
}
// ToastBox.showTop(`${image.size}`)
if(Platform.OS=='android'){
let DateName = new Date().getTime();
image.filename = DateName + ".jpg";
}
let file = {
uri: image.path,
type: "multipart/form-data",
name: image.filename
};
let formData = new FormData();
formData.append("file", file);
this.setState({
upLoadState: 1
});
fetch(config.uploadImg, {
method: "post",
body: formData,
headers: {
"Content-Type": "multipart/form-data;charset=utf-8"
}
// body: JSON.stringify({
// base64Str:param
// }),
})
.then(res => {
console.log(res);
// console.log(res.text())
return res.json();
})
.then(response => {
console.log(response);
if (response.code == 0) {
this.setState({
upLoadState: 2
});
console.log(response.data.uri);
let myfile = response.data.uri;
let flieLists = [...this.state.flieLists];
flieLists.push(myfile);
this.setState({ flieLists }, () => {
this.feedBack();
});
}
})
.catch(err => {
console.log(err);
ToastBox.showTop("圖片上傳失敗,請重試");
this.setState({
upLoadState: 2
});
});
});
}
takePhoto(type) {
const { userInfo, setUserInfo } = this.props;
uploadImag(type, image => {
// const param = `data:${image.mime};base64,${image.data}`;
// console.log(param)
console.log(image);
let maxSize = image.size / 1024 / 1024, // MB
minSize = image.size / 1024; // KB
let filename;
if (maxSize > 1) {
ToastBox.showTop("圖片大小不符合要求,請重試");
return;
}
// ToastBox.showTop(`${image.size}`)
let DateName = new Date().getTime();
filename = DateName + ".jpg";
let file = {
uri: image.path,
type: "multipart/form-data",
name: filename
};
this.setState({
upLoadState: 1
});
let formData = new FormData();
formData.append("file", file);
fetch(config.uploadImg, {
method: "post",
body: formData,
headers: {
"Content-Type": "multipart/form-data;charset=utf-8"
}
// body: JSON.stringify({
// base64Str:param
// }),
})
.then(res => res.json())
.then(response => {
if (response.code == 0) {
// ToastBox.showTop(`圖片上傳成功:${JSON.stringify( response)}`)
let myfile = response.data.uri;
let flieLists = [...this.state.flieLists];
flieLists.push(myfile);
this.setState({ flieLists, upLoadState: 2 }, () => {
this.feedBack();
});
}
})
.catch(err => {
console.log(err);
ToastBox.showTop("圖片上傳失敗,請重試");
this.setState({upLoadState: 2})
});
});
}
// 開打底部選項卡
showActionSheet = () => {
if (this.props.maxNum && this.state.flieLists.length >= this.props.maxNum) {
Toast.show("上傳數量達到極限");
return;
}
this.ActionSheet.show();
};
// 刪除圖片
delImg = index => {
let flieLists = [...this.state.flieLists];
flieLists.splice(index, 1);
console.log(flieLists);
this.setState({ flieLists: flieLists }, () => {
this.feedBack();
});
};
render() {
const { flieLists, visible, upLoadState } = this.state;
const { maxNum, actionText, size, noRequire, initList } = this.props;
if (size) {
let num = scaleSizeW(size);
console.log(num)
styles.upLoadItem = { ...styles.upLoadItem, width: num, height: num };
styles.image = { ...styles.image, width: num, height: num };
}
console.log(flieLists);
return (
<View style={styles.upLoad}>
{flieLists.length > 0 &&
flieLists.map((item, index) => {
console.log(item);
const images = [
{
// Simplest usage.
url: item
}
];
return (
<TouchableOpacity
onPress={() => {
this.setState({ visible: true });
}}
key={index}
style={styles.upLoadItem}
>
<Image source={{ uri: item }} style={styles.image} />
<Modal
style={{ width: "100%", height: "100%" }}
visible={visible}
transparent
>
<ImageViewer
backgroundColor={"rgba(0,0,0,0.8)"}
onClick={() => {
this.setState({ visible: false });
}}
imageUrls={images}
/>
</Modal>
<Text
style={styles.close}
onPress={() => {
this.delImg(index);
}}
>
{"\ue613"}
</Text>
</TouchableOpacity>
);
})}
{/* 超過最大數隱藏上傳 */}
{maxNum > flieLists.length && (
<TouchableOpacity
activeOpacity={1}
onPress={() => {
this.showActionSheet();
}}
>
{upLoadState == 2 && (
<View style={[styles.upLoadItem, styles.addBtn]}>
<Text style={styles.add}>{"\ue612"}</Text>
<Text style={styles.addText}>
{actionText ? actionText : "上傳"}
</Text>
{noRequire && <Text style={styles.otherText}>(選傳)</Text>}
</View>
)}
{upLoadState == 1 && (
<View style={[styles.upLoadItem, styles.loadingImgWrap]}>
<Image
style={styles.loadingImg}
source={require("../assets/image/timg.gif")}
></Image>
</View>
)}
</TouchableOpacity>
)}
<ActionSheet
ref={o => (this.ActionSheet = o)}
options={["拍照", "從相冊上傳", "取消"]}
cancelButtonIndex={2}
destructiveButtonIndex={1}
onPress={index => {
if (index === 0) {
this.takePhoto(1);
} else if (index === 1) {
this.selectFromAblum(2);
}
}}
/>
</View>
);
}
}
const styles = StyleSheet.create({
upLoad: {
// width: "100%",
flexDirection: "row",
flexWrap: "wrap",
// paddingLeft: scaleSizeW(20),
paddingTop: scaleSizeW(20)
// justifyContent: "flex-start"
},
upLoadItem: {
width: scaleSizeW(204),
height: scaleSizeW(204),
borderRadius: scaleSizeW(8),
borderColor: "#ccc",
borderWidth: StyleSheet.hairlineWidth,
justifyContent: "center",
alignItems: "center",
marginRight: scaleSizeW(20),
marginBottom: scaleSizeW(20),
position: "relative"
},
loadingImgWrap: {
backgroundColor: "#fff"
},
loadingImg: {
width: scaleSizeW(100),
height: scaleSizeW(100),
borderRadius: scaleSizeW(8)
},
addBtn: {
borderStyle: "dashed",
backgroundColor: "rgba(247,250,253,1)"
},
image: {
width: scaleSizeW(204),
height: scaleSizeW(204),
borderRadius: scaleSizeW(8)
},
add: {
fontFamily: "iconfont",
fontSize: setSpText(40),
color: "#8595A6"
},
addText: {
color: "#FF6737",
fontSize: setSpText(24),
textAlign: "center"
},
otherText: {
fontSize: scaleSizeW(24),
color: "rgba(76,154,255,0.6)",
marginTop: scaleSizeW(8),
position: "absolute",
bottom: scaleSizeW(30),
left: "50%",
marginLeft: scaleSizeW(-30)
},
close: {
position: "absolute",
right: scaleSizeW(12),
zIndex: 10,
top: scaleSizeW(12),
fontSize: setSpText(50),
fontFamily: "iconfont",
color: "#999"
}
});
上傳圖片,拍照組件
import ImagePicker from 'react-native-image-crop-picker';
/**
* 上傳圖片
* @param callback 上傳成功後的回調函數
*/
export function uploadImag(type,callback) {
if(type==1){
ImagePicker.openCamera({
cropping: false,
compressImageQuality: 0.3,
includeExif: true
}).then((image) => {
callback(image)
}).catch(err=>{console.log(err)})
}else if(type==2){
ImagePicker.openPicker({
cropping: false,
compressImageQuality: 0.5,
includeExif: true
}).then((image) => {
callback(image)
}).catch(err=>{console.log(err)});
}
}
export function uploadFile(callback) {
DocumentPicker.show(
{
filetype: [DocumentPickerUtil.allFiles()]
},
(error, res) => {
if (error) {
Toast.message('上傳文件失敗');
} else {
let source = {
uri: res.uri,
type: 'multipart/form-data',
name: res.fileName
};
let params = {
image: source,
imageFileName: 'images'
};
Api.uploadFile(params).then(res => {
if (res.success) {
if (typeof callback === 'function') {
callback(res);
}
} else {
Toast.message('上傳圖片失敗');
}
});
}
}
);
}