Вопрос по изображениям

Tracktor
Tracktor
1.2K
9
Здравствуйте. Вопрос по изображениям. Что делать, если необходимо расположить рядом несколько изображений разных размеров (например, одно горизонтальное, другое вертикальное, разные по длине и ширине) таким образом, чтобы их общая ширина была равна ширине блока, в котором они находятся, но высота изображений была одна, без потери соотношения их сторон? Возможно ли такое с использованием Bootstrap? При этом, нужно сохранять их адаптивность (т.е. уменьшать при уменьшении размеров экрана). Пробовал класс img-responsive, но он, как я понял, просто вписывает изображение в ширину блока...

Комментарии: 9

  1. Сергей
    Сергей
    13.02.2017, 11:17
    Может вам sapegin.github.io/jquery.mosaicflow/ поможет. На itchief.ru и урок по этому есть itchief.ru/lessons/bootstrap-3/bootstrap-3-create-image-galleries
    1. Tracktor
      Tracktor
      13.02.2017, 12:48
      Видел этот урок. Уже думал по поводу подобных галерей, но всё равно немного не то, что нужно… В примере по ссылке высота изображений разная, а я хочу получить одну высоту всех изображений в блоке и выстроить их ровненько в ряд по ширине блока.
  2. Tracktor
    Tracktor
    13.02.2017, 10:44
    Спасибо. Попробовал, но всё равно получается немного не то. Наверное, я не точно сформулировал задачу.
    Изображения необходимо будет добавлять статьи на сайте, а скрипт поместить например перед закрытием на постоянной основе, чтобы он, видя обозначенный блок (в моём примере это div.main), совершал в нём все эти рассчёты с изображениями… Плюс, хочется видеть изображения в их полном, «необрезанном» виде. Высота контейнера при этом неважна, главная задача ровно расположить изображения по всей ширине контейнера без изменения их пропорций…
  3. Tracktor
    Tracktor
    11.02.2017, 10:28
    Александр, спасибо за ответ. Но похоже, мне всё-таки нужен будет вариант с Javascript. В данном способе, как я понял, изображения подключаются через css свойство background, а в моём случае изображения будут добавляться динамически (то есть, придётся к каждой статье на сайте менять это свойство для картинок). Плюс, картинок может быть не две, а больше.

    На одном из форумов подсказали интересное решение на JS:

    HTML:
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
    <div class="main" style="width: 800px; border: 1px solid black; margin: 0 auto;">
      <img src="http://nemalo.net/uploads/posts/2015-08/1440496077_java.jpg"><img src="https://trashbox.ru/ifiles/533976_72c4c8_screenshot_08/html-css-php-js-book-1.2.4-9.png">
    </div>
    
    JS:
    function imgSize(href){
      var img = new Image();
      img.src = href;
      img.onload = function() {
        sum += img.width / img.height;
    	loaded++;
    	if (loaded == count) $('.main img').height($('.main').width() / sum);
      };
    }
    
    var sum = 0;
    var count = $('.main img').length;
    var loaded = 0;
    $('.main img').each(function() {
      imgSize($(this).attr('src'));
    });
    Код работает, но есть три минуса:
    1. Изображения нужно добавлять вплотную друг к другу, таким образом смотрится не очень красиво без отступов.
    2. Размеры изображений вычисляются в пикселях, что приводит к потере адаптивности. Если ширину блока main задавать в процентах — размеры картинок всё равно остаются в пикселях, и при изменении размеров экрана вёрстка рушится.
    3. Если нужно создать на странице, например, два таких блока по два изображения в каждом, всё равно скрипт будет считать их общие размеры, и результат получится не тот, что нужен.

    К сожалению, с моим незнанием языка Javascript, не хватает мозгов, чтобы допилить данный скрипт…
    Если у вас найдётся время и желание помочь с этим делом, был бы очень признателен :)
    1. Александр Мальцев
      Александр Мальцев
      11.02.2017, 17:41
      Можно конечно и так сделать, но тут необходимо будет всё вычислять.
      С помощью JavaScript можно не только изображения, но и целые блоки добавлять.
      Например, в HTML создать только контейнер:
      <div id="images" class="container"></div>
      
      Скрипт JavaScript (с использованием jQuery) для динамического вывода изображений:
      <script>
      $(function(){
        var images = {
          'rows': 2,
          'landscape': ['img/l1.jpg','img/l2.jpg'],
          'portrait': ['img/p1.jpg','img/p2.jpg']
        }
        var container = $('#images');
        for (var i=0; i<images['rows'];i++) {
          container.append('<div class="rowflex" style="height: 200px;">'+
            '<div id="landscape-image'+i+'" class="colflex-xs-12 colflex-md-8"></div>'+
            '<div id="portrait-image'+i+'" class="colflex-xs-12 colflex-md-4"></div>'+
            '</div>');
          $('#landscape-image'+i).css({
            'background':'url('+images['landscape'][i]+')',
            'background-size':'cover'
          });
          $('#portrait-image'+i).css({
            'background':'url('+images['portrait'][i]+')',
            'background-size':'cover'  
          });  
        }
      });
      </script>
      
      Т.е. создаём объект images и записываем туда, сколько необходимо вывести количество блоков (например, 2) и также пути к изображениям для каждого блока.

      Тогда эти стили можно удалить из CSS:
      #landscape-image {
        background: url(img/image_1.jpg);
        background-size: cover;
      }
      #portrait-image {
        background: url(img/image_2.jpg);
        background-size: cover;
      }
      
    2. Александр Мальцев
      Александр Мальцев
      18.02.2017, 02:27
      Можно конечно и этот доработать…
      Чтобы он работал адаптивно необходимо рассчитывать тогда не высоту, а ширину и устанавливать её в процентах от ширины контейнера.
      <script>
      $(function () {
        // id - идентификатор блока, содержащий изображения
        // width - ширина всех изображений % от ширины контейнера
        // img-margin - отступы
        // img-radius - скруления углов
        var resizePictures = function(id,totalwidth,img_margin,img_radius){
          var sum = 0;
          var count = $(id).find('img').length;
          var loaded = 0;
          function imgSize(href){
            var img = new Image();
            img.src = href;
            img.onload = function() {
              sum += img.width / img.height;                                         
      	  loaded++;
      	  if (loaded == count) {
                  $(id).find('img').each(function(){
                  $(this).css({
                    'width': ((($(this).width() / $(this).height()) / sum)*totalwidth)+'%',
                    'margin': img_margin,
                    'border-radius':img_radius
                  });
                });
              };
            };
          };	  
          $(id).find('img').each(function() {
            imgSize($(this).attr('src'));
          });
        };
        resizePictures('#main',90,'3px','4px');
      });
      </script>
      
      Добавление отступов в вышепредставленном скрипте осуществляется посредством margin, и указывать их лучше в пикселях. Иначе изображения получатся немного разные, т.к. они имеют не одинаковую ширину.
      Если необходимо установить несколько таких блоков, то необходимо просто вызвать ещё раз функцию resizePictures и передать ей в качестве параметра нужный идентификатор блока.
      resizePictures('#main',90,'3px','4px');
      Но, решение на свойстве background даже на основании этого скрипта было бы более простым…
    3. Tracktor
      Tracktor
      20.02.2017, 14:37
      Громадное спасибо!
      Пара вопросов:
      1. Можно ли сразу добавить в скрипт несколько контейнеров, в которых будут ресайзиться изображения? например,
      resizePictures('#main-1',90,'3px','4px');
      resizePictures('#main-2',90,'3px','4px');
      resizePictures('#main-3',90,'3px','4px');
      
      Идея в том, чтобы подключить скрипт перед </боди> и больше к нему не возвращаться, а в статьях просто прописывать нужные классы блокам (вряд ли больше трёх будет в статье)…
      2. Правильно ли я сделал, заменив «id» на «className» во всём скрипте, если хочу идентифицировать блок с изображениями по классу, а не по ид? Вроде, работает.
    4. Александр Мальцев
      Александр Мальцев
      21.02.2017, 10:12
      1. Да, можно:
      <div id="main-1" style="margin: 0 auto; text-align:center;">
        <img src="img/1.jpg"><img src="img/2.jpg"><img src="img/3.jpg">
      </div>
      <div id="main-2" style="margin: 0 auto; text-align:center;">
        <img src="img/4.jpg"><img src="img/5.jpg"><img src="img/6.jpg">
      </div>
      <div id="main-3" style="margin: 0 auto; text-align:center;">
        <img src="img/7.jpg"><img src="img/8.jpg"><img src="img/9.jpg">
      </div>
      
      2. Можно использовать вместо id и имя класса.
  4. Александр Мальцев
    Александр Мальцев
    10.02.2017, 16:25
    Добрый день. Без JavaScript это можно выполнить только на Flexbox. Только вам необходимо указать высоту контейнера с изображениями.
    Код HTML:
    <div class="container">
      <div class="rowflex" style="height: 200px;">
        <div id="landscape-image" class="colflex-xs-12 colflex-md-8"></div>
    	<div id="portrait-image" class="colflex-xs-12 colflex-md-4"></div>
      </div>
    </div>
    
    Код CSS:
    .rowflex {
      display: -webkit-box;
      display: -webkit-flex;
      display: -ms-flexbox;
      display: flex;
      -webkit-flex-wrap: wrap;
      -ms-flex-wrap: wrap;
      flex-wrap: wrap;
    }
    @media (min-width: 768px) {
      .colflex-md-4 {
        -webkit-box-flex: 0;
        -webkit-flex: 0 0 33.333333%;
        -ms-flex: 0 0 33.333333%;
        flex: 0 0 33.333333%;
        max-width: 33.333333%;
      }
      .colflex-md-8 {
        -webkit-box-flex: 0;
        -webkit-flex: 0 0 66.666666%;
        -ms-flex: 0 0 66.666666%;
        flex: 0 0 66.666666%;
        max-width: 66.666666%;
      }
    }
    @media (max-width: 767px) {
      .colflex-xs-12 {
        -webkit-box-flex: 0;
        -webkit-flex: 0 0 100%;
        -ms-flex: 0 0 100%%;
        flex: 0 0 100%%;
        max-width: 100%%;
      }
    }
    #landscape-image {
      background: url(img/image_1.jpg);
      background-size: cover;
    }
    #portrait-image {
      background: url(img/image_2.jpg);
      background-size: cover;
    }