Создание кастомной навигации

Для начала необходимо подключить библиотеку fullPage.js и её CSS. Обычно это делается через CDN или локальные файлы:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullPage.js/4.1.12/fullpage.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullPage.js/4.1.12/fullpage.min.js"></script>

HTML-структура для fullPage.js должна содержать контейнер с классом #fullpage, внутри которого располагаются секции:

<div id="fullpage">
    <div class="section" data-anchor="first">Секция 1</div>
    <div class="section" data-anchor="second">Секция 2</div>
    <div class="section" data-anchor="third">Секция 3</div>
</div>

Ключевой момент: каждая секция может иметь атрибут data-anchor, который будет использоваться для навигации по ссылкам.

Инициализация fullPage.js

Создание экземпляра библиотеки происходит через new fullpage():

const fullPageInstance = new fullpage('#fullpage', {
    anchors: ['first', 'second', 'third'],
    navigation: false, // отключаем стандартную навигацию
    controlArrows: true,
    scrollingSpeed: 700,
    loopTop: false,
    loopBottom: false
});

Опция navigation: false отключает стандартные точки навигации, чтобы можно было создать кастомный интерфейс.

Создание кастомного меню

Кастомное меню строится как обычный список или набор кнопок. Пример HTML:

<nav id="customNav">
    <ul>
        <li><a href="#first" data-menuanchor="first">Секция 1</a></li>
        <li><a href="#second" data-menuanchor="second">Секция 2</a></li>
        <li><a href="#third" data-menuanchor="third">Секция 3</a></li>
    </ul>
</nav>

Каждая ссылка содержит href на якорь и атрибут data-menuanchor, совпадающий с anchor секции.

Привязка навигации к fullPage.js

Чтобы ссылки работали с fullPage.js, используется метод moveTo:

document.querySelectorAll('#customNav a').forEach(link => {
    link.addEventListener('click', function(e) {
        e.preventDefault();
        const target = this.getAttribute('data-menuanchor');
        fullPageInstance.moveTo(target);
    });
});

Метод moveTo принимает либо индекс секции, либо её anchor.

Подсветка активной секции

Чтобы визуально показывать, какая секция активна, необходимо отслеживать событие afterLoad:

fullPageInstance.on('afterLoad', function(origin, destination, direction) {
    document.querySelectorAll('#customNav a').forEach(link => link.classList.remove('active'));
    const activeLink = document.querySelector(`#customNav a[data-menuanchor="${destination.anchor}"]`);
    if(activeLink) activeLink.classList.add('active');
});

Класс active можно стилизовать в CSS:

#customNav a.active {
    color: #ff0000;
    font-weight: bold;
}

Добавление кнопок “Вверх” и “Вниз”

Кнопки навигации по секциям создаются через обычные элементы и связываются с методами moveSectionUp и moveSectionDown:

<div id="sectionControls">
    <button id="upBtn">Вверх</button>
    <button id="downBtn">Вниз</button>
</div>
document.getElementById('upBtn').addEventListener('click', () => {
    fullPageInstance.moveSectionUp();
});

document.getElementById('downBtn').addEventListener('click', () => {
    fullPageInstance.moveSectionDown();
});

Прокрутка по событиям клавиатуры и колесу мыши

Для расширенной кастомизации можно добавить обработку клавиш или жестов:

document.addEventListener('keydown', e => {
    switch(e.key) {
        case 'ArrowUp':
            fullPageInstance.moveSectionUp();
            break;
        case 'ArrowDown':
            fullPageInstance.moveSectionDown();
            break;
    }
});

Такое решение позволяет полностью контролировать навигацию и синхронизировать её с визуальными элементами интерфейса.

Анимация при переходе между секциями

fullPage.js позволяет использовать callback функции для запуска анимаций:

fullPageInstance.on('onLeave', function(origin, destination, direction){
    const leavingSection = origin.item;
    leavingSection.classList.add('fade-out');

    const enteringSection = destination.item;
    enteringSection.classList.add('fade-in');
});

CSS-анимации могут выглядеть так:

.fade-out {
    animation: fadeOut 0.7s forwards;
}

.fade-in {
    animation: fadeIn 0.7s forwards;
}

@keyframes fadeOut {
    from {opacity: 1;}
    to {opacity: 0;}
}

@keyframes fadeIn {
    from {opacity: 0;}
    to {opacity: 1;}
}

Динамическое обновление меню

Для сайтов с динамическими секциями можно обновлять кастомное меню на лету:

function addSection(name) {
    const section = document.createElement('div');
    section.classList.add('section');
    section.setAttribute('data-anchor', name);
    section.innerHTML = `Секция ${name}`;
    document.getElementById('fullpage').appendChild(section);

    fullPageInstance.addSection(section);

    const menuItem = document.createElement('li');
    menuItem.innerHTML = `<a href="#${name}" data-menuanchor="${name}">Секция ${name}</a>`;
    document.querySelector('#customNav ul').appendChild(menuItem);

    menuItem.querySelector('a').addEventListener('click', function(e){
        e.preventDefault();
        fullPageInstance.moveTo(name);
    });
}

Такой подход позволяет поддерживать меню синхронизированным с любыми изменениями DOM.

Использование кастомной пагинации

Кроме меню, можно создать собственную пагинацию с индикаторами прогресса:

<div id="progressNav">
    <span class="dot" data-index="1"></span>
    <span class="dot" data-index="2"></span>
    <span class="dot" data-index="3"></span>
</div>
const dots = document.querySelectorAll('#progressNav .dot');
dots.forEach(dot => {
    dot.addEventListener('click', () => {
        const index = parseInt(dot.getAttribute('data-index'));
        fullPageInstance.moveTo(index);
    });
});

fullPageInstance.on('afterLoad', function(origin, destination) {
    dots.forEach(d => d.classList.remove('active'));
    dots[destination.index].classList.add('active');
});

Такой механизм позволяет реализовать любые визуальные решения, от круговой индикаторной линии до кастомного прогресс-бара.


Этот набор приёмов полностью покрывает создание кастомной навигации в fullPage.js: от простых ссылок до динамических меню и сложной анимации, сохраняя синхронизацию с состоянием секций.