Pull to refresh

Простой фотоколлаж на 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.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.