Домой / Для сайта / Как создать мозаичный слайдер
Как создать мозаичный слайдер

Как создать мозаичный слайдер

Урок, который показывает, как воссоздать четыре мозаичных слайд-шоу эффекта которые я видел на

веб-сайте Serge Thoroval. Будем использовать 3D-преобразования, переходы и анимации, цель заключается в реализации smooth-эффекта и добавлении нескольких его вариантов.

Сегодня мы хотели бы показать вам, как воссоздать фоновый слайдер изображений, который мы видели на потрясающем сайте Serge Thoroval’s Atelier, который был создан и спроектирован талантливой Жан-Кристоф Сюзанной и Джонатаном Да Коста. Если вы еще не видели веб-сайте, вы должны обязательно пойти и посмотреть; он полон интересных и творческих эффектов. Слайд-шоу, что мы воссоздадим сегодня, состоит из четырех плиток, которые перемещаются по отдельности, что делает раскол изображения при масштабировании до новое изображение. Все это объединяется в действительно хороший эффект, который мы будем повторно реализовывать сегодня с использованием 3D-преобразования, переходов и анимации. В дополнение к этому мы также добавим еще два изменения. Цель, которую мы хотим достигнуть — супер-гладкий эффект.

Обратите внимание, что мы будем использовать очень современные свойства CSS, поэтому желаемый эффект будет работать только в новейших версиях браузеров.

Демо Скачать исходники

Давайте начнем с разметки.

Разметка

Для слайд-шоу нам нужна специальная структура, которая позволит нам играть с четырьмя различными плитками, содержащее то же изображение, но с разным позиционированием. Мы должны убедиться, что все растянуто по всей области просмотра, так как это «полноэкранный» слайдер. Мы определим простую первоначальную структуру, что позволит нам указать, какие изображения будут видны на каждой панели (или слайде), а затем мы создадим и структуру для плитки.

Так, для начала нам нужно что-то вроде этого:


<div id="boxgallery" class="boxgallery" data-effect="effect-1">

<div class="panel"><img src="img/1.jpg" alt="Image 1"/></div>


<div class="panel"><img src="img/2.jpg" alt="Image 2"/></div>


<div class="panel"><img src="img/3.jpg" alt="Image 3"/></div>


<div class="panel"><img src="img/4.jpg" alt="Image 4"/></div>

</div>

Для того, чтобы иметь возможность оживить изображение, разбив его на плитки нам понадобится следующая повторная структура для каждой панели:


<div id="boxgallery" class="boxgallery" data-effect="effect-1">

<div class="panel current">

<div class="bg-tile">

<div class="bg-img"><img src="img/1.jpg" /></div>

        </div>


<div class="bg-tile">

<div class="bg-img"><img src="img/1.jpg" /></div>

        </div>


<div class="bg-tile">

<div class="bg-img"><img src="img/1.jpg" /></div>

        </div>


<div class="bg-tile">

<div class="bg-img"><img src="img/1.jpg" /></div>

        </div>

    </div>


<div class="panel">

<div class="bg-tile">

<div class="bg-img"><img src="img/2.jpg" /></div>

        </div>


<div class="bg-tile">

<div class="bg-img"><img src="img/2.jpg" /></div>

        </div>


<div class="bg-tile">

<div class="bg-img"><img src="img/2.jpg" /></div>

        </div>


<div class="bg-tile">

<div class="bg-img"><img src="img/2.jpg" /></div>

        </div>

    </div>


<div class="panel">
        <!-- ... -->
    </div>


<div class="panel">
        <!-- ... -->
    </div>


<nav>
        <span class="prev"><i></i></span>
        <span class="next"><i></i></span>
    </nav>

</div>

Мы также должны добавить навигацию, чтобы мы могли просматривать варианты. Атрибут данных data-effect позволит определить некоторые индивидуальные вариации эффекта.
Естественно, вы можете посмотреть на структуру и подумать, почему бы не использовать фоновые изображения вместо элементов изображения? После некоторых попыток для лучшей кросс-браузерности, мы пришли к выводу, что использование background image вместе с  background-size может привести к достаточно порывистым переходам. Использование например, background-size: cover может стать основным источником рывков. Другим важным моментом есть то, что вызывает дергающийся переход (по крайней мере, в Chrome) это использования процентных значения при переходе. На первый взгляд это может быть не заметно, но при сравнении вы сможете увидеть значительную разницу. По этой причине мы не будем использовать классы для управления преобразований, но вместо этого мы сделаем это в нашем сценарии, получив значения пикселей в окне проекции и применяя соответствующие значения для плитки в «background images».
Давайте добавим стили.

CSS

С созданной структуру в памяти, мы теперь добавить стили.
Обратите внимание, что CSS не будет содержать никаких префиксов, но вы найдете их в файлах.
Прежде всего, мы находимся в «полноэкраннй» области, потому к этому мы должны подготовить элементы нашей страницы. Значения html, body и container на высоту 100% позволит нам расширить наш слайдер на всю высоту окна:

html, body, .container {
    height: 100%;
}

The main wrapper and the child divisions will all be of absolute positioning and the panels will occupy all the width and height:

Основная обертка и дочерняя часть будет иметь абсолютное позиционирование, и панели займут всю ширину и высоту:

.js .boxgallery,
.js .boxgallery div {
    position: absolute;
}

.js .boxgallery,
.js .panel {
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

Так как наши эффекты потенциально будут иметь элементы перемещения из своих границ, так же мы позаботимся, что ничего не переполняется:

.js .boxgallery,
.bg-tile,
.bg-img {
    overflow: hidden;
}

При взгляде на эффект слайд-шоу Сержа, вы заметите, что при навигации, новый слайд масштабируется. Мы будем использовать 3D-преобразования везде где мы можем, поэтому мы должны добавить некоторую перспективу к обертке слайда,  в итоге мы можем перевести отдельные плитки на оси, то есть сделать их визуально меньшими:

.panel {
    z-index: 0;
    perspective: 1200px;
}

Далее, мы должны записать стили для плитки. Поскольку у нас есть четыре плитки, то каждая плитка будет 50% в высоту и ширину:

.bg-tile {
    width: 50%;
    height: 50%;
}

Позиционируем каждую плитку:

.bg-tile:nth-child(2),
.bg-tile:nth-child(4) {
    left: 50%;
}

.bg-tile:nth-child(3),
.bg-tile:nth-child(4) {
    top: 50%;
}

Внутреннее деление с классом bg-img займет всю плитку:

.bg-img {
    width: 100%;
    height: 100%;
    background: #999;
}

Для того чтобы разместить изображения таким образом, что бы показывало только один полный образ за плиткой, нам нужно установить ширину и высоту в два раза больше. Используя процентовку на обоих, ширина и высота будет искажать наш стиль, поэтому мы должны убедиться что поддерживаем соотношения сторон. Мы можем сделать это путем установки только одного из размеров до 200%, и пусть другой определяется автоматически. Но на какой из нам это установить? К счастью, у нас есть медиа запросы и одно выражение которое в частности поможет нам сделать именно то, что мы хотим:min-aspect-ratio. Это позволяет нам просто взять реальный размер наших изображений как отношение значений (ширина/высота) и определить, когда мы хотим рассчитать ширину и  высоту автоматически:

.bg-img img {
    position: absolute;
    display: block;
    height: 200%;
}

@media screen and (min-aspect-ratio: 1280/850) {
    .bg-img img {
        width: 200%;
        height: auto;
    }
}

Вы можете настроить этот метод для добавление ширины/высоты для того чтобы достигнуть желаемого впечатления от просмотра изображения на любом размере экрана. Для выезда слайдов  этот маленький и простой метод отлично работает.
Каждое изображение должно быть расположено так:

.bg-tile:nth-child(2) .bg-img img,
.bg-tile:nth-child(4) .bg-img img {
    left: -100%;
}

.bg-tile:nth-child(3) .bg-img img,
.bg-tile:nth-child(4) .bg-img img {
    top: -100%;
}

Стиль навигации от Arrow Navigation Styles.
Давайте определим, что происходит, когда мы пользуемся навигацией.
Прежде всего, нам нужно установить значение z-index в текущей панели так, чтобы она оставалась поверх всех остальных. Так как мы ранее установили  z-индексы для панелей, мы можем использовать значение 1. Но поскольку у нас есть .current панель которая должна быть показана непосредственно под ним (следующая или предыдущая), мы установим z-индексы следующим образом:

.panel.current {
    z-index: 2;
}

.panel.active {
    z-index: 1;
}
.panel.current .bg-img {
    transition: transform 1.1s ease-in-out;
}

Для первого эффекта (тот, который мы пытаемся воссоздать) и для второго (который перемещается плитки снаружи), мы хотим, чтобы следующая панель появляться со эффект спада вниз :

.boxgallery[data-effect="effect-1"] .panel.active .bg-tile,
.boxgallery[data-effect="effect-2"] .panel.active .bg-tile {
    animation: scaleDown 1.1s ease-in-out;
}

@keyframes scaleDown {
    from { transform: translate3d(0,0,380px); }
    to { transform: translate3d(0,0,0); }
}

Следующий эффект:

/* Variation 2 */

.boxgallery[data-effect="effect-2"] .panel.current .bg-img {
    transition: transform 0.9s cubic-bezier(0.7,0,0.3,1);
}

.boxgallery[data-effect="effect-2"] .panel.current .bg-tile:nth-child(2) .bg-img {
    transition-delay: 0.15s;
}

.boxgallery[data-effect="effect-2"] .panel.current .bg-tile:nth-child(3) .bg-img {
    transition-delay: 0.3s;
}

.boxgallery[data-effect="effect-2"] .panel.current .bg-tile:nth-child(4) .bg-img {
    transition-delay: 0.45s;
}

Третий вариант служит примером использования наложения, которое будет исчезать как только новая панель раскрывается:

/* Variation 3 */

.boxgallery[data-effect="effect-3"] .panel::after {
    position: absolute;
    width: 100%;
    height: 100%;
    background: rgba(0,0,0,0.8);
    content: '';
    transition: opacity 1.1s ease-in-out;
}

.boxgallery[data-effect="effect-3"] .panel.current::after,
.boxgallery[data-effect="effect-3"] .panel.active::after {
    opacity: 0;
}

.boxgallery[data-effect="effect-3"] .panel.current::after {
    transition: none;
}

Мы будем также использовать одну и туже же кубическую функцию синхронизации и определим некоторые задержки (так же самое, как и раньше).

.boxgallery[data-effect="effect-3"] .panel.current .bg-img {
    transition: transform 1.1s cubic-bezier(0.7,0,0.3,1);
}

.boxgallery[data-effect="effect-3"] .panel.current .bg-tile:nth-child(2) .bg-img {
    transition-delay: 0.15s;
}

.boxgallery[data-effect="effect-3"] .panel.current .bg-tile:nth-child(3) .bg-img {
    transition-delay: 0.3s;
}

.boxgallery[data-effect="effect-3"] .panel.current .bg-tile:nth-child(4) .bg-img {
    transition-delay: 0.45s;
}

После того добавим JavaScript будет возможность создавать новые эффекты, у вас будет очень много возможностей!

JavaScript

Добавим следующие функции:

BoxesFx.prototype._init = function() {
    // set transforms configuration
    this._setTransforms();
    // which effect
    this.effect = this.el.getAttribute( 'data-effect' ) || 'effect-1';
    // check if animating
    this.isAnimating = false;
    // the panels
    this.panels = [].slice.call( this.el.querySelectorAll( '.panel' ) );
    // total number of panels (4 for this demo)
    //this.panelsCount = this.panels.length;
    this.panelsCount = 4;
    // current panel´s index
    this.current = 0;
    classie.add( this.panels[0], 'current' );
    // replace image with 4 divs, each including the image
    var self = this;
    this.panels.forEach( function( panel ) {
        var img = panel.querySelector( 'img' ), imgReplacement = '';
        for( var i = 0; i < self.panelsCount; ++i ) {
            imgReplacement += '
<div class="bg-tile">
<div class="bg-img"><img src="' + img.src + '" /></div>
</div>

'
        }
        panel.removeChild( img );
        panel.innerHTML = imgReplacement + panel.innerHTML;
    } );
    // add navigation element
    this.nav = document.createElement( 'nav' );
    this.nav.innerHTML = '<span class="prev"><i></i></span><span class="next"><i></i></span>';
    this.el.appendChild( this.nav );
    // initialize events
    this._initEvents();
}

Переменные значения рассчитываются используя ширину и высоту окна. Мы также добавим 10 пикселей для того чтобы переходы не заканчивались в последней видимой точке, а чуть дальше, добавив еще немного эффекта гладкости:

BoxesFx.prototype._setTransforms = function() {
    this.transforms = {
        'effect-1' : {
            'next' : [
                'translate3d(0, ' + (win.height/2+10) + 'px, 0)', // transforms for panel 1
                'translate3d(-' + (win.width/2+10) + 'px, 0, 0)', // transforms for panel 2
                'translate3d(' + (win.width/2+10) + 'px, 0, 0)', // transforms for panel 3
                'translate3d(0, -' + (win.height/2+10) + 'px, 0)' // transforms for panel 4
            ],
            'prev' : [
                'translate3d(' + (win.width/2+10) + 'px, 0, 0)',
                'translate3d(0, ' + (win.height/2+10) + 'px, 0)',
                'translate3d(0, -' + (win.height/2+10) + 'px, 0)',
                'translate3d(-' + (win.width/2+10) + 'px, 0, 0)'
            ]
        },
        'effect-2' : {
            'next' : [
                'translate3d(-' + (win.width/2+10) + 'px, 0, 0)',
                'translate3d(' + (win.width/2+10) + 'px, 0, 0)',
                'translate3d(-' + (win.width/2+10) + 'px, 0, 0)',
                'translate3d(' + (win.width/2+10) + 'px, 0, 0)'
            ],
            'prev' : [
                'translate3d(0,-' + (win.height/2+10) + 'px, 0)',
                'translate3d(0,-' + (win.height/2+10) + 'px, 0)',
                'translate3d(0,' + (win.height/2+10) + 'px, 0)',
                'translate3d(0,' + (win.height/2+10) + 'px, 0)'
            ]
        },
        'effect-3' : {
            'next' : [
                'translate3d(0,' + (win.height/2+10) + 'px, 0)',
                'translate3d(0,' + (win.height/2+10) + 'px, 0)',
                'translate3d(0,' + (win.height/2+10) + 'px, 0)',
                'translate3d(0,' + (win.height/2+10) + 'px, 0)'
            ],
            'prev' : [
                'translate3d(0,-' + (win.height/2+10) + 'px, 0)',
                'translate3d(0,-' + (win.height/2+10) + 'px, 0)',
                'translate3d(0,-' + (win.height/2+10) + 'px, 0)',
                'translate3d(0,-' + (win.height/2+10) + 'px, 0)'
            ]
        }
    };
}

Следующее что нужно сделать это для инициализировать события для навигационных стрелок и события для изменения размера окна (мы должны сбросить наши преобразования):

BoxesFx.prototype._initEvents = function() {
    var self = this, navctrls = this.nav.children;
    // previous action
    navctrls[0].addEventListener( 'click', function() { self._navigate('prev') } );
    // next action
    navctrls[1].addEventListener( 'click', function() { self._navigate('next') } );
    // window resize
    window.addEventListener( 'resize', function() { self._resizeHandler(); } );
}

Давайте взглянем на функции навигации:

BoxesFx.prototype._navigate = function( dir ) {
    if( this.isAnimating ) return false;
    this.isAnimating = true;

    var self = this, currentPanel = this.panels[ this.current ];

    if( dir === 'next' ) {
        this.current = this.current < this.panelsCount - 1 ? this.current + 1 : 0; } else { this.current = this.current > 0 ? this.current - 1 : this.panelsCount - 1;
    }

    // next panel to be shown
    var nextPanel = this.panels[ this.current ];
    // add class active to the next panel to trigger its animation
    classie.add( nextPanel, 'active' );
    // apply the transforms to the current panel
    this._applyTransforms( currentPanel, dir );

    // let´s track the number of transitions ended per panel
    var cntTransTotal = 0,

        // transition end event function
        onEndTransitionFn = function( ev ) {
            if( ev && !classie.has( ev.target, 'bg-img' ) ) return false;

            // return if not all panel transitions ended
            ++cntTransTotal;
            if( cntTransTotal < self.panelsCount ) return false;

            if( support.transitions ) {
                this.removeEventListener( transEndEventName, onEndTransitionFn );
            }

            // remove current class from current panel and add it to the next one
            classie.remove( currentPanel, 'current' );
            classie.add( nextPanel, 'current' );
            // reset transforms for the currentPanel
            self._resetTransforms( currentPanel );
            // remove class active
            classie.remove( nextPanel, 'active' );
            self.isAnimating = false;
        };

    if( support.transitions ) {
        currentPanel.addEventListener( transEndEventName, onEndTransitionFn );
    }
    else {
        onEndTransitionFn();
    }
}

BoxesFx.prototype._applyTransforms = function( panel, dir ) {
    var self = this;
    [].slice.call( panel.querySelectorAll( 'div.bg-img' ) ).forEach( function( tile, pos ) {
        tile.style.WebkitTransform = self.transforms[self.effect][dir][pos];
        tile.style.transform = self.transforms[self.effect][dir][pos];
    } );
}

BoxesFx.prototype._resetTransforms = function( panel ) {
    [].slice.call( panel.querySelectorAll( 'div.bg-img' ) ).forEach( function( tile ) {
        tile.style.WebkitTransform = 'none';
        tile.style.transform = 'none';
    } );
}

Я надеюсь вам понравилось и этот урок будет вам полезный!

Источник урока:

http://tympanus.net/codrops/2014/06/11/how-to-create-a-tiled-background-slideshow

Урок, который показывает, как воссоздать четыре мозаичных слайд-шоу эффекта которые я видел на веб-сайте Serge Thoroval. Будем использовать 3D-преобразования, переходы и анимации, цель заключается в реализации smooth-эффекта и добавлении нескольких его вариантов. Сегодня мы хотели бы показать вам, как воссоздать фоновый слайдер изображений, который мы видели на потрясающем сайте Serge Thoroval’s Atelier, который был создан и спроектирован талантливой Жан-Кристоф Сюзанной и Джонатаном Да Коста. Если вы еще не видели веб-сайте, вы должны обязательно пойти и посмотреть; он полон интересных и творческих эффектов. Слайд-шоу, что мы воссоздадим сегодня, состоит из четырех плиток, которые перемещаются по отдельности, что делает раскол изображения при масштабировании до новое изображение. Все это&hellip;

Обзор

Проголосуйте за урок

Оценка

Итог : Уважаемые читатели! Если вам понравилась статья не поленитесь проголосовать и оставить комментарий, ведь так я смогу понять полезность уроков и статей, и улучшить их качество в будущем. Заранее спасибо!

Рейтинг: 4.2 ( 3 голосов )
100

Оставить комментарий

Ваш email не будет опубликован.

*