Многослойная страница с эффектом раскрытия
В этом уроке мы создадим многослойную страницу, различные элементы которой будут раскрываться эффектным образом.
Сегодня мы продемонстрируем процесс создания простого, но в тоже модного эффекта. Результат может напомнить Nation или Keep Portland Weird, где несколько слоёв перекрывают всю страницу после чего подгружается новый контент. Мы будем варганить что-то подобное: сфокусируемся на анимации, а вот загрузки контента касаться не будем.
Разметка
Наш пример будет развёрнут на всю ширину и высоту экрана. По бокам и в углах поместим кнопки при нажатии на которые будет запускаться анимация. Идея в том чтобы перекрыть контент анимированным слоем, а в это время подставить другую информацию. Мы будем иметь дело с статичным контентом. Вы же можете добавить динамики — реализовать динамическую подгрузку контента.
Основная часть страницы будет выглядеть вот так:
<body> <main class="container"> <div class="pages"> <div class="page page--current"> <!-- intro page content --> </div><!-- /page --> <div class="page"> <!-- some other page --> </div> </div><!-- /pages --> <nav class="pagenav"> <!-- buttons that will trigger the overlay animations --> </nav> </main> </body>
Структура перекрывающего слоя будет встраиваться через JavaScript. Он будет располагаться поверх всего остального контента. В зависимости от направления мы будем задавать данному элементу соответствующие классы. В самом перекрытии будет расположено определённое количество слоёв с фоном и другими персонализированными настройками.
Примерный вид перекрывающего слоя:
<div class="revealer revealer--right"> <div class="revealer__layer"></div> <div class="revealer__layer"></div> <div class="revealer__layer"></div> </div>
Каждому слою будет присвоен свой цвет фона. Чтобы переход был эффектнее каждый слой будем анимировать отдельно. В нашем скрипте поместим родительский контейнер за предел видимости страницы. Анимация будет реализована через CSS за счёт присвоения тех или иных классов.
CSS
Для начала давайте напишем общие стили для наших страницы (браузерные префиксы удалены):
html, body { min-height: 100vh; overflow-x: hidden; } .js .container { position: relative; height: 100vh; overflow: hidden; } .js .pages { position: relative; overflow: hidden; width: 100vw; height: 100vh; z-index: 0; } .page { padding: 6.5em; background: #66c6ff; display: flex; flex-direction: column; } .js .page { position: absolute; top: 0; left: 0; width: 100%; height: 100%; visibility: hidden; z-index: 1; } .js .page--current { visibility: visible; position: relative; }
По нашему замыслу главный элемент будет занимать всё пространство экрана. С помощью JS (Modernizr), все “страницы” будут скрыты, а пользователю отобразится главный экран. Для того чтобы наша страница работала и без JavaScript-а, добавим “условные” стили.
Давайте взглянем как будет выглядеть стиль для класса revealer. Поместим данный элемент поверх всего остального контента и зададим фиксированную позицию:
.revealer { width: 100vw; height: 100vh; position: fixed; z-index: 1000; pointer-events: none; }
В зависимости от выбранного направления, будут выставляться позиции для анимации. Таким образом нам не нужно будет определять отдельную анимацию для каждого слоя:
.revealer--cornertopleft, .revealer--cornertopright, .revealer--cornerbottomleft, .revealer--cornerbottomright { top: 50%; left: 50%; } .revealer--top, .revealer--bottom { left: 0; } .revealer--right, .revealer--left { top: 50%; left: 50%; } .revealer--top { bottom: 100%; } .revealer--bottom { top: 100%; }
Слою будет присвоен свой цвет фона, который для разных эффектов определяется динамически:
.revealer__layer { position: absolute; width: 100%; height: 100%; top: 0; left: 0; background: #ddd; }
Давайте в качестве примера рассмотрим один из эффектов. В анимации будут участвовать три слоя к каждому из которых будет присвоена анимационная функция. Какой именно эффект будет применён запишем с помощью класса anim–effect.
Так же нам необходимо определить небольшую задержку, чтобы все три анимации не сработали одновременно:
.anim--effect-3 .page:nth-child(2) { background: #F3A3D3; } .anim--effect-3 .revealer--animate .revealer__layer { animation: anim-effect-3-1 1.5s cubic-bezier(0.550, 0.055, 0.675, 0.190) forwards; } .anim--effect-3 .revealer--animate .revealer__layer:nth-child(2) { animation-name: anim-effect-3-2; } .anim--effect-3 .revealer--animate .revealer__layer:nth-child(3) { animation-name: anim-effect-3-3; } @keyframes anim-effect-3-1 { 0% { transform: translate3d(0, 0, 0); } 25%, 75% { transform: translate3d(0, -100%, 0); animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); } 100% { transform: translate3d(0, -200%, 0); } } @keyframes anim-effect-3-2 { 0%, 12.5% { transform: translate3d(0, 0, 0); } 37.5%, 62.5% { transform: translate3d(0, -100%, 0); animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); } 87.5%, 100% { transform: translate3d(0, -200%, 0); } } @keyframes anim-effect-3-3 { 0%, 25% { transform: translate3d(0, 0, 0); animation-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1.000); } 75%, 100% { transform: translate3d(0, -200%, 0); } }
Согласно данному коду первый слой будет двигаться до тех пор пока не дойдёт до середины. Далее он замедлится пока не окажется на 75% выше видимой части экрана. После этого мы покажем новый контент. То же самое будет происходить и с двумя оставшимися слоями, за исключением последнего, которому мы не задаём никакой паузы.
JavaScript
Мы создали небольшой плагин, который будет работать в зависимости от заданных настроек:
Revealer.prototype.options = { // общее количество слоёв для анимации (минимум 1) nmbLayers : 1, // цвет слоя bgcolor : '#fff', // класс эффекта effect : 'anim--effect-1', // коллбэк onStart : function(direction) { return false; }, // коллбэк onEnd : function(direction) { return false; } };
Функция отвечающая за добавление слоёв на страницу:
Revealer.prototype._addLayers = function() { this.revealerWrapper = document.createElement('div'); this.revealerWrapper.className = 'revealer'; classie.add(bodyEl, this.options.effect); var strHTML = ''; for(var i = 0; i < this.options.nmbLayers; ++i) { var bgcolor = typeof this.options.bgcolor === 'string' ? this.options.bgcolor : (this.options.bgcolor instanceof Array && this.options.bgcolor[i] ? this.options.bgcolor[i] : '#fff'); strHTML += ' '; } this.revealerWrapper.innerHTML = strHTML; bodyEl.appendChild(this.revealerWrapper); };
Самой сложной будет следующая функция, где мы будем определять направление анимации согласно выбранной кнопке и типу эффекта.
Revealer.prototype.reveal = function(direction, callbacktime, callback) { // если анимация запищена if( this.isAnimating ) { return false; } this.isAnimating = true; // текущее направление this.direction = direction; // коллбэк onStart this.options.onStart(this.direction); // изначальное положение родительского слоя var widthVal, heightVal, transform; if( direction === 'cornertopleft' || direction === 'cornertopright' || direction === 'cornerbottomleft' || direction === 'cornerbottomright' ) { var pageDiagonal = Math.sqrt(Math.pow(winsize.width, 2) + Math.pow(winsize.height, 2)); widthVal = heightVal = pageDiagonal + 'px'; if( direction === 'cornertopleft' ) { transform = 'translate3d(-50%,-50%,0) rotate3d(0,0,1,135deg) translate3d(0,' + pageDiagonal + 'px,0)'; } else if( direction === 'cornertopright' ) { transform = 'translate3d(-50%,-50%,0) rotate3d(0,0,1,-135deg) translate3d(0,' + pageDiagonal + 'px,0)'; } else if( direction === 'cornerbottomleft' ) { transform = 'translate3d(-50%,-50%,0) rotate3d(0,0,1,45deg) translate3d(0,' + pageDiagonal + 'px,0)'; } else if( direction === 'cornerbottomright' ) { transform = 'translate3d(-50%,-50%,0) rotate3d(0,0,1,-45deg) translate3d(0,' + pageDiagonal + 'px,0)'; } } else if( direction === 'left' || direction === 'right' ) { widthVal = '100vh' heightVal = '100vw'; transform = 'translate3d(-50%,-50%,0) rotate3d(0,0,1,' + (direction === 'left' ? 90 : -90) + 'deg) translate3d(0,100%,0)'; } else if( direction === 'top' || direction === 'bottom' ) { widthVal = '100vw'; heightVal = '100vh'; transform = direction === 'top' ? 'rotate3d(0,0,1,180deg)' : 'none'; } this.revealerWrapper.style.width = widthVal; this.revealerWrapper.style.height = heightVal; this.revealerWrapper.style.WebkitTransform = this.revealerWrapper.style.transform = transform; this.revealerWrapper.style.opacity = 1; // присваиваем направление и класс анимации родительскому элементу classie.add(this.revealerWrapper, 'revealer--' + direction || 'revealer--right'); classie.add(this.revealerWrapper, 'revealer--animate'); // завершение анимации для всех слоёв var self = this, layerscomplete = 0; this.layers.forEach(function(layer) { onEndAnimation(layer, function() { ++layerscomplete; if( layerscomplete === self.options.nmbLayers ) { classie.remove(self.revealerWrapper, 'revealer--' + direction || 'revealer--right'); classie.remove(self.revealerWrapper, 'revealer--animate'); self.revealerWrapper.style.opacity = 0; self.isAnimating = false; // коллюбэк self.options.onEnd(self.direction); } }); }); if( typeof callback === 'function') { if( this.callbacktimeout ) { clearTimeout(this.callbacktimeout); } this.callbacktimeout = setTimeout(callback, callbacktime); } };
Надеемся, данная наработка будет вам полезна.
Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: http://tympanus.net/codrops/2016/06/01/multi-layer-page-reveal-effects/
Перевел: Станислав Протасевич
Урок создан: 7 Июня 2016
Просмотров: 11853
Правила перепечатки
5 последних уроков рубрики "CSS"
-
Забавные эффекты для букв
Небольшой эффект с интерактивной анимацией букв.
-
Реализация забавных подсказок
Небольшой концепт забавных подсказок, которые реализованы на SVG и anime.js. Помимо особого стиля в примере реализована анимация и трансформация графических объектов.
-
Анимированные буквы
Эксперимент: анимированные SVG буквы на базе библиотеки anime.js.
-
Солнцезащитные очки от первого лица
Прикольный эксперимент веб страницы отображение которой осуществляется “от первого лица” через солнцезащитные очки.
-
Раскрывающаяся навигация
Экспериментальный скрипт раскрывающейся навигации.