Ефект перегортання сторінок на jQuery

18

Від автора: даний урок присвячений створенню анімаційного ефекту перелистыванию сторінок сайту за допомогою плагінів jQuery. Ідея полягає в тому, щоб перегортати вміст, як книгу, і переходити до сторінок за допомогою з’являється зліва бічного меню.

Ми отримали безліч листів про те, як за допомогою плагіна BookBlock, створювати ефекти перегортання сторінок, але вже в повноекранному режимі. Тому було вирішено створити розмітку, застосувати до неї BookBlock і додати бічне меню. Ми покажемо вам, як застосувати до своїх цілей BookBlock і використовувати для навігації по вмісту деякі доступні опції.

Ідея полягає в тому, щоб переходити по сторінках за допомогою стрілок або «гортаючи» їх, і змушувати меню з’являтися по клацанню на кнопку. Бічне меню буде містити посилання на різні сторінки, наприклад, на зміст. Таким чином, ми отримаємо з вами ефект перегортання сторінок на нашому сайті.

Ми також застосуємо jScrollPane від Кевіна Лаку (Kevin Luck) для додавання користувача смуги прокручування вмісту там, де це потрібно.

Ефект перегортання сторінок на jQueryЕфект перегортання сторінок на jQuery

Будь ласка, зверніть увагу: 3D-transforms CSS будуть працювати тільки в сучасних браузерах, які підтримують ці властивості.

Демоверсія містить витяги з сміховинної книги «Смішна медицина» А. Д. Крэбтри («The Funny Side of Physic» by A. D. Crabtree) з сайту Project Gutenberg.

Для отримання ефекту перегортання сторінок, ми скористаємося наступними плагінами jQuery:

BookBlock від Педро Ботельо (Pedro Botelho)

Користувальницький jQuery++ від Битови (Bitovi)

jScrollPane від Кевіна Лаку (Kevin Luck)

Плагін jQuery Mouse Wheel від Брендона Аарона (Brandon Aaron)

Користувальницький Modernizr

Отже, давайте почнемо створення ефекту перегортання сторінок!

Розмітка

Давайте зробимо основний контейнер для всіх елементів. Всередину додамо розділ для бічного меню, якому призначимо клас «menu-panel», і обгортку для BookBlock’а з класом «bb-custom-wrapper». BookBlock буде містити обгортку (до якої ми застосуємо плагін) і потрібну плагіну структуру. Всередину кожного елемента ми додамо обгортку вмісту з розділом, необхідним для функціональності користувача прокручування:

Table of Contents

Self-destruction



Table of Contents

Елементи меню будуть вказувати на відповідні сторінки BookBlock’а (bb-item). Також додамо навігаційні стрілки-покажчики і кнопку перемикання відкриття і закриття меню.

Давайте перейдемо до стилів.

CSS

Зауважте, що тут ми не будемо використовувати ніяких спеціальних префіксів, але ви відшукаєте їх у файлах.

Тут ми не обговорюємо стиль плагіна BookBlock (стилі можна знайти в bookblock.css), замість цього зосередимося на інших важливих для розмітки стилях, і пару штук з них модифікуємо.

Почнемо з імпортування шрифту Lato з веб-шрифтів Google:

@import url(http://fonts.googleapis.com/css?family=Lato:300,400,700);

Html-елемент повинен бути заввишки в 100%, оскільки нам необхідно розтягнути висоту внутрішніх елементів до висоти вікна:

html {
height: 100%;
}

Для зміни розміру блоку застосуємо border-box, що дозволить нам визначити процентне співвідношення висоти і ширини елементів при використанні відступів, і не хвилюватися про те, що елементи будуть занадто великими:

*,
*:after,
*:before {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
padding: 0;
margin: 0;
}

(Ми «по-звірячому» скидаємо відступи полів всіх елементів; вам цього робити не потрібно, замість цього можна просто впорядкувати відповідні елементи.)

Давайте визначимо шрифт основного тексту body і встановимо його висоту на 100%. Пам’ятайте, що нам потрібно визначити її дочірніх записів, які будуть абсолютними і теж заввишки 100%:

body {
font-family: ‘Lato’, Calibri, Arial, sans-serif;
font-weight: 400;
font-size: 100%;
color: #333;
height: 100%;
}

Ми користуємося Modernizr’ом і додали до html-елемента клас «no-js». При активованому JavaScript’е Modernizr замінить цей клас на «js». Це дасть нам можливість призначити елементів певні властивості CSS, що при вимкненому JavaScript’е не вимагається. Наша розмітка шириною і висотою в 100% має сенс, тільки якщо у нас активний JS, і тоді нам потрібно, щоб переповнення overflow у body було приховано hidden:

.js body {
overflow: hidden;
}

Давайте визначимо декілька стилів посилань:

a {
color: #555;
text-decoration: none;
}
a:hover {
color: #000;
}

Нам потрібно, щоб основний контейнер займав всю ширину і висоту вікна. Бічне меню буде розташоване поза його шляхом установки негативного лівого значення (його власної ширини). Ідея полягає в тому, щоб анімувати весь контейнер при клацанні для відкриття меню. Воно зісковзне вправо, відкриваючи переповнене бічне меню.

Так, давайте встановимо ширину і висоту основного контейнера на 100% і додамо до контейнера перехід:

.container,
.bb-custom-wrapper,
.bb-bookblock {
width: 100%;
height: 100%;
}
.container {
position: relative;
left: 0px;
transition: left 0.3 s ease-in-out;
}

При натисканні на кнопку меню ми додамо до контейнера інший клас, який встановить значення left на 240 px (ширина бічного меню):

.slideRight {
left: 240px;
}

При деактивированном JavaScript’е ми не зможемо цього зробити, тому давайте додамо замість цього відступ зліва:

.no-js .container {
padding-left: 240px;
}

Нам потрібно, щоб за замовчуванням бічне меню було зафіксовано по лівій стороні:

.menu-panel {
background: #f1103a;
width: 240px;
height: 100%;
position: fixed;
z-index: 1000;
top: 0;
left: 0;
text-shadow: 0 1px 1px rgba(0,0,0,0.1);
}

При активному JS ми встановимо position на absolute, а left на -240 px:

.js .menu-panel {
position: absolute;
left: -240px;
}

Давайте призначимо стилі елементів меню:

.menu-panel h3 {
font-size: 1.8 em;
padding: 20px;
font-weight: 300;
color: #fff;
box-shadow: inset 0 -1px 0 rgba(0,0,0,0.05);
}
.menu-toc {
list-style: none;
}
.menu-toc li a {
display: block;
color: #fff;
font-size: 1.1 em;
line-height: 3.5;
padding: 0 20px;
cursor: pointer;
background: #f1103a;
border-bottom: 1px solid #dd1338;
}
.menu-toc li a:hover,
.menu-toc li.menu-toc-current a{
background: #dd1338;
}

Навігація буде розташовуватися абсолютно поверх усього:

.bb-custom-wrapper nav {
top: 20px;
left: 60px;
position: absolute;
z-index: 1000;
}

Посилання на стрілки-покажчики і кнопку меню теж будуть позиціонуватися абсолютно, і ми скруглим їх, встановивши border-radius на 50%:

.bb-custom-wrapper nav span,
.menu-button {
position: absolute;
width: 32px;
height: 32px;
top: 0;
left: 0;
background: #f1103a;
border-radius: 50%;
color: #fff;
line-height: 30px;
text-align: center;
speak: none;
font-weight: bold;
cursor: pointer;
}
.bb-custom-wrapper nav span:last-child {
left: 40px;
}
.bb-custom-wrapper nav span:hover,
.menu-button:hover {
background: #000;
}

Кнопка меню буде розташована в лівому верхньому кутку, і її текст ми приховаємо:

.menu-button {
z-index: 1000;
left: 20px;
top: 20px;
text-indent: -9000px;
}

Давайте створимо маленьку іконку меню, скориставшись псевдоэлементом з подвійною тінню блоку стосовно верхньої і нижньої ліній:

.menu-button:after {
position: absolute;
content: «;
width: 50%;
height: 2px;
background: #fff;
top: 50%;
margin-top: -1px;
left: 25%;
box-shadow: 0 -4px #fff, 0 4px #fff;
}

У разі, коли JS не активований, нам ці елементи виявляться не потрібні, тому просто сховаємо їх:

.no-js .bb-custom-wrapper nav span,
.no-js .menu-button {
display: none;
}

Перейдемо до внутрішніх частин елементів BookBlock’а. Розділ контенту повинен бути absolute, а також встановимо переповнення overflow на hidden. Це важливо, тому що тут нам потрібно застосувати свою модифіковану користувача прокручування, і ми зробимо це, тільки коли сторінка перегорнута. Якщо не встановити overflow на hidden, то ми побачили б переповнення вмісту. І знову, це має сенс тільки при активному JS, тому додамо клас «js»:

.js .content {
position: absolute;
top: 60px;
left: 0;
bottom: 50px;
width: 100%;
overflow: hidden;
}

Div scroller буде розростатися разом з контентом, тому давайте додамо сюди кілька відступів:

.scroller {
padding: 10px 5% 10px 5%;
}

Застосування процентного співвідношення в якості бокового відступу змусить розмітку гнучко підлаштовуватися до розміру екрана.

Давайте будемо приховувати гострі краї при прокручуванні, додавши псевдоелементи з градієнтом від білого кольору до прозорого до верху і низу div а content:

.js .content:before,
.js .content:after {
content: «;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 20px;
z-index: 100;
pointer-events: none;
background:
linear-gradient(
to bottom,
rgba(255,255,255,1) 0%,
rgba(255,255,255,0) 100%
);
}
.js .content:after {
top: auto;
bottom: 0;
background:
linear-gradient(
to top,
rgba(255,255,255,1) 0%,
rgba(255,255,255,0) 100%
);
}

Так текст буде виглядати трохи вицвілим. Додамо стилі до елементів тексту:

.content h2 {
font-weight: 300;
font-size: 4em;
padding: 0 0 10px;
color: #333;
margin: 0 1% 40px;
text-align: left;
box-shadow: 0 10px 0 rgba(0,0,0,0.02);
text-shadow: 0 2px 0 #fff;
}
.no-js .content h2 {
padding: 40px 1% 20px;
}
.content p {
font-size: 1.2 em;
line-height: 1.6;
font-weight: 300;
padding: 5px 8%;
text-align: justify;
}

Нарешті давайте додамо медиазапросы. При деактивированном JavaScript’е нам більше не потрібно показувати меню 800 px. Простий приклад того, як можна при певних умовах контролювати ці елементи.

Останній медиазапрос трохи змінить розмір шрифту під менші пристрої. У таких випадках дуже полегшує застосування em’ів.

@media screen and (max-width: 800px){
.no-js .menu-panel {
display: none;
}
.no-js .container {
padding: 0;
}
}
@media screen and (max-width: 400px){
.menu-panel,
.content {
font-size: 75%;
}
}

Ось і всі стилі!

JavaScript

Почнемо з кешування деяких елементів і ініціалізації плагіна BookBlock. Нам потрібно дещо встановити після перегортання кожної сторінки, в основному вказівник поточного елемента і поведінку jScrollPane’а. Це визначено в зворотному виклик onEndFlip, що передається BookBlock’у.

var $container = $( ‘#container’ ),
// елемент, до якого ми застосуємо плагін BookBlock
$bookBlock = $( ‘#bb-bookblock’ ),
// елементи BookBlock (bb-item)
$items = $bookBlock.children(),
// покажчик поточного елемента
current = 0,
// ініціалізувати BookBlock
bb = $( ‘#bb-bookblock’ ).bookblock( {
speed : 800,
perspective : 2000,
shadowSides : 0.8,
shadowFlip : 0.4,
// після кожного перегортання…
onEndFlip : function(old, page, isLimit) {
// оновіть поточне значення
current = page;
// оновіть вибраний елемент змісту (TOC)
updateTOC();
// покажіть і/або приховайте стрілки-покажчики навігації
updateNavigation( isLimit );
// ініціалізувати jScrollPane на div контенту для нового елемента
setJSP( ‘init’ );
// ліквідуйте jScrollPane на div контенту для старого елемента
setJSP( ‘destroy’, old );
}
} ),
// стрілки-покажчики навігації
$navNext = $( ‘#bb-nav-next’ ),
$navPrev = $( ‘#bb-nav-prev’ ).hide(),
// зміст елементів
$menuItems = $container.find( ‘ul.menu-toc > li’ ),
// кнопка для відкривання TOC
$tblcontents = $( ‘#tblcontents’ ),
transEndEventNames = {
‘WebkitTransition’: ‘webkitTransitionEnd’,
‘MozTransition’: ‘transitionend’,
‘OTransition’: ‘oTransitionEnd’,
‘msTransition’: ‘MSTransitionEnd’,
‘transition’: ‘transitionend’
},
// назви події переходу
transEndEventName = transEndEventNames[Modernizr.prefixed(‘transition’)],
// перевірити, чи підтримуються переходи
supportTransitions = Modernizr.csstransitions;

Спочатку прив’яжемо події до деяких раніше инициализированным елементів. Крім того, нам потрібно ініціалізувати jScrollPane для першого (поточного) елемента.

function init() {
// ініціалізувати jScrollPane на div контенту першого елемента
setJSP( ‘init’ );
initEvents();
}

Так як нам згодом доведеться ініціалізувати, реинициализировать і ліквідувати jScrollPane, давайте визначимо для цього функцію:

function setJSP( action, idx ) {
var idx = idx === undefined ? current : idx,
$content = $items.eq( idx ).children( ‘div.content’ ),
apiJSP = $content.data( ‘jsp’ );
if( action === ‘init’ && apiJSP === undefined ) {
$content.jScrollPane({verticalGutter : 0, hideFocus : true });
}
else if( action === ‘reinit’ && apiJSP !== undefined ) {
apiJSP.reinitialise();
}
else if( action === ‘destroy’ && apiJSP !== undefined ) {
apiJSP.destroy();
}
}

Нам знадобиться прив’язати кілька подій:

Ми викличемо методи BookBlock’а next() і prev() при натисканні стрілки навігації або перегортанні сторінки

TOC буде показуватися/ховатися при натисканні на кнопку $tblcontents (меню)

Ми викличемо метод BookBlock’а jump() при клацанні на елемент

jScrollPane ініціалізується при зміні розміру вікна

Отже, ось ми де:

function initEvents() {
// додайте події навігації
$navNext.on( ‘click’, function() {
bb.next();
return false;
} );
$navPrev.on( ‘click’, function() {
bb.prev();
return false;
} );
// додайте події перегортання
$items.on( {
‘swipeleft’ : function( event ) {
if( $container.data( ‘opened’ ) ) {
return false;
}
bb.next();
return false;
},
‘swiperight’ : function( event ) {
if( $container.data( ‘opened’ ) ) {
return false;
}
bb.prev();
return false;
}
} );
// покажіть TOC
$tblcontents.on( ‘click’, toggleTOC );
// виберіть пункт меню
$menuItems.on( ‘click’, function() {
var $el = $( this ),
idx = $el.index(),
jump = function() {
bb.jump( idx + 1 );
};
current !== idx ? closeTOC( jump ) : closeTOC();
return false;
} );
// реинициализируйте jScrollPane при зміні розміру вікна
$( window ).on( ‘debouncedresize’, function() {
// реинициализируйте jScrollPane на div вмісту
setJSP( ‘reinit’ );
} );
}

Видимість навігаційних стрілок-вказівників буде залежати від поточної сторінки. Перебуваючи на першій сторінці, ми побачимо тільки наступну стрілку, а будучи на останній – тільки попередню:

function updateNavigation( isLastPage ) {
if( current === 0 ) {
$navNext.show();
$navPrev.hide();
}
else if( isLastPage ) {
$navNext.hide();
$navPrev.show();
}
else {
$navNext.show();
$navPrev.show();
}
}

Відкриваючи поточний контент, потрібно приховати навігаційні стрілки-покажчики, а знову показуємо ми їх лише після закриття текущщего контенту.

Анімувати бічне меню ми будемо з допомогою переходу CSS. Якщо підтримка переходів відсутня, то слід застосувати просту альтернативу show/hide:

function toggleTOC() {
var opened = $container.data( ‘opened’ );
opened ? closeTOC() : openTOC();
}
function openTOC() {
$navNext.hide();
$navPrev.hide();
$container.addClass( ‘slideRight’ ).data( ‘opened’, true );
}
function closeTOC( callback ) {
$navNext.show();
$navPrev.show();
$container.removeClass( ‘slideRight’ ).data( ‘opened’, ‘false’);
if( callback ) {
if( supportTransitions ) {
$container.on( transEndEventName, function() {
$( this ).off( transEndEventName );
callback.call();
} );
}
else {
callback.call();
}
}
}

Уффф! Ефект перегортання сторінок на jQuery Ось так ми і створили з вами на сайті, ефект перегортання сторінок! Сподіваюся, вам сподобався і виявився корисний цей підручник!