Исправить глитч-анимацию на основе прокрутки в Edge? - PullRequest
0 голосов
/ 02 июля 2018

Я создаю сайт, у которого цвет заголовка меняется при прокрутке различных разделов на странице, он делает это, показывая / скрывая различные слои разноцветных заголовков, отслеживая верхние и нижние части страниц, чтобы сохранить их выравнивание как вы прокручиваете Прекрасно работает в Chrome, Firefox и т. Д.

Но, Edge, к сожалению, чертовски блестящий с анимацией на основе прокрутки. У меня была эта проблема раньше много раз, и я не нашел решения, и я не смог найти много онлайн в отношении этой проблемы.

Я создал урезанный тестовый набор. Это просто элемент заголовка, который переведен по оси Y на ту же величину, что и scrollTop, так что он остается выровненным по верху страницы.

Хотя моя анимация анимирует разные слои в элементе с фиксированным положением, этот тестовый пример демонстрирует ту же самую глюковость.

Это как если бы значения scrollTop колебались или произошла некоторая задержка в применении стиля.

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

Сбой все еще происходит, когда не используется цикл requestAnimationFrame.

Контрольный пример:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <style type="text/css">
            body {
                margin: 0;
                padding-bottom: 4000px;
            }

            #header {
                position: absolute;
                top: 0;
                left: 0;
                width: 100%;
                height: 100px;
                border: 2px solid #444444;
            }

            * {
                box-sizing: border-box;
            }
        </style>
    </head>
    <body>
        <header id="header">
            Test Header
        </header>
        <script type="text/javascript">
            var header = document.getElementById('header'),
                scrollTop = 0,
                loopTimeout = null;

            function frame() {
                scrollTop = window.pageYOffset || document.documentElement.scrollTop;

                header.style.transform = 'translateY(' + scrollTop + 'px)';

                if (loopTimeout) {
                    requestFrame();
                }
            }

            function requestFrame() {
                window.requestAnimationFrame(frame);
            }

            function endLoop() {
                clearTimeout(loopTimeout);

                loopTimeout = null;
            }

            function startLoop() {
                loopTimeout = setTimeout(endLoop, 500);
            }

            function onWindowScroll() {
                let frame = loopTimeout;

                endLoop();
                startLoop();

                if ( ! frame) {
                    requestFrame();
                }
            }

            window.addEventListener('scroll', onWindowScroll);
        </script>
    </body>
</html>

1 Ответ

0 голосов
/ 04 июля 2018

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

Решение:

applyIEFixes() {
    let container,
        scrollTop;

    // IE 11 needs documentElement as container
    if (this.app.IEVersion <= 11) {
        container = document.documentElement;
        scrollTop = document.documentElement.scrollTop;
    }

    // Edge needs body, however
    else {
        container = document.body;
        scrollTop = document.body.scrollTop;
    }

    let onWheel = event => {
        event.preventDefault();

        scrollTop += event.deltaY;

        if (scrollTop < 0) {
            scrollTop = 0;
        }

        if (scrollTop > this.maxScrollTop) {
            scrollTop = this.maxScrollTop;
        }

        // So we can have some sort of smooth scrolling, still
        TweenLite.to(container, 0.2, {
            scrollTop,
            ease: Power2.easeOut
        });
    };

    let onScroll = () => {
        scrollTop = container.scrollTop;
    };

    container.addEventListener('wheel', onWheel, { passive: false, capture: true });
    // 300ms after last scroll, update the current scrollTop value
    window.addEventListener('scroll', Helpers.delayedFunction(300, onScroll), { passive: false });
}
...