#javascript #css #reactjs
#javascript #css #reactjs
Вопрос:
У меня есть конкретное требование, которое заключается в динамическом определении количества строк и столбцов, необходимых для охвата, на основе высоты изображения. Я попробовал несколько способов, последний из которых находится в конце вопроса.
Вот текущий код, который нуждается в предложениях
HTML
<div className="grid">
{
pictures.map((pic,i)=>{
return(
<div key={pic.name i} className="pic-container"
style={{
gridRowStart: pic.row, gridColumnStart:pic.col,
// Need to put the height amp; width of each image in the array
// in the following place to span dynamically
gridRowEnd: HEIGHT/50 , gridColumnEnd:8*(WIDTH/1400)}}>
<div>
<img src={`/pictures/${pic.name}.png`} className="pic"/>
<div className="pic-name">{pic.name}</div>
</div>
</div>
);
}
</div>
CSS
.grid{
display: grid;
grid-template-rows: repeat(99, 50px);
grid-template-columns: repeat(8, 1fr);
max-width: 1400px;
gap: 0px;
position: relative;
z-index: 2;
}
.pic-container{
width: 100%;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
}
.pic-container > div{
display: block;
width:100%;
height:100%;
}
.pic{
max-width: 100%;
max-height: 100%;
height: 100%;
object-fit: contain;
}
Последнее, что я пробовал:
const [width,setWidth] = useState(null);
const [height,setHeight] = useState(null);
.
..
...
pictures.map((pic,i)=>{
const getDim = (e) =>{
setWidth(e.target.offsetWidth);
setHeight(e.target.offsetHeight);
}
return(
<div key={'' pic.name i} className="pic-container"
style={{gridArea:`${pic.row} / ${pic.col} / span ${Math.ceil(height/50)} / span ${Math.ceil(8*(width/1400))`}}>
<div>
<img onLoad={getDim} className="pic" src={`/pictures/${pic.name}.png`}/>
<div className="pic-name">{pic.name}</div>
</div>
</div>
)
})
Идея предыдущего решения заключается в том, что каждый раз, когда мы получаем новое изображение, состояние ширины и высоты будет обновляться с учетом новых размеров изображения, а затем будет применено к промежутку. Следующее изображение обновит ширину и высоту, а затем применит их к своему диапазону и так далее и тому подобное. Но это не сработало.
Ответ №1:
Я надеюсь, что это может вам помочь.
Компонент списка изображений:
const ImageList = (props) => {
const images = props.images.map((image) => {
return <ImageCard key={image.id} image={image} />
});
return <div className="image-list">{images}</div>
Список изображений Css
.image-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
grid-gap:0 10px;
grid-auto-rows: 10px;
}
.image-list img {
width: 250px;
}
Компонент ImageCard:
class ImageCard extends React.Component {
constructor(props) {
super(props);
this.state = {
spans : 0
}
this.imageRef = React.createRef();
}
componentDidMount() {
this.imageRef.current.addEventListener('load', this.setSpans);
}
setSpans = () => {
const height = this.imageRef.current.clientHeight;
const spans = Math.ceil(height / 10);
this.setState({spans});
}
render() {
const {description, urls} = this.props.image;
return (
<div style={{gridRowEnd: `span ${this.state.spans}`}}>
<img ref={this.imageRef} src={urls.regular} alt={description} />
</div>
);
}
Комментарии:
1. @AnasNabulsi если вы используете это решение, не забудьте удалить прослушиватель событий из компонента в функции componentDidUnmount, иначе у вас возникнут проблемы с утечкой памяти!
2. Спасибо, Саад, ваше решение дало мне некоторое представление. Разделение контейнера изображения как компонента и использование ref с useEffect (componentDidMount) для получения высоты помогло мне лучше решить эту проблему, хотя мне пришлось внести коррективы в стиль, чтобы соответствовать моим требованиям.