ReactNative: 使用第三方庫圖像選擇器react-native-image-picker和react-native-image-crop-picker


一、簡介

同前面使用第三方庫相機框架react-native-camera一樣,對於原生的圖片選擇器的使用也有第三方框架提供。分別是react-native-image-picker和react-native-image-crop-picker。 react-native-image-picker庫可以實現啟動本地相冊和照相機來采集圖片,但是沒有實現裁剪功能。針對頭像上傳的需求,一般都需要對圖片進行裁剪,此時可以使用react-native-image-crop-picker庫,該庫同樣實現了本地相冊和照相機來采集圖片,並且提供多選、圖片裁剪等功能,支持iOS和Android兩個平台。

react-native-image-picker:https://github.com/react-native-community/react-native-image-picker,基本樣式如下:

react-native-image-crop-picker:https://github.com/ivpusic/react-native-image-crop-picker,基本樣式如下:

 

二、配置plist文件

iOS10以后,訪問用戶的隱私文件需要授權,例如相冊或者相機(錄屏),因此需要打開Xcode並在項目的plist中添加授權字段。分別是NSCameraUsageDescription和NSPhotoLibraryUsageDescription以及NSMicrophoneUsageDescription(錄制視屏需要訪問麥克風)。

 

三、react-native-image-picker

1、安裝:

  • 注意自己的React-Native版本號,選擇對應的庫進行安裝。我使用的0.44.3版本RN,之前安裝高版本的react-native-image-picker總是編譯失敗。就裝了低版本的。

  • 命令行如下 
//安裝(本人安裝的是低版本的:0.28.0)
npm install react-native-image-picker@0.28.0 --save

//鏈接(系統會自動在xcode中導入xcodeproj工程和.a靜態包, link后面可以跟具體的庫名,也可以不用跟)
react-native link react-native-image-picker@0.28.0

2、配置

  • 安裝react-native-image-picker庫后需要打開xcode添加它的.xcodeproj工程和libRNImagePicker.a靜態包到項目中
  • 注意事項:如果開發者手動執行了安裝步驟的第2條命令行 react-native link xxxxxx”,則這下面的兩步就不用手動操作了,系統會幫助自動完成。

 

3、API

高版本和低版本的庫其實差別也不是特別大,本人裝的是低版本的,對低版本的api做一些簡單的注釋如下:

declare module "react-native-image-picker" {

    //這個是操作ImagePicker的方法的回調信息(主要是操作界面被點擊的信息和圖片視屏的信息)
    interface Response {
        customButton: string;
        didCancel: boolean;
        error: string;
        data: string;
        uri: string;
        origURL?: string;
        isVertical: boolean;
        width: number;
        height: number;
        fileSize: number;
        type?: string;
        fileName?: string;
        path?: string;
        latitude?: number;
        longitude?: number;
        timestamp?: string;
    }

    //在默認操作界面上添加自定義文案的按鈕
    interface CustomButtonOptions {
        name?: string;
        title?: string;
    }

    //在操作ImagePicker的方法之前,傳入的一下配置選項。主要是界面的配置選項和相機以及圖片視頻的配置選項
    interface Options {
        title?: string;
        cancelButtonTitle?: string;
        takePhotoButtonTitle?: string;
        chooseFromLibraryButtonTitle?: string;
        customButtons?: Array<CustomButtonOptions>;
        cameraType?: 'front' | 'back';
        mediaType?: 'photo' | 'video' | 'mixed';
        maxWidth?: number;
        maxHeight?: number;
        quality?: number;
        videoQuality?: 'low' | 'medium' | 'high';
        durationLimit?: number;
        rotation?: number;
        allowsEditing?: boolean;
        noData?: boolean;
        storageOptions?: StorageOptions;
    }

    //關於存儲相關的配置選項
    interface StorageOptions {
        skipBackup?: boolean;
        path?: string;
        cameraRoll?: boolean;
        waitUntilSaved?: boolean;
    }


    //ImagePicker的三方常用方法
    class ImagePicker {

        //選擇圖片(包括相機和圖庫選項)
        static showImagePicker(options: Options, callback: (response: Response) => void): void;

        //打開相機(可以拍照,也可以錄制視頻)
        static launchCamera(options: Options, callback: (response: Response) => void): void;

        //打開圖庫
        static launchImageLibrary(options: Options, callback: (response: Response) => void): void;
    }

    export = ImagePicker;

}

4、使用

 代碼如下:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    TouchableHighlight,
    View
} from 'react-native';

const ImagePicker = require('react-native-image-picker');

export default class App extends Component {

    //選擇圖片
    _showImagePicker(){

        //配置選項
        const options = {
            title: '選擇圖片',
            cancelButtonTitle: '取消',
            takePhotoButtonTitle: '拍照',
            chooseFromLibraryButtonTitle: '圖庫',
            customButtons: [
                {name: 'share photo', title: '分享'},
            ],
            cameraType: 'back',
            mediaType: 'photo',
            videoQuality: 'high',
            durationLimit: 10,
            maxWidth: 300,
            maxHeight: 300,
            quality: 0.8,
            angle: 0,
            allowsEditing: false,
            noData: false,
            storageOptions: {
                skipBackup: true
            }
        };

        //回調數據
        ImagePicker.showImagePicker(options, (response => {
             console.log("response: "+response);
        }))
    }

    //打開相機
    _launchCamera(){

        //配置選項
        const options = {
            cameraType: 'front',  //前置攝像頭
            mediaType: 'photo'    //進行拍照
        };

        //回調數據
        ImagePicker.launchCamera(options, (response => {
            console.log("response: "+response);
        }))
    }

    //打開圖庫
    _launchImageLibrary(){

        //配置選項
        const options = { mediaType: 'photo' };

        //回調數據
        ImagePicker.launchImageLibrary(options, (response => {
            console.log("response: "+response);
        }))
    }

    render() {
        return (
            <View style={styles.container}>
                <TouchableHighlight onPress={this._showImagePicker.bind(this)}>
                    <Text style={{color:'red',fontSize:30}}>選擇圖片</Text>
                </TouchableHighlight>
                <TouchableHighlight onPress={this._launchCamera.bind(this)}>
                    <Text style={{color:'red',marginTop:30,fontSize:30}}>打開相機</Text>
                </TouchableHighlight>
                <TouchableHighlight onPress={this._launchImageLibrary.bind(this)}>
                    <Text style={{color:'red',marginTop:30,fontSize:30}}>打開圖庫</Text>
                </TouchableHighlight>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    }
});

AppRegistry.registerComponent('App', () => App);

踩坑經驗:0.28.0這個版本的庫有點問題,打開相機和圖庫時,app會很慢,甚至嚴重到閃退。這是由於作者對於打開相機launchCamear和打開圖庫launchImageLibrary的方法,沒有放在主線程中執行,修改庫文件即可,如下:

運行結果如下所示:

 

 

四、react-native-image-crop-picker

1、安裝

  • 安裝react-native-image-crop-picker也需要根據自己的ReactNative版本。在github上已經寫明安裝的要求,如下: 
如果您使用的是react-native> = 0.60,請使用react-native-image-crop-picker版本> = 0.25.0。 否則,使用版本<0.25.0。
  • 命令行(同上)
//安裝
npm install react-native-image-crop-picker@0.24.1 --save

//鏈接
react-native link react-native-image-crop-picker@0.24.1

2、配置

  • 置步驟和上面的react-native-image-picker一樣,不再贅述。但是注意,仍需要手動添加如下兩個框架,否則會報錯如下:

dyld: Library not loaded: @rpath/QBImagePicker.framework/QBImagePicker
  Referenced from: /private/var/containers/Bundle/Application/1816C8C9-80A2-4860-919B-CD415E245C4C/RNDemo.app/RNDemo
  Reason: image not found

3、API

它的類構成也很簡單,如下所示: 

declare module "react-native-image-crop-picker" {
     
     //配置裁剪選項,在調用方法時需要傳入的參數
     export interface Options {
        cropping?: boolean;
        width?: number;
        height?: number;
        multiple?: boolean;
        path?: string;
        includeBase64?: boolean;
        includeExif?: boolean;
        avoidEmptySpaceAroundImage?: boolean;
        cropperActiveWidgetColor?: string;
        cropperStatusBarColor?: string;
        cropperToolbarColor?: string;
        cropperToolbarTitle?: string;
        freeStyleCropEnabled?: boolean;
        cropperTintColor?: string;
        cropperCircleOverlay?: boolean;
        disableCropperColorSetters?: boolean;
        maxFiles?: number;
        waitAnimationEnd?: boolean;
        smartAlbums?: string[];
        useFrontCamera?: boolean;
        compressVideoPreset?: string;
        compressImageMaxWidth?: number;
        compressImageMaxHeight?: number;
        compressImageQuality?: number;
        loadingLabelText?: string;
        mediaType?: string;
        showsSelectedCount?: boolean;
        forceJpg?: boolean;
        showCropGuidelines?: boolean;
        hideBottomControls?: boolean;
        enableRotationGesture?: boolean;
        cropperCancelText?: string;
        cropperChooseText?: string;
    }

    //關於圖片的信息
    export interface Image {
        path: string;
        size: number;
        data: null | string;
        width: number;
        height: number;
        mime: string;
        exif: null | object;
        cropRect: null | CropRect;
        filename: string;
        creationDate: string;
        modificationDate?: string;

    }

    //裁剪的局域信息
    export interface CropRect {
        x: number;
        y: number;
        width: number;
        height: number;
    }

    //打開選擇器,返回值是一個Promise異步函數,結果是圖片或圖片數組
    export function openPicker(options: Options): Promise<Image | Image[]>;
   
    //打開相機,返回值是一個Promise異步函數,結果是圖片或圖片數組
    export function openCamera(options: Options): Promise<Image | Image[]>;
    
    //打開裁剪器,需要指定要裁剪資源的路徑path ,返回值是一個Promise異步函數,結果是圖片
    export function openCropper(options: Options): Promise<Image>;
    
    //清除所有臨時緩存,返回值是一個Promise異步函數,無結果
    export function clean(): Promise<void>;
    
    //清除某一個資源的臨時緩存,返回值是一個Promise異步函數,無結果
    export function cleanSingle(path: string): Promise<void>;

     //裁剪選擇器 
    export interface ImageCropPicker {
        openPicker(options: Options): Promise<Image | Image[]>;
        openCamera(options: Options): Promise<Image | Image[]>;
        openCropper(options: Options): Promise<Image>;
        clean(): Promise<void>;
        cleanSingle(path: string): Promise<void>;
    }

    const ImageCropPicker: ImageCropPicker;

    export default ImageCropPicker;
}

4、使用

針對api,簡單使用如下:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    TouchableHighlight,
    View
} from 'react-native';

import ImageCropPicker from 'react-native-image-crop-picker';

export default class App extends Component {

    //打開選擇器: 裁剪單張圖片
    _openPicker1(){
       const option = { width: 300, height: 400, mediaType:"photo", cropping: true };
       ImageCropPicker.openPicker(option).then(image =>{
           alert(image);
       }, (error) =>{
           alert(error);
       });
    }

    //打開選擇器: 選擇多張圖片
    _openPicker2(){
        const option = {mediaType:"photo", multiple:true};
        ImageCropPicker.openPicker(option).then(images =>{
            alert(images);
        }, (error) =>{
            alert(error);
        });
    }

    //打開選擇器: 選擇視屏資源
    _openPicker3(){
        const option = { mediaType:"video" };
        ImageCropPicker.openPicker(option).then(video =>{
            alert(video);
        }, (error) =>{
            alert(error);
        });
    }

    //打開相機: 拍照
    _openCamera1(){
        const option = { width: 300, height: 400, mediaType:"photo", cropping: true };
        ImageCropPicker.openCamera(option).then(image =>{
            alert(image);
        }, (error) =>{
            alert(error);
        });
    }

    //打開相機: 視頻
    _openCamera2(){
        const option = { mediaType:"video" };
        ImageCropPicker.openCamera(option).then(video =>{
            alert(video);
        },(error) =>{
            alert(error);
        });
    }

    //打開截取器: 直接裁剪指定路徑下的圖片
    _openCropper(){
        const option = { path:"car.png", width: 100, height: 100, mediaType:"photo", cropping: true };
        ImageCropPicker.openCropper(option).then(image => {
            alert(image);
        },(error) =>{
            alert(error);
        });
    }

    render() {
        return (
            <View style={styles.container}>
                <TouchableHighlight onPress={this._openPicker1.bind(this)}>
                    <Text style={{color:'red',marginBottom:30,fontSize:25}}>打開選擇器:裁剪單張圖片</Text>
                </TouchableHighlight>
                <TouchableHighlight onPress={this._openPicker2.bind(this)}>
                    <Text style={{color:'red',marginBottom:30,fontSize:25}}>打開選擇器:選擇多張圖片</Text>
                </TouchableHighlight>
                <TouchableHighlight onPress={this._openPicker3.bind(this)}>
                    <Text style={{color:'red',marginTop:0,fontSize:25}}>打開選擇器:選擇視屏資源</Text>
                </TouchableHighlight>
                <TouchableHighlight onPress={this._openCamera1.bind(this)}>
                    <Text style={{color:'red',marginTop:30,fontSize:25}}>打開相機: 拍照</Text>
                </TouchableHighlight>
                <TouchableHighlight onPress={this._openCamera2.bind(this)}>
                    <Text style={{color:'red',marginTop:30,fontSize:25}}>打開相機: 視頻</Text>
                </TouchableHighlight>
                <TouchableHighlight onPress={this._openCropper.bind(this)}>
                    <Text style={{color:'red',marginTop:30,fontSize:25}}>打開裁剪器</Text>
                </TouchableHighlight>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    }
});

AppRegistry.registerComponent('App', () => App); 

結果如下:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM