Задать вопрос
svisch
@svisch

Как выводить изображения в 2 или в 3 колонки в строке в зависимости от пропорций изображений?

Здравствуйте. Имеется некое подобие галереи на реакте и динамический вывод изображений с разной пропорцией сторон (назовем эти изображения горизонтальное и вертикальное, для простоты). Задача в том, что хочу, чтобы если идут подряд 3 вертикальных, то они будут в одной строке, если 2 горизонтальных или 1 горизонтальное и 1 вертикальное, то 2 в строке.
Итак, до чего дошел я в этом вопросе. Решил, что при построении контента буду проверять ширину и высоту изображения и в зависимости от результатов и задавать ширину элемента 50% или 33%. Но здесь столкнулся с проблемой:
Вот код для получения размеров картинки:
const getMeta = (url) =>
  new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => resolve(img);
    img.onerror = (err) => reject(err);
    img.src = url;
  });

// Usage example: 
(async() => {
  const img = await getMeta('https://i.sstatic.net/qCWYU.jpg');
  console.dir(img.naturalHeight + ' ' + img.naturalWidth);
})();


Вот генерация содержимого:
let items = project?.items.map(item => {
        return <div className={'project-item'}>
            <img
                key={item.id}
                src={`/img/${item.path}/${item.fileName}`}
            />
        </div>
    })

Вопрос в том как мне использовать данные ширины и высоты картинки, полученные в асинхронной функции в мэпе, чтобы уже применить свою логику в нем. Ну или может кто подскажет более изящное решение.
  • Вопрос задан
  • 101 просмотр
Подписаться 1 Средний Комментировать
Помогут разобраться в теме Все курсы
  • Нетология
    Веб-разработчик с нуля: профессия с выбором специализации
    14 месяцев
    Далее
  • Академия Эдюсон
    Fullstack-разработчик на JavaScript + ИИ
    11 месяцев
    Далее
  • ProductStar × РБК
    Профессия: Инженер по тестированию + ИИ
    6 месяцев
    Далее
Решения вопроса 1
opium
@opium
Просто люблю качественно работать
дело в том что рендер синхронный, а onload — нет. Гружи размеры всех картинок заранее: useEffect + Promise.all, складывай результат в state, и уже из готового state собирай строки по 2 или 3.

const items = await Promise.all(list.map(async i => {
  const src = `/img/${i.path}/${i.fileName}`;
  const {naturalWidth: w, naturalHeight: h} = await getMeta(src);
  return {...i, src, vertical: h > w};
}));
setItems(items);


дальше просто идёшь по items и группируешь: три вертикальных подряд — тройка, иначе пара. И да, если получится — отдавай width/height сразу в данных с бэка, тогда грузить картинки на клиенте ради размеров вообще не придётся.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы