2015-09-17 12 views
6

Ich versuche, Bilder von meiner Testgeräte-Kamerarolle als Miniaturbilder zu rendern. Ich habe die Bilder erfolgreich von der Kamerarolle geholt und sie in einer Reihe von Bildelementen in einer Listenansicht angezeigt, aber das Laden dauert sehr lange. Außerdem lese ich in den React Native-Dokumenten, dass das Image-Element die Datei auswählen wird Korrekte Bildgröße für den Raum, in den es gerendert wird.React Native - So erhalten Sie Kamera-Roll-Thumbnails anstelle von Bildern in voller Größe

Dies ist aus der Dokumentation.

iOS speichert mehrere Größen für das gleiche Bild in der Kamerarolle, es ist sehr wichtig, aus Gründen der Leistung eine auszuwählen, die so nah wie möglich ist. Sie möchten nicht das volle 3264 x 2448-Bild als Quelle verwenden, wenn Sie eine 200 x 200-Miniaturansicht anzeigen. Wenn es eine genaue Übereinstimmung gibt, wird sie von React Native ausgewählt, andernfalls wird die erste verwendet, die mindestens 50% größer ist, um Unschärfe bei der Größenänderung zu vermeiden. All dies geschieht standardmäßig, sodass Sie sich keine Gedanken darüber machen müssen, wie Sie den langwierigen (und fehleranfälligen) Code selbst erstellen können. https://facebook.github.io/react-native/docs/image.html#best-camera-roll-image

Der Code, den ich verwende, um die Bilder zu lesen, ist super einfach.

CameraRoll.getPhotos({ 
     first: 21, 
     assetType: 'Photos' 
    }, (data) => { 
     console.log(data); 
     var images = data.edges.map((asset) => { 
      return { 
       uri: asset.node.image.uri 
      }; 
     }); 

     this.setState({ 
      images: this.state.images.cloneWithRows(images) 
     }); 
    },() => { 
     this.setState({ 
      retrievePhotoError: messages.errors.retrievePhotos 
     }); 
    }); 

Und dann um es zu rendern habe ich diese Funktionen.

renderImage(image) { 
    return <Image resizeMode="cover" source={{uri: image.uri}} style={[{ 
     height: imageDimensions, // imageDimensions == 93.5 
     width: imageDimensions 
    }, componentStyles.thumbnails]}/>; 
}, 

render() { 
    <ListView 
     automaticallyAdjustContentInsets={false} 
     contentContainerStyle={componentStyles.row} 
     dataSource={this.state.images} 
     renderRow={this.renderImage} 
    /> 
} 

Was fehlt mir hier? Ich werde verrückt!!!

+0

kommst du mit JavaScript-Lösung noch heraus? –

Antwort

0

OK, es ist möglich, aber Sie müssen Ihre Hände in die Objective-C-Partei von react-native legen.

Sie können überprüfen this.

Sie müssen die Datei RCTCameraRollManager.m ändern.

Sie werden diese Zeilen hinzufügen:

ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; 

NSURL *url = [[NSURL alloc] initWithString:uri]; 

[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]; 
    CGSize dimensions = [UIImage imageWithCGImage:imageRef].size; 

    // Create UIImageJPEGRepresentation from CGImageRef 
    NSData *imageData = UIImageJPEGRepresentation([UIImage imageWithCGImage:imageRef], 0.1); 

vor der [assets addObject:@{...}] Methode und fügen:

} failureBlock:^(NSError *error) { 
    NSLog(@"that didn't work %@", error); 
}]; 

nach der [assets addObject:@{...}] Methode.

Sie können auch die Prop @"base64": base64Encoded in der [assets addObject:@{ Methode hinzufügen.

Überprüfen Sie den Link, Sie haben die "neue Datei", die Ihnen die Miniaturansicht (Größe 125 x 125) gibt.

1

Ich kämpfte auch um die Lösung zu finden. Offensichtlich react-native-image-resizer

löst dies. Hier ist, wie ich es verwendet:

import ImageResizer from 'react-native-image-resizer'; 

async getPhotos(){ 
    await CameraRoll.getPhotos({ 
     first: 10 , 
     assetType: 'Photos' 
    }) 
    .then(r => { 
     this.setState({ photos:r.edges, endCursorPhotos:r.page_info.end_cursor }) 
     let resizePromiseArray = [] 
     for(let i=0; i<r.edges.length; i++){ 
      resizePromiseArray.push(ImageResizer.createResizedImage(r.edges[i].node.image.uri , 300, 500, 'JPEG', 100)) 
     } 
     return Promise.all(resizePromiseArray) 
    }) 
    .then(newUris=>{ 
     // console.log(JSON.stringify(this.state.photos,null,4)) 
     let newPhotos = this.state.photos.map((photo,i) => { 
      photo.node.image['optiUri'] = newUris[i] 
      return photo 
     }) 
     this.setState({ photos:newPhotos }) 
    }) 
    .catch(err =>{ 
     console.log(err) 
    }) 
} 

Ich füge das Miniaturbild, um das Bildobjekt eine Option zu haben, um entweder als nötig.
Sie können nur ein Bild verkleinern.

Es ist nicht unglaublich schnell also, es ist besser, es bei ComponentDidMount zu tun. Ein noch besserer Ansatz ist, es in einem dieser Fotos in einem Modal zu verwenden, während die Elternkomponente laden und Fotos speichern, bevor der Benutzer auf sie zugreift

Verwandte Themen