React Native Retrieve Actual Image Sizes

后端 未结 4 1405
孤城傲影
孤城傲影 2020-12-24 04:56

I would like to be able to know the actual size of a network-loaded image that has been passed into I have tried using onLayout to

相关标签:
4条回答
  • 2020-12-24 05:31

    Image component now provides a static method to get the size of the image. For example:

    Image.getSize(myUri, (width, height) => {this.setState({width, height})});
    
    0 讨论(0)
  • 2020-12-24 05:40

    This answer is now out of date. See Bill's answer.

    Image.getSize(myUri, (width, height) => { this.setState({ width, height }) });
    

    Old Answer (valid for older builds of react native)

    Ok, I got it working. Currently this takes some modification of the React-Native installation as it's not natively supported.

    I followed the tips in this thread to enabled me to do this. https://github.com/facebook/react-native/issues/494

    Mainly, alter the RCTNetworkImageView.m file: add the following into setImageURL

    void (^loadImageEndHandler)(UIImage *image) = ^(UIImage *image) {
      NSDictionary *event = @{
        @"target": self.reactTag,
        @"size": @{
          @"height": @(image.size.height),
          @"width": @(image.size.width)
        }
      };
      [_eventDispatcher sendInputEventWithName:@"loaded" body:event];
    };
    

    Then edit the line that handles the load completion:

    [self.layer removeAnimationForKey:@"contents"];
    self.layer.contentsScale = image.scale;
    self.layer.contents = (__bridge id)image.CGImage;
    loadEndHandler();
    

    replace

    loadEndHandler();
    

    with

    loadImageEndHandler(image);
    

    Then in React-Native you have access to the size via the native events. data from the onLoaded function - note the documentation currently says the function is onLoad but this is incorrect. The correct functions are as follows for v0.8.0:

    onLoadStart
    onLoadProgress
    onLoaded
    onLoadError
    onLoadAbort
    

    These can be accessed like so:

    onImageLoaded: function(data){
        try{
            console.log("image width:"+data.nativeEvents.size.width);
            console.log("image height:"+data.nativeEvents.size.height);
        }catch(e){
            //error
        }
    },
    ...
    render: function(){
        return (
            <View style={{width:1,height:1,overflow='hidden'}}>
                <Image source={{uri: yourImageURL}} resizeMode='contain' onLoaded={this.onImageLoaded} style={{width:5000,height:5000}} />
            </View>
        );
    }
    

    Points to note:

    • I have set a large image window and set it inside a wrapping element of 1x1px this is because the image must fit inside if you are to retrieve meaningful values.

    • The resize mode must be 'contain' to enable you to get the correct sizes, otherwise the constrained size will be reported.

    • The image sizes are scaled proportionately to the scale factor of the device, e.g. a 200*200 image on an iPhone6 (not 6 plus) will be reported as 100*100. I assume that this also means it will be reported as 67*67 on an iPhone6 plus but I have not tested this.

    • I have not yet got this to work for GIF files which traverse a different path on the Obj-C side of the bridge. I will update this answer once I have done that.

    • I believe there is a PR going through for this at the moment but until it is included in the core then this change will have to be made to the react-native installation every time you update/re-install.

    0 讨论(0)
  • 2020-12-24 05:43

    You can use resolveAssetSource method from the Image component :

    import picture from 'pathToYourPicture';  
    const {width, height} = Image.resolveAssetSource(picture);
    
    0 讨论(0)
  • 2020-12-24 05:50

    TypeScript example:

    import {Image} from 'react-native';
    
    export interface ISize {
      width: number;
      height: number;
    }
    
    function getImageSize(uri: string): Promise<ISize> {
      const success = (resolve: (value?: ISize | PromiseLike<ISize>) => void) => (width: number, height: number) => {
        resolve({
          width,
          height
        });
      };
      const error = (reject: (reason?: any) => void) => (failure: Error) => {
       reject(failure);
      };
    
      return new Promise<ISize>((resolve, reject) => {
        Image.getSize(uri, success(resolve), error(reject));
      });
    }
    
    0 讨论(0)
提交回复
热议问题