Округла анімована навігація

20

Від автора: Експериментальна повноекранна навігація, розкривається по формі кола та анімована за допомогою CSS і jQuery.

Нещодавно я тестувала новий додаток Ping для iOS. Так от ефект, який відбувався при натисканні на гурток для перемикання сторінки, був настільки класний, що я спробувала створити щось схоже на CSS та jQuery. Результат вийшов досить вражаючим, тому ми вирішили опублікувати приклад такого ефекту на сайті CodyHouse Округла анімована навігація Ця навігація є експериментальною, хоча підтримується усіма основними браузерами – ми використовували Velocity.js – і я впевнена, що ви, друзі, знайдете для цієї навігації креативне застосування!

Округла анімована навігаціяОкругла анімована навігація

Створення структури

Що стосується HTML розмітки, то для даної переходів ми використовували ненумерований список, обгорнутий (з семантичної точки зору) в елемент nav. Елементи з класами .cd-overlay-nav .cd-overlay-content використовуються для створення анімації для кола. Точніше, вони використовуються в якості контейнерів для розташування гуртків відразу за верхній іконкою меню, в той час як, знаходяться всередині них, елементи span є двома кольоровими гуртками, які потім збільшуються в розмірах. Нарешті, елемент з класом .cd-nav-trigger є самою іконкою меню, яка перетворюється на іконку у вигляді хрестика.

Округла анімована навігація

  • The team
  • Our services
  • Our projects
  • Start a project
  • Join In
  • Create an account

Menu

Додавання стилів

Якщо ви подивитеся на CSS, то помітите, що кнопка-перемикач (тригер з класом .cd-nav-trigger) має властивість position:fixed з параметрами для верхнього і правого країв. Щоб ефект працював належним чином, ми повинні відцентрувати контейнери (.cd-overlay-nav .cd-overlay-content) двох анімованих гуртків так, щоб вони знаходилися відразу за перемикачем (тригером). Для цього нам буде потрібно задати для них фіксовану висоту і ширину. Але якщо ви подивитеся на елементи span, які і є анімованими кружками, то ви можете помітити, що для них ми не призначили ні позиціонування, ні розмірів. Оскільки гурток повинен згодом розкритися на весь екран, незалежно від розмірів області перегляду, ми поставили позиціонування (параметри для верхнього і лівого країв) і розміри (ширину) через jQuery.

.cd-nav-trigger {
top: 18px;
right: 5%;
height: 44px;
width: 44px;
z-index: 5;
/* заміна зображення */
overflow: hidden;
text-indent: 100%;
white-space: nowrap;
}
.cd-overlay-nav, .cd-overlay-content {
/* контейнери для 2 основних округлих фонів – ці контейнери використовуються, щоб розташувати округлі фони прямо за іконкою меню */
position: fixed;
top: 18px;
right: 5%;
height: 4px;
width: 4px;
transform: translateX(-20px) translateY(20px);
}
.cd-overlay-nav span, .cd-overlay-content span {
display: inline-block;
position: absolute;
border-radius: 50%;
will-change: transform;
transform: scale(0);
}

Ідея полягала в тому, щоб створити анімацію для іконки меню, а не просо замінити «гамбургер» на «хрестик», тому ми додали елемент (.cd-icon) в наш перемикач. Завдяки цьому ми зможемо створювати (а також створювати анімацію) іконку, використовуючи псевдо-елементи ::before ::after.

.cd-nav-trigger .cd-icon {
/* іконка, створена в CSS */
position: absolute;
left: 50%;
top: 50%;
bottom: auto;
right: auto;
transform: translateX(-50%) translateY(-50%);
display: inline-block;
width: 18px;
height: 3px;
background-color: #ffffff;
z-index: 10;
}
.cd-nav-trigger .cd-icon::before, .cd-nav-trigger .cd-icon:after {
/* верхня і нижня лінії у іконки меню */
position: absolute;
top: 0;
right: 0;
width: 100%;
height: 100%;
background-color: inherit;
transition: transform .3s;
}
.cd-nav-trigger .cd-icon::before {
transform: translateY(-6px) rotate(0deg);
}
.cd-nav-trigger .cd-icon::after {
transform: translateY(6px) rotate(0deg);
}
.cd-nav-trigger.close-nav .cd-icon {
/* користувач натискає на елемент з класом .cd-nav-trigger – іконка змінюється */
background-color: rgba(255, 255, 255, 0);
}
.cd-nav-trigger.close-nav .cd-icon::before, .cd-nav-trigger.close-nav .cd-icon::after {
background-color: white;
}
.cd-nav-trigger.close-nav .cd-icon::before {
transform: translateY(0) rotate(45deg);
}
.cd-nav-trigger.close-nav .cd-icon::after {
transform: translateY(0) rotate(-45deg);
}

Фоновий колір меню/перемикача змінюється, і анімація створюється з невеликою затримкою. І знову, ми використовуємо 2 псевдо-елемента, щоб добитися цього ефекту:

.cd-nav-trigger::before, .cd-nav-trigger::after {
/* 2 округлих кольорових фону для іконки меню */
position: absolute;
top: 0;
left: 0;
border-radius: 50%;
height: 100%;
width: 100%;
transition-property: transform;
}
.cd-nav-trigger::before {
background-color: #091d23;
transform: scale(1);
transition-duration: 0.3 s;
transition-delay: 0.4 s;
}
.cd-nav-trigger::after {
background-color: #ffb441;
transform: scale(0);
transition-duration: 0s;
transition-delay: 0s;
}
.cd-nav-trigger.close-nav::before {
/* користувач натискає на елемент з класом .cd-nav-trigger – 1й округлий фон зникає */
transform: scale(0);
}
.cd-nav-trigger.close-nav::after {
/* користувач натискає на елемент з класом .cd-nav-trigger – 2й округлий фон зникає */
transform: scale(1);
transition-duration: 0.3 s;
transition-delay: 0.4 s;
}

Обробка подій

Перш, ніж ми поглибимося у вивчення jQuery коду, я б хотіла пояснити простими словами, що відбувається: коли користувач клікає/натискає на кнопку з меню, ми активуємо анімацію для елемента span всередині елемента з класом .cd-overlay-nav. Після того як окружність заповнить екран, ми показуємо навігацію. Коли користувач знову клацає/натискає на перемикач для закриття навігації, ми активуємо анімацію для елемента span всередині елемента з класом .cd-overlay-content. В завершенні даної анімації ми приховуємо першу окружність і навігацію, які залишаються на місці, а не видно їх, тому що у них більш низьке значення для властивості z-index. Нарешті, ми зменшуємо прозорість у другій колу (в демо-прикладі вона жовта), показуючи, таким чином, вміст, тобто нібито поміщаючи вміст поверх навігації.

Що стосується jQuery, то тут ми визначаємо позиціонування і розміри елементів span з гуртками (використовуючи функцію initLayer()). Ми призначаємо висоту в два рази більше діагоналі області перегляду і установки для верхнього (і лівого) краю рівні від’ємного значення діагоналі області перегляду елемент span знаходиться всередині елемента з класом .cd-overlay-nav/.cd-overlay-content має властивість position: absolute).

Коли користувач перший раз клацає по елементу з класом .cd-nav-trigger, ми активуємо анімацію для елемента span з класом .cd-overlay-nav, змінюючи значення параметра scale з 0 на 1 (ми використовували Velocity.js для створення анімації):

var overlayNav = $(‘.cd-overlay-nav’),
toggleNav = $(‘.cd-nav-trigger’),
navigation = $(‘.cd-primary-nav’);
toggleNav.on(‘click’, function(){
if(!toggleNav.hasClass(‘close-nav’)) {
//анімоване перетворення іконки в меню іконку у вигляді хрестика
toggleNav.addClass(‘close-nav’);
//створення анімації для шару з навігацією
overlayNav.children(‘span’).velocity({
translateZ: 0,
scaleX: 1,
scaleY: 1,
}, 500, ‘easeInCubic’, function(){
//показуємо навігацію
navigation.addClass(‘fade-in’);
});
}
}

Коли користувач клікає по елементу з класом .cd-nav-trigger для закриття меню, то ми вже активуємо анімацію для зміни значення параметра scale у елемента span з класом .cd-overlay-content:

var overlayNav = $(‘.cd-overlay-nav’),
overlayContent = $(‘.cd-overlay-content’),
toggleNav = $(‘.cd-nav-trigger’),
navigation = $(‘.cd-primary-nav’);
toggleNav.on(‘click’, function(){
if(!toggleNav.hasClass(‘close-nav’)) {
//це означає, що навігацію ще не видно – відкриваємо її і створюємо анімацію для шару з навігацією
//….
} else {
//анімоване перетворення іконки у вигляді хрестика на іконку меню
toggleNav.removeClass(‘close-nav’);
//анімація для шару з содержимымг
overlayContent.children(‘span’).velocity({
translateZ: 0,
scaleX: 1,
scaleY: 1,
}, 500, ‘easeInCubic’, function(){
//приховуємо навігацію
navigation.removeClass(‘fade-in’);
//встановлюємо значення scale для шару з навігацією 0
overlayNav.children(‘span’).velocity({
translateZ: 0,
scaleX: 0,
scaleY: 0,
}, 0);
//зменшуємо прозорість шару з вмістом з класом is-hidden
overlayContent.addClass(‘is-hidden’).one(‘webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend’, function(){
//очікує завершення переходу і виставляємо значення scale для шару з вмістом 0
overlayContent.children(‘span’).velocity({
translateZ: 0,
scaleX: 0,
scaleY: 0,
}, 0, function(){overlayContent.removeClass(‘is-hidden’)});
});
});
}
});