Camera Roll API + Upload From Camera Roll Module
導入CameraRoll API
const React = require('react-native');
const {
CameraRoll,
} = React;
{
first: ..., // (必須的) 在照片中,按反相排序後,在獲取的照片的數量
after: ..., // 上一次調用getPhotos返回的指針。cursor
groupTypes: ..., // 指定分組類型,過濾結果
// One of ['Album', 'All', 'Event', 'Faces', 'Library', 'PhotoStream', 'SavedPhotos'(default)]
groupName: ..., // Specifies filter on group names, like 'Recent Photos' or custom album titles
assetType: ... // Specifies filter on assetType
// One of ['All', 'Videos', 'Photos'(default)]
}
const fetchParams = {
first: 25,
}
{
edges: [
node: {
type: ...,
group_name: ...,
image: {
uri: ...,
height: ...,
width: ...,
isStored: ...,
},
timestamp: ...,
location {
...
},
},
node: { ... },
node: { ... },
...
],
page_info: {
has_next_page: ...,
start_cursor: ...,
end_cursor: ...,
}
}
由於節點中的image對像包含了我們將要在App中顯示圖片的時要使用到的數據,所以我們需要創建一個函數,從edges數組中提取image對像。並且應該將它們保存到一個state變量中.
storeImages(data) {
const assets = data.edges;
const images = assets.map( asset => asset.node.image );
this.setState({
images: images,
});
},
由於我們使用了images變量,所以需要先定義這個變量
getInitialState() {
return {
images: [],
};
},
getPhotos的第三個參數是用來處理錯誤的回調函數。對於這個例子,我們只是將錯誤發送到控制檯.
logImageError(err) {
console.log(err);
},
到目前爲此,我們已經爲CameraRoll.getPhotos定義了三個參數。我們將在ComponentDidMount()中調用這個getPhotos, 它會檢索一次圖片信息。
componentDidMount() {
const fetchParams = {
first: 25,
};
CameraRoll.getPhotos(fetchParams, this.storeImages, this.logImageError);
},
讀取圖片
const {
CameraRoll,
StyleSheet,
Image,
} = React;
然後在render函數中顯示圖片
render() {
return (
<ScrollView style={styles.container}>
<View style={styles.imageGrid}>
{ this.state.images.map(image => <Image style={styles.image} source={{ uri: image.uri }} />) }
</View>
</ScrollView>
);
}
然後添加樣式
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5FCFF',
},
imageGrid: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'center'
},
image: {
width: 100,
height: 100,
margin: 10,
},
});
const React = require('react-native');
const {
StyleSheet,
Text,
View,
ScrollView,
Image,
CameraRoll,
} = React;
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5FCFF',
},
imageGrid: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'center'
},
image: {
width: 100,
height: 100,
margin: 10,
},
});
const reactImageProject = React.createClass({
getInitialState() {
return {
images: [],
};
},
componentDidMount() {
const fetchParams = {
first: 25,
};
CameraRoll.getPhotos(fetchParams, this.storeImages, this.logImageError);
},
storeImages(data) {
const assets = data.edges;
const images = assets.map((asset) => asset.node.image);
this.setState({
images: images,
});
},
logImageError(err) {
console.log(err);
},
render() {
return (
<ScrollView style={styles.container}>
<View style={styles.imageGrid}>
{ this.state.images.map((image) => <Image style={styles.image} source={{ uri: image.uri }} />) }
</View>
</ScrollView>
);
}
});
當你運行這個項目,你會看到一個最新相機中最新的25張圖片
選擇圖片
selectImage(uri) {
this.setState({
selected: uri,
});
console.log('Selected image: ', uri);
},
getInitialState() {
return {
images: [],
selected: '',
};
},
以下是新的render函數
const {
StyleSheet,
Text,
View,
ScrollView,
Image,
CameraRoll,
TouchableHighlight,
} = React;
render() {
return (
<ScrollView style={styles.container}>
<View style={styles.imageGrid}>
{ this.state.images.map((image) => {
return (
<TouchableHighlight onPress={this.selectImage.bind(null, image.uri)}>
<Image style={styles.image} source={{ uri: image.uri }} />
</TouchableHighlight>
);
})
}
</View>
</ScrollView>
);
}
獲得圖片的base64數據
selectImage(uri) {
NativeModules.ReadImageData.readImage(uri, (image) => {
this.setState({
selected: image,
});
console.log(image);
});
},
const React = require('react-native');
const {
AppRegistry,
StyleSheet,
Text,
View,
ScrollView,
Image,
CameraRoll,
TouchableHighlight,
NativeModules,
} = React;
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5FCFF',
},
imageGrid: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'center'
},
image: {
width: 100,
height: 100,
margin: 10,
}
});
const reactImageProject = React.createClass({
getInitialState() {
return {
images: [],
selected: '',
};
},
componentDidMount() {
const fetchParams = {
first: 25,
};
CameraRoll.getPhotos(fetchParams, this.storeImages, this.logImageError);
},
storeImages(data) {
const assets = data.edges;
const images = assets.map((asset) => asset.node.image);
this.setState({
images: images,
});
},
logImageError(err) {
console.log(err);
},
selectImage(uri) {
NativeModules.ReadImageData.readImage(uri, (image) => {
this.setState({
selected: image,
});
console.log(image);
});
},
render() {
return (
<ScrollView style={styles.container}>
<View style={styles.imageGrid}>
{ this.state.images.map((image) => {
return (
<TouchableHighlight onPress={this.selectImage.bind(null, image.uri)}>
<Image style={styles.image} source={{ uri: image.uri }} />
</TouchableHighlight>
);
})
}
</View>
</ScrollView>
);
}
});
AppRegistry.registerComponent('reactImageProject', () => reactImageProject);
關於NativeModules模塊
我們可以在獲取到的圖片數據中,添加一個base64屬性到image對像. 如下現在你獲得的圖片對像就會包含base64屬性。你僅需要調整相關的React Native文件,讓它知道新的屬性
base64: ReactPropTypes.string,
如果你打算使用這個方法上傳全分辨率的圖片,應用程序會運行的超慢,因爲它需要將圖片轉換爲大型的base64字符串。
#import "RCTBridgeModule.h"
#import <AssetsLibrary/AssetsLibrary.h>
#import <UIKit/UIKit.h>
@interface ReadImageData : NSObject <RCTBridgeModule>
@end
@implementation ReadImageData
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(readImage:(NSString *)input callback:(RCTResponseSenderBlock)callback)
{
// Create NSURL from uri
NSURL *url = [[NSURL alloc] initWithString:input];
// Create an ALAssetsLibrary instance. This provides access to the
// videos and photos that are under the control of the Photos application.
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
// Using the ALAssetsLibrary instance and our NSURL object open the image.
[library assetForURL:url resultBlock:^(ALAsset *asset) {
// Create an ALAssetRepresentation object using our asset
// and turn it into a bitmap using the CGImageRef opaque type.
CGImageRef imageRef = [asset thumbnail];
// Create UIImageJPEGRepresentation from CGImageRef
NSData *imageData = UIImageJPEGRepresentation([UIImage imageWithCGImage:imageRef], 0.1);
// Convert to base64 encoded string
NSString *base64Encoded = [imageData base64EncodedStringWithOptions:0];
callback(@[base64Encoded]);
} failureBlock:^(NSError *error) {
NSLog(@"that didn't work %@", error);
}];
}
@end
現在你的Xcode project 已經有了一個新的自定義模塊,我們可以在Javascript中導入這個組件.
var {View, Text, Image, NativeModules} = React;
NativeModules.ReadImageData.readImage(ourImage.node.image.uri, (image) => {
console.log(image)
})
然後,能過fetch方法,上傳圖片資源
fetch('http://your.server/app.php', {
method:'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
body: JSON.stringify({imageData:image})
}
})