Camera Roll API + Upload From Camera Roll Module

前端之家收集整理的这篇文章主要介绍了Camera Roll API + Upload From Camera Roll Module前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

Camera Roll API + Upload From Camera Roll Module

我们将介绍使用内置的React Native Camera Roll API显示相机中的图片。一旦用户选择了一张图片,我们将使用 Upload From Camera Roll Module获得图片的base64数据。如果你只是想让用户看到和选择图片,你可以使用这种方法,但如果是想拍照,你需要使用 camera模块. 如果不想让用户定义和选择图片的界面,你可以使用 Image Picker Module.

导入CameraRoll API

const React = require('react-native');

const {
    CameraRoll,} = React;

使用CameraRoll中的getPhotos方法,获得图片列表.

CameraRoll.getPhotos接受 3 个参数:第一个参数是一个对像,它定义了从相机胶卷中返回什么样的图片。第二个是一个回调函数,这个函数,接受请求到的图片,第三个参数也是一个回调函数,它用来处理错误。首先,让我们看看第一个参数,它是如何定义要返回的图片。以下是这个对数的属性

{
    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)]
}

对于我们的例子来说,我们想要从camera roll 中获取前25张图片,getPhotos的第一个参数为:

const fetchParams = {
    first: 25,}

下一步,我们定义一个回调函数来处理接收到的图片。要传递给这个回调函数的数据,是从CameraRool.getPhotos中获得,这个数据是一个对像,它包含了一个数组,这个数组包含了所有的图片节点。另一个是一个对像,它包含了分页信息。这个对像如下:

{
    edges: [
        node: {
            type: ...,group_name: ...,image: {
                uri: ...,height: ...,width: ...,isStored: ...,},timestamp: ...,location {
                ...
            },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);
},

读取图片

我们可以使用Image组件,flexBox样式,以及其它的map function来显示检索到的图片

让我们先导入StyleSheet和Image组件

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,CameraRoll,} = React;

const styles = StyleSheet.create({
  container: {
    flex: 1,imageGrid: {
    flex: 1,justifyContent: 'center'
  },image: {
    width: 100,});

const reactImageProject = React.createClass({
  getInitialState() {
    return {
      images: [],};
  },componentDidMount() {
    const fetchParams = {
      first: 25,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张图片




选择图片

为了让用户可以选择其中一张图片,我们冉要让上面的图片可以被点击。我们需要使用TouchableHighlight组件,当点击图片是,将图片的uri保存到另一个state变量中.

我们首先测试选择到图片的uri

selectImage(uri) {
  this.setState({
    selected: uri,});
  console.log('Selected image: ',uri);
},

同样,需要在getInitialSate()中定义

getInitialState() {
  return {
    images: [],selected: '',

以下是新的render函数

const {
  StyleSheet,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>
  );
}

当你运行这个项目时,点击图片输出图片的uri到console.

获得图片的base64数据

已经存在一个模块,它使用React native image 组件获得这个图片的base64版本。但它不能通过NPM安装。所以我们仅要在创建自定义模块是,将它添加进来。如 upload-from-camera-roll中有介绍,如何在你的项目中包含upload-form-camera-roll模块。

现在,我们可以使用这个模块从image的uri中,来获得base64编码的图片数据。 我们可以改变selectImage函数,把原来输出uri的功能,改成保存和输出图片的base64编码.

selectImage(uri) {
    NativeModules.ReadImageData.readImage(uri,(image) => {
        this.setState({
            selected: image,});
        console.log(image);
    });
},


完整代码如下

const React = require('react-native');

const {
    AppRegistry,NativeModules,} = React;

const styles = StyleSheet.create({
    container: {
        flex: 1,}
});

const reactImageProject = React.createClass({
    getInitialState() {
        return {
            images: [],};
    },componentDidMount() {
        const fetchParams = {
            first: 25,};
        CameraRoll.getPhotos(fetchParams,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对像. 如下

在Xcode中打开Libraries > RCTImage > RCTCameraRollManager.m中打开


替换这个文件

https://github.com/scottdixon/react-native-upload-from-camera-roll/blob/master/RCTCameraRollManager.m


现在你获得的图片对像就会包含base64属性。你仅需要调整相关的React Native文件,让它知道新的属性

打开/node_modules/react-native/Libraries/CameraRoll/CameraRoll.js,将下面的行,添加到76行

base64: ReactPropTypes.string,

如果你打算使用这个方法上传全分辨率的图片,应用程序会运行的超慢,因为它需要将图片转换为大型的base64字符串。

为了更好的优化,我们创建一个自定义的本地模块,它充许我们的Javascript 与Object-c通话,通过这种方式,我们给 Object-C传递一个图片资源的URI给它,Object-c在返回这个图片的base64数据。现在iOS仅在需要的时候读取一个图片。相对于上面的方法,要读取所有的图片。这是一个非常大的优化 。

创建一个自定义模块,非常简单。

在Xcode中,打开Project > Libraries > React > Base. 在Base上右键,选择New File... ,在选择Object-C文件。命名为RCTCustom.m,并且添加以下的内容。这就创建了一个ReadImageData的模块了.


#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,NativeModules} = React;

然后我们可以能过NativeModules访问我们 new module

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})
}
})
原文链接:https://www.f2er.com/react/306814.html

猜你在找的React相关文章