2017-02-10 4 views
19

В моем приложении React Native я получаю изображения из API с неизвестными размерами. Как автоматически масштабировать высоту, если я знаю свою желаемую ширину?Автомасштабирование изображения с помощью React Native

Пример:

установить ширину, чтобы Dimensions.get('window').width. Как установить высоту и сохранить одинаковое соотношение?

export default class MyComponent extends Component { 
    constructor(props) { 
    super(props) 
    this.state = { 
     imgUrl: 'http://someimg.com/coolstuff.jpg' 
    } 
    } 

    componentDidMount() { 
    // sets the image url to state 
    this.props.getImageFromAPi() 
    } 

    render() { 
    return (
     <View> 
     <Image 
      source={uri: this.state.imgUrl} 
      style={styles.myImg} 
     /> 
     <Text>Some description</Text> 
     </View> 
    ) 
    } 
} 

const styles = StyleSheet.create(
    myImg: { 
    width: Dimensions.get('window').width, 
    height: >>>???what goes here???<<< 
    } 
) 
+0

Посмотрите [среагировать родной-масштабируемой образа ] (https://www.npmjs.com/package/react-native-scalable-image) –

ответ

17

Попробуйте это:

import React, { Component, PropTypes } from 'react'; 
import { Image } from 'react-native'; 

export default class ScaledImage extends Component { 
    constructor(props) { 
     super(props); 
     this.state = {source: {uri: this.props.uri}}; 
    } 

    componentWillMount() { 
     Image.getSize(this.props.uri, (width, height) => { 
      if (this.props.width && !this.props.height) { 
       this.setState({width: this.props.width, height: height * (this.props.width/width)}); 
      } else if (!this.props.width && this.props.height) { 
       this.setState({width: width * (this.props.height/height), height: this.props.height}); 
      } else { 
       this.setState({width: width, height: height}); 
      } 
     }); 
    } 

    render() { 
     return (
      <Image source={this.state.source} style={{height: this.state.height, width: this.state.width}}/> 
     ); 
    } 
} 

ScaledImage.propTypes = { 
    uri: PropTypes.string.isRequired, 
    width: PropTypes.number, 
    height: PropTypes.number 
}; 

Я передавая URL в качестве опоры под названием uri. Вы можете указать width опору как Dimensions.get('window').width, и это должно покрыть ее.

Обратите внимание, что это также будет работать, если вы знаете, что хотите установить высоту, и вам нужно изменить размер ширины, чтобы поддерживать соотношение. В этом случае вы должны указать height, а не width.

+0

Это работает, спасибо вам большое. Удивительно, что для этого не существует метода сборки. Я думаю, что RN все еще довольно новый. – plmok61

+0

@ plmok61 Вы также можете попробовать «resizeMode» в классе «Image» и применить «flex» в своих стилях. Сначала я попробовал это, но мне не понравилось, как высота контейнера не будет расширяться на основе масштабирования изображения. – TheJizel

+0

Чтобы добавить реальный путь к URL-адресу изображения? – Somename

1

Сначала попробуйте это и посмотреть, если он работает для вас: https://github.com/facebook/react-native/commit/5850165795c54b8d5de7bef9f69f6fe6b1b4763d

Если это не так, то вы можете реализовать свой собственный компонент изображения. Но вместо того, чтобы принимать ширину в качестве опоры, вы переопределяете метод onLayout, который дает вам желаемую ширину, чтобы вы могли рассчитать высоту. Это работает лучше, если вы не знаете ширины и хотите, чтобы RN сделал макет для вас. Недостаток onLayout вызывается после одного прохода макета и рендеринга. Таким образом, вы можете заметить, что ваши компоненты немного перемещаются.

1

Вот суть для довольно простого решения, который использует предложение @Haitao Li «s использовать AspectRatio:

https://gist.github.com/tpraxl/02dc4bfcfa301340d26a0bf2140cd8b9

Нет магии и никаких расчетов необходимы. Чистый «CSS», если вы знаете размеры оригинального изображения.

0

версия машинопись из @TheJizel ответа с опциональным style собственности и failure обратного вызова в Image.getSize: использование

import * as React from 'react' 
import {Image} from 'react-native' 

interface Props { 
    uri: string 
    width?: number 
    height?: number 
    style? 
} 

interface State { 
    source: {} 
    width: number 
    height: number 
} 

export default class ScaledImage extends React.Component<Props, State> { 
    constructor(props) { 
     super(props) 
     this.state = { 
      source: {uri: this.props.uri}, 
      width: 0, 
      height: 0, 
     } 
    } 

    componentWillMount() { 
     Image.getSize(this.props.uri, (width, height) => { 
      if (this.props.width && !this.props.height) { 
       this.setState({width: this.props.width, height: height * (this.props.width/width)}) 
      } else if (!this.props.width && this.props.height) { 
       this.setState({width: width * (this.props.height/height), height: this.props.height}) 
      } else { 
       this.setState({width: width, height: height}) 
      } 
     }, (error) => { 
      console.log("ScaledImage:componentWillMount:Image.getSize failed with error: ", error) 
     }) 
    } 

    render() { 
     return <Image source={this.state.source} style={[this.props.style, {height: this.state.height, width: this.state.width}]}/> 
    } 
} 

Пример:

<ScaledImage style={styles.scaledImage} uri={this.props.article.coverImageUrl} width={Dimensions.get('window').width}/> 
Смежные вопросы