Автоматическая высота изображения изображения с помощью React Native
В моем приложении React Native я получаю изображения из API с неизвестными размерами. Как автоматически масштабировать высоту, если я знаю желаемую ширину?
Пример:
Я установил ширину в 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???<<<
}
)
Ответы
Ответ 1
Попробуй это:
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
.
Ответ 2
Существует свойство resizeMode, устанавливающее его на "содержать"
Пример:
<Image
source={require('./local_path_to/your_image.png')}
style={{ width: 30 }}
resizeMode="contain"
/>
Источник: https://facebook.github.io/react-native/docs/image#resizemode
Ответ 3
Взгляните на эту библиотеку response-native-scalable-image. Это именно то, что вы просите.
import React from 'react';
import { Dimensions } from 'react-native';
import Image from 'react-native-scalable-image';
const image = (
<Image
width={Dimensions.get('window').width} // height will be calculated automatically
source={{uri: '<image uri>'}}
/>
);
Ответ 4
TypeScript- версия ответа @TheJizel с необязательным свойством style
и обратным Image.getSize
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}/>
Ответ 5
Сначала попробуйте это и посмотрите, работает ли оно для вас: https://github.com/facebook/react-native/commit/5850165795c54b8d5de7bef9f69f6fe6b1b4763d
Если это не так, вы можете реализовать свой собственный компонент изображения. Но вместо того, чтобы принимать ширину в качестве опоры, вы переопределяете метод onLayout
, который дает желаемую ширину, чтобы вы могли рассчитать высоту. Это работает лучше, если вы не знаете ширины и хотите, чтобы RN сделал макет для вас. Недостаток onLayout
вызывается после одного прохода макета и рендеринга. Таким образом, вы можете заметить, что ваши компоненты немного перемещаются.
Ответ 6
Вот сущность для довольно простого решения, которое использует предложение @Haitao Li для использования aspectRatio:
https://gist.github.com/tpraxl/02dc4bfcfa301340d26a0bf2140cd8b9
Никакой магии и никаких вычислений не требуется. Чистый "CSS", если вы знаете исходные размеры изображения.
Ответ 7
Предлагаемое решение работает, но вы должны загрузить изображение дважды, один раз, чтобы определить размер, и другой, чтобы фактически показать изображение, это другой подход, изображение загружается в квадрате вначале и изменяется в размере.
import React, { Component, } from "react";
import { Image } from "react-native";
import PropTypes from 'prop-types'
export default class ScaledImage extends Component {
state = {}
componentWillMount() {
const { uri, width, height } = this.props;
this.setState({ source: { uri }, width: width || height, height: height || width });
}
render() {
return (
<Image
source={this.state.source}
onLoad={(value) => {
const { height, width } = value.nativeEvent.source;
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 });
}
}}
style={{ height: this.state.height, width: this.state.width }}
/>
);
}
}
ScaledImage.propTypes = {
uri: PropTypes.string.isRequired,
width: PropTypes.number,
height: PropTypes.number
};
Ответ 8
Основываясь на идее @TheJizel, я что-то приготовил, используя свойство стиля aspectRatio. Следующий класс работает, когда ширина установлена, но высота опущена. Это также работает с процентами как ширина.
import React from "react";
import { Image, ImageProps } from "react-native";
export default class ScaledImage extends React.Component<ImageProps> {
state = {
aspectRatio: 0
}
setAspectRatio(ratio:any) {
this.setState({
aspectRatio: ratio
});
}
componentWillMount() {
if (Array.isArray(this.props.source)) {
console.warn("ScaledImage received an array as source instead of local file resource or ImageURISource.")
} else if(typeof this.props.source === "number") {
// Resolve local file resource
const resolved = Image.resolveAssetSource(this.props.source);
// We assume 100% width, so we set the aspect ratio we want for it height
this.setAspectRatio(resolved.width / resolved.height);
} else if (this.props.source.uri) {
// Resolve remote resource
Image.getSize(this.props.source.uri, (width, height) => {
this.setAspectRatio( width / height);
}, (err) => {
console.error(err);
});
} else {
console.warn("ScaledImage did not receive a valid source uri.");
}
}
render() {
if(!this.state.aspectRatio) return null;
const props = {
...this.props,
style: [this.props.style, {
aspectRatio: this.state.aspectRatio
}]
};
return (
<Image {...props} />
)
}
}
Использование:
<ScaledImage source={{ uri: "<URI HERE>" }} style={{ width: "100%" }} />
Ответ 9
У вас есть 3 номера:
- ширина изображения
- высота изображения
- ширина экрана
и вы должны поставить "ширину экрана" в стиле ширины, а также рассчитать высоту для настройки в стиле?? !!
componentWillMount() {
Image.getSize(this.props.product.image, (width, height) => {
const screenWidth = Math.round(Dimensions.get('window').width);
this.setState({screenWidth:screenWidth});
Calculatedheight = screenWidth * height / width ;
this.setState({Calculatedheight : Calculatedheight });
});
}
а также
<Image
source={{uri: product.image,cache: 'only-if-cached'}}
style={{ height: this.state.screenHeight , width: this.state.Calculatedheight }}
/>