Реальный исходный выбор фактических размеров изображения

Я хотел бы иметь возможность узнать фактический размер загруженного по сети изображения, которое было передано в <Image/> Я пытался использовать onLayout для определения размера (как взято здесь https://github.com/facebook/реагировать-родной/проблемы/858) но это, кажется, возвращает очищенный размер после того, как он уже был передан через механизм макета.

Я попытался заглянуть в onLoadStart, onLoad, onLoadEnd, onProgress, чтобы увидеть, есть ли какая-либо другая доступная информация, но, похоже, не может заставить ее работать. Я объявил их следующим образом:

  onImageLoadStart: function(e){
    console.log("onImageLoadStart");
  },

  onImageLoad: function(e){
    console.log("onImageLoad");
  },

  onImageLoadEnd: function(e){
    console.log("onImageLoadEnd");
  },


  onImageProgress: function(e){
    console.log("onImageProgress");
  },

  onImageError: function(e){
    console.log("onImageError");
  },

  render: function (e) {
    return (
      <Image
        source={{uri: "http://adomain.com/myimageurl.jpg"}}
        style={[this.props.style, this.state.style]}
        onLayout={this.onImageLayout}
        onLoadStart={(e) => {this.onImageLoadStart(e)}}
        onLoad={(e) => {this.onImageLoad(e)}}
        onLoadEnd={(e) => {this.onImageLoadEnd(e)}}
        onProgress={(e) => {this.onImageProgress(e)}}
        onError={(e) => {this.onImageError(e)}} />
    );
  }

Благодарю.

Ответ 1

Image компонент теперь предоставляет статический метод для получения размера изображения. Например:

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

Ответ 2

Этот ответ сейчас устарел. Смотри ответ Билла.

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

Старый ответ (действительно для более старых сборок реагировать нативно)

Хорошо, я получил это работает. В настоящее время требуется некоторая модификация установки React-Native, поскольку она не поддерживается изначально.

Я следовал советам в этой теме, чтобы я смог это сделать. https://github.com/facebook/react-native/issues/494

В основном, измените файл RCTNetworkImageView.m: добавьте следующее в 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];
};

Затем отредактируйте строку, которая обрабатывает завершение загрузки:

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

замещать

loadEndHandler();

с

loadImageEndHandler(image);

Затем в React-Native у вас есть доступ к размеру через нативные события. данные из функции onLoaded - обратите внимание, в документации в настоящее время говорится, что функция onLoad но это неверно. Правильные функции следующие для v0.8.0:

onLoadStart
onLoadProgress
onLoaded
onLoadError
onLoadAbort

К ним можно получить доступ так:

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>
    );
}

Примечания к сведению:

  • Я установил большое окно изображения и установил его внутри оберточного элемента размером 1x1px, потому что изображение должно помещаться внутрь, если вы хотите получить значимые значения.

  • Режим изменения размера должен быть 'contain' чтобы вы могли получить правильные размеры, в противном случае будет сообщено об ограниченном размере.

  • Размеры изображения масштабируются пропорционально масштабному коэффициенту устройства, например, изображение 200 * 200 на iPhone6 (не 6 плюс) будет отображаться как 100 * 100. Я предполагаю, что это также означает, что на iPhone6 plus он будет отображаться как 67 * 67, но я не проверял это.

  • Я еще не получил это, чтобы работать для файлов GIF, которые пересекают другой путь на стороне моста Obj-C. Я обновлю этот ответ, как только я это сделаю.

  • Я полагаю, что в данный момент существует PR для этого, но до тех пор, пока он не будет включен в ядро, это изменение будет необходимо вносить в реактивную установку каждый раз, когда вы обновляете/переустанавливаете.

Ответ 3

Вы можете использовать метод resolveAssetSource из компонента Image:

import picture from 'pathToYourPicture';  
const {width, height} = Image.resolveAssetSource(picture);

Ответ 4

Пример TypeScript:

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));
  });
}