Сабмит при достижении конца

Взаимодействие с пользователем на основе положения прокрутки — одна из ключевых задач при работе с ScrollMagic. Один из распространённых сценариев — выполнение действия при достижении конца страницы или определённого контейнера. Это может быть автоматическая отправка формы (submit), активация кнопки, подгрузка данных или запуск анимации.

ScrollMagic предоставляет гибкий механизм отслеживания позиции через сцены (Scene) и контроллер (Controller), что позволяет точно определить момент, когда пользователь достиг нужной точки.


Базовая настройка ScrollMagic

Перед реализацией логики необходимо инициализировать контроллер:

var controller = new ScrollMagic.Controller();

Контроллер управляет всеми сценами и синхронизирует их с прокруткой страницы.


Определение конца страницы

Конец страницы можно определить разными способами:

  • через высоту документа (document.body.scrollHeight)
  • через позицию последнего элемента
  • через специальный “якорный” элемент (например, #footer)

Наиболее удобный и управляемый способ — использование триггер-элемента.


Создание сцены для отслеживания конца

var scene = new ScrollMagic.Scene({
    triggerElement: "#end",
    triggerHook: 1,
    reverse: false
})
.addTo(controller);

Ключевые параметры:

  • triggerElement — элемент, при достижении которого срабатывает сцена
  • triggerHook: 1 — означает нижнюю границу viewport
  • reverse: false — сцена срабатывает один раз

Сабмит формы при достижении конца

scene.on("enter", function () {
    document.querySelector("#myForm").submit();
});

Событие "enter" срабатывает в момент входа триггер-элемента в область viewport.


Контроль повторных отправок

Даже при reverse: false важно предусмотреть защиту от повторного сабмита:

var submitted = false;

scene.on("enter", function () {
    if (!submitted) {
        submitted = true;
        document.querySelector("#myForm").submit();
    }
});

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

Вместо привязки к реальному элементу можно добавить специальный маркер:

<div id="scroll-end"></div>

И задать ему стили:

#scroll-end {
    height: 1px;
}

Сцена:

new ScrollMagic.Scene({
    triggerElement: "#scroll-end",
    triggerHook: 1,
    reverse: false
})
.on("enter", function () {
    document.querySelector("#myForm").submit();
})
.addTo(controller);

Альтернативный подход через вычисление позиции

Если отсутствует явный DOM-элемент конца, можно вычислить позицию вручную:

window.addEventListener("scroll", function () {
    var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
    var windowHeight = window.innerHeight;
    var docHeight = document.documentElement.scrollHeight;

    if (scrollTop + windowHeight >= docHeight) {
        document.querySelector("#myForm").submit();
    }
});

Однако такой подход не использует преимущества ScrollMagic, такие как сцены и управление состояниями.


Комбинирование с анимацией

Перед отправкой формы можно добавить визуальную индикацию:

scene.on("enter", function () {
    var button = document.querySelector("#submitBtn");
    button.classList.add("active");

    setTimeout(function () {
        document.querySelector("#myForm").submit();
    }, 500);
});

Работа с асинхронной отправкой

Вместо стандартного submit() часто используется AJAX:

scene.on("enter", function () {
    fetch("/submit", {
        method: "POST",
        body: new FormData(document.querySelector("#myForm"))
    });
});

Это позволяет избежать перезагрузки страницы и сохранить плавность пользовательского опыта.


Отладка сцены

ScrollMagic поддерживает визуализацию триггеров через плагин debug.addIndicators:

scene.addIndicators({
    name: "End Trigger",
    colorStart: "green",
    colorTrigger: "red"
});

Это помогает точно понять, когда сцена срабатывает.


Обработка динамического контента

Если высота страницы изменяется (например, при подгрузке данных), необходимо обновлять контроллер:

controller.update(true);

Или пересоздавать сцену при изменении DOM.


Особенности на мобильных устройствах

  • возможны различия в расчётах viewport
  • динамическая высота адресной строки влияет на window.innerHeight
  • рекомендуется тестировать triggerHook (например, 0.9 вместо 1)

Расширенные сценарии

1. Сабмит только при достижении конца и наличии условий:

scene.on("enter", function () {
    if (formIsValid()) {
        document.querySelector("#myForm").submit();
    }
});

2. Сабмит после полной прокрутки секции:

new ScrollMagic.Scene({
    triggerElement: "#section",
    duration: document.querySelector("#section").offsetHeight,
    triggerHook: 0
})
.on("end", function () {
    document.querySelector("#myForm").submit();
})
.addTo(controller);

Событие "end" срабатывает после прохождения всей длительности сцены.


Управление состоянием сцены

ScrollMagic предоставляет доступ к состоянию:

scene.on("progress", function (event) {
    if (event.progress === 1) {
        document.querySelector("#myForm").submit();
    }
});

progress изменяется от 0 до 1, где 1 означает достижение конца сцены.


Практические замечания

  • использование reverse: false снижает риск повторных действий
  • предпочтительно использовать явные триггер-элементы вместо вычислений
  • необходимо учитывать асинхронность загрузки контента
  • при сложных интерфейсах полезно комбинировать несколько сцен

Архитектурный подход

Для масштабируемости логики рекомендуется выносить обработчики:

function handleScrollEnd() {
    document.querySelector("#myForm").submit();
}

scene.on("enter", handleScrollEnd);

Это упрощает тестирование и повторное использование.


Интеграция с другими библиотеками

ScrollMagic часто используется вместе с:

  • GSAP для анимаций
  • AJAX/Fetch API для отправки данных
  • IntersectionObserver как альтернативный механизм

Однако ScrollMagic остаётся более гибким при сложных сценариях прокрутки.


Оптимизация производительности

  • минимизировать количество сцен
  • избегать тяжёлых вычислений внутри обработчиков
  • использовать requestAnimationFrame при необходимости

Безопасность сабмита

При автоматической отправке важно учитывать:

  • защиту от CSRF
  • валидацию данных перед отправкой
  • предотвращение случайных отправок
if (confirmSubmit) {
    form.submit();
}

Поведение при возврате вверх

Если требуется повторное выполнение при повторной прокрутке:

reverse: true

И сброс состояния:

scene.on("leave", function () {
    submitted = false;
});

Управление несколькими формами

document.querySelectorAll("form.auto-submit").forEach(function(form) {
    scene.on("enter", function () {
        form.submit();
    });
});

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