kfiroo / react-native-cached-image

CachedImage component for react-native
MIT License
938 stars 470 forks source link

How to get the size of the cached image ? #147

Open mmoonn2 opened 5 years ago

mmoonn2 commented 5 years ago

How get the size of the cached image

Like this

Image.getSize(this.state.source.uri, (width: any, height: any) => {
   this.setState({
      width: windowWidth,
         height: height * (windowWidth / width)
      });
   }, () => { })
slonv23 commented 5 years ago

@junjun16818 this should work:

import React from 'react';
import { StyleSheet, View, Image, FlatList, ImageBackground } from 'react-native';
import { CachedImage } from 'react-native-cached-image';

class ListItem extends React.PureComponent {

    constructor(props) {
        super(props);

        this.state = {aspectRatio: null};
    }

    _onPress = () => {
      this.props.onPressItem(this.props.id);
    };

    render() {
      return (
        <View style={styles.imageContainer}>
            <CachedImage
                renderImage={props =>
                    (<ImageBackground imageStyle={props.style} ref={ref => {
                        if (ref && ref.props.source && ref.props.source.uri) {
                            Image.getSize(ref.props.source.uri, (width, height) => {
                                this.setState({aspectRatio: width/height});
                            });
                        }
                    }} {...props} />)}
                source={this.props.source}
                style={[styles.image, this.props.style, {aspectRatio: this.state.aspectRatio}]} />
        </View>
      );
    }

}

const styles = StyleSheet.create({
    image: {
        height: 158,
        borderRadius: 4
    },
    imageContainer: {
        marginRight: 8
    }
});
benvium commented 5 years ago

@slonv23 That should work but will the Image.getSize call use the cached version of the image? I suspect it may result in another request to download the image as we're using React Native's built-in image handling there.

Thrajnor commented 5 years ago

@benvium Is that so? Did you by any chance confirmed it? It would greatly help me out.

benvium commented 5 years ago

@Thrajnor Hi there. For me, another network request was made when Image.getSize() is used with a remote image. I had a temporarily misconfigured server that resulted in the whole image being downloaded again - e.g. was downloaded twice to measure the image then display it. If your server's cacheing is set up correctly, RN will download it once then used the cached version.

Thrajnor commented 5 years ago

Got it. Thanks for quick response. Though I've ended up using react-native-fast-image and checked size of image in onLoad attribute. Anyway thanks for your in site :)

nzaillian commented 5 years ago

Hey, was there ever any resolution to this issue? I am trying to work through a solution and I do not think the nuance that @benvium pointed out actually resolves things for our project. Our use-case looks like the following:

1) on first application load, we fetch a group of images (~100 or so) using ImageCacheManager.downloadAndCacheUrl (but do not display them). 2) Subsequently, several navigation actions away, we show some of the images.

It is at this point, several navigation actions away (and when the user may not have an active internet connection) where I am trying to get the size of the cached image. Using Image.getSize and passing the URI does, in this case, always seem to re-fetch the image. Is there perhaps some hack wherein I can directly read the local file (i.e. based on the path of theImageInstance.state.cachedImagePath) and somehow get size based on the content (or perhaps some other strategy)? I am curious what people are doing and if I am missing something.

nzaillian commented 5 years ago

I am not sure whether there is another approach but thought I should share in this issue that the following approach (using react-native-fs) seems to work to determine the size of an image when you have a reference to the file within the filesystem (and so I think it solves our problem):

    import RNFS from 'react-native-fs';

    // assumes that you have pointed this._cachedImage to a 
    // CachedImage component instance via `ref=...`
    const localPath = this._cachedImage.state.cachedImagePath;

    if (localPath) {
      RNFS.readFile(localPath, 'base64').then((fileContents) => {
        const dataUri = `data:image/jpeg;base64,${fileContents}`;
        Image.getSize(dataUri, (imageWidth, imageHeight) => {
          // do whatever you want with the image imageWidth/imageHeight passed in here...
        });
      });

Still, if there is some other, better approach I would be interested.

slonv23 commented 5 years ago

@slonv23 That should work but will the Image.getSize call use the cached version of the image? I suspect it may result in another request to download the image as we're using React Native's built-in image handling there.

Strange, new request should not be made, because uri should be the path to file in filesystem, not remote url.

image