Как стать автором
Обновить

Простой фотоколлаж на JavaScript

image
Год-два назад, когда тема фотоколлажей в интернете только начинала набирать обороты, мне стало интересно, как же это работает? И все это время, я оставлял этот вопрос «на потом». Как видимо зря — все оказалось гораздо проще.

Почему не готовые плагины?

  • Некоторые плагины просчитываю размер изображений случайным образом — при обновлении страницы коллаж меняет свой вид
  • Трудность в кастомизации
  • Трудность в подключении LightBox или FancyBox
  • Многие плагины обрезают или меняют пропорции изображения

Что было целью?

  • Написание и понимание простого алгоритма фотоколлажа для удобства кастомизации под любые нужды и проекты

Что целью не было

  • Супер универсальность
  • Куча понятных и непонятных настроек под все случаи жизни

Стили


#collage{ width: 600px;}
#collage img{ display: block; float: left;}
.clear{ *zoom: 1;}
.clear:before,
.clear:after { display: table; content: ""; line-height: 0;}
.clear:after { clear: both;}

Разметка


Все изображение имеют «float: left» поэтому не забываем о классе «clear».
В атрибутах каждого изображения обязательно должны быть указаны width и height.
<div id="collage" class="clear">
    <img width="300" height="400" src="http://placehold.it/300x400/ffdd00/ffffff" alt=""/>
    <img width="255" height="120" src="http://placehold.it/255x120/37dcff/ffffff" alt=""/>
    <img width="300" height="300" src="http://placehold.it/300x300/28c933/ffffff" alt=""/>
    <img width="425" height="222" src="http://placehold.it/425x222/0069ff/ffffff" alt=""/>
    <img width="148" height="254" src="http://placehold.it/148x254/ff5e00/ffffff" alt=""/>
    <img width="456" height="321" src="http://placehold.it/456x321/ff9959/ffffff" alt=""/>
</div>

JavaScript


    var collage = document.getElementById('collage');
    var images = collage.getElementsByTagName('img');
    //Маленький набор опций: averageRowHeight - примерная высота строки; gap - отступы между картинками;
    var options = {averageRowHeight: 175, gap: 3};
    var widths = [], rows = [], rowNumber = 0, index = 0, k = 0;
    //Записываем в массив ширину каждой картинки при одинаковой высоте
    for(var i = 0; i < images.length; i++){
        widths.push(Math.round(images[i].width / images[i].height * options.averageRowHeight));
    }
    //Функция суммы элементов массива
    Array.prototype.sum = function(){
        return this.reduce( function(prev,current){ return  +current + prev; }, 0);
    }
    //Разбиение оизображений на строки обичным деление общей ширины всех картинок на ширину контейнера
    while(rowNumber < Math.ceil(widths.sum() / collage.clientWidth)){
        rows[rowNumber] = [];
        //Как только общая ширина картинок превысила ширину контейнера переходим на следующую строку
        while(index < widths.length && rows[rowNumber].sum()+(rows[rowNumber].length * options.gap) < collage.clientWidth + options.gap){
            rows[rowNumber].push(widths[index]);
            index++;
            //Если на последнюю строку осталось одно изображение, то дописываем его в "предпоследнюю"
            if(index == widths.length - 1){
                rows[rowNumber].push(widths[index]);
                rowNumber++;
                break;
            }
        }
        rowNumber++;
    }
    index = 0;
    //Непосредственно изменение масштаба картинок (пропорционально, без обрезания изображений)
    for(var i = 0; i < rows.length; i++){
        for(var j = 0; j < rows[i].length; j++){
            // Если ширина строки больше/меньше ширины контейнера - соответственно
            // уменьшаем/увеличиваем до ширины контейнера с учетем отступов между картинками
            k = (collage.clientWidth - ((rows[i].length - 1) * options.gap)) / rows[i].sum();
            images[index].style.width = rows[i][j] * k  + 'px';
            images[index].style.height = k * options.averageRowHeight + 'px';
            if(j < rows[i].length - 1) images[index].style.marginRight = options.gap + 'px';
            if(i < rows.length - 1) images[index].style.marginBottom = options.gap + 'px';
            index++;
        }
    }

Как видно, немного математики и задача решилась совсем не сложным способом, чуть больше чем в 30 строк JavaScript кода.

И в заключение ссылка на fiddle.
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.