修复Edge中基于滚动的故障动画?

时间:2018-07-02 09:00:50

标签: javascript scroll microsoft-edge

我正在建立一个网站,当您滚动浏览页面的不同部分时,标题会更改颜色,它通过显示/隐藏不同颜色的标题的不同层,跟踪页面的顶部/底部以使其对齐来实现此目的滚动时。在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 :(得分:0)

除了控制滚动行为外,我找不到其他解决方法。这真的很讨厌,肮脏,并且可以考虑其他任何负面描述词,但是嘿,它确实可行。不过,我希望听到更好的解决方案。

解决方案:

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 });
}