• Страница 1 из 1
  • 1
Многоуровневые эффекты раскрытия страницы
Webmaster32
Четверг, 24 Мая 2018, 01:56 | Сообщение 1
Оффлайн
Vip
Сообщений:431
Награды: 6
Сегодня мы хотели бы показать вам, как создать простой и современный эффект перехода страницы. Возможно, вы заметили некоторые из замечательных эффектов, которые можно увидеть на сайтах, таких как Nation или Keep Portland Weird, где два или более слоев оверлеев анимируются по всей странице, чтобы показать какой-то новый контент. Давайте посмотрим, как мы можем сделать что-то подобное. Мы сосредоточимся только на части анимации, а не на загрузке контента. Для эффектов мы будем использовать CSS Animations.
DEMO



Внимание: мы будем использовать CSS-анимации и единицы просмотра, которые поддерживаются только в современных браузерах.

Разметка

Для нашей простой демонстрации мы создадим макет ширины и высоты с несколькими стрелками, которые будут запускать анимацию оверлей. Идея состоит в том, чтобы показать страницу и посередине оверлейной анимации, перейти на другую страницу. Пока мы будем работать со статическим контентом, вы можете подключить к нему динамическое решение, которое будет получать данные на лету.

Наша разметка выглядит следующим образом:
Код
<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

Во-первых, давайте рассмотрим некоторые общие стили для нашего тела, контейнера и страниц (префикс поставщика опущен):
Код
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 {
    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% в то время как поверх видимого экрана. Затем мы переместим его в противоположном направлении, чтобы открыть новый контент. То же самое происходит и для двух других слоев, просто здесь мы начинаем их с разных ключевых кадров, уменьшая «паузу». Последний слой вообще не имеет паузы, он просто переходит на другую сторону, начиная с 25%.

JavaScript

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

Код
Revealer.prototype.options = {
    // total number of revealing layers (min is 1)
    nmbLayers : 1,
    // bg color for the revealing layers
    bgcolor : '#fff',
    // effect classname
    effect : 'anim--effect-1',
    // callback
    onStart : function(direction) { return false; },
    // callback
    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);
};


Самая важная функция устанавливает начальное позиционирование нашего элемента раскрытия и добавляет классы управления для запуска анимации и выбранного эффекта.

В зависимости от того, в каком направлении мы выбираем, мы должны убедиться, что элемент раскрытия получает правильные преобразования. Помните, что мы просто вращаем и позиционируем открыватель таким образом, чтобы верхняя сторона всегда была обращена к экрану, чтобы слои всегда двигались вверх. Для угловых случаев нам необходимо убедиться, что ширина и высота раскрывателя правильно установлены на диагонали страницы. Для левого и правого корпуса нам нужно убедиться, что высота раскрывающего устройства - это ширина экрана, потому что мы поворачиваем его на 90 градусов.

Код
Revealer.prototype.reveal = function(direction, callbacktime, callback) {
    // if animating return
    if( this.isAnimating ) {
  return false;
    }
    this.isAnimating = true;
    // current direction
    this.direction = direction;
    // onStart callback
    this.options.onStart(this.direction);

    // set the initial position for the layers´ parent
    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;

    // add direction and animate classes to parent
    classie.add(this.revealerWrapper, 'revealer--' + direction || 'revealer--right');
    classie.add(this.revealerWrapper, 'revealer--animate');

    // track the end of the animation for all layers
    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;

    // callback
    self.options.onEnd(self.direction);
   }
  });
    });
  
    // reveal fn callback
    if( typeof callback === 'function') {
  if( this.callbacktimeout ) {
   clearTimeout(this.callbacktimeout);
  }
  this.callbacktimeout = setTimeout(callback, callbacktime);
    }
};


И это все люди, мы надеемся, что вам понравился этот маленький эффект и вдохновение.
Прикрепления: 5194369.jpg (46.9 Kb) · PageRevealEffec.zip (39.3 Kb)
Страна: (CZ)
  • Страница 1 из 1
  • 1
Поиск: