首页 > 解决方案 > Javascript以恒定速度滚动div

问题描述

我有固定数量的 div 需要水平无限滚动。

因此,当您滚动时,最后会创建一个新的孩子,而另一边会删除一个孩子。像这样的东西:http: //jsfiddle.net/3neoap96/

我在 SO 中的另一个答案中找到了这个动画功能,但问题是我不想从 A 点到 BI 点的动画需要以恒定的速度进行动画,而且这个动画永远不会结束,它会一直持续下去。

这是我目前的功能。它开始正常,但随后进展非常快。

document.addEventListener("DOMContentLoaded", function (event) {
    let lastPos = 0;

    document.getElementById('scroll').addEventListener('scroll', evt => {
        if (lastPos && lastPos - evt.target.scrollLeft > 0) {
            document.querySelectorAll('.element').reverse().forEach(elem => {
                if (isRightOfContainer(elem)) {
                    const width = elem.getBoundingClientRect().width;
                    elem.parentNode.prepend(elem)
                    elem.parentNode.parentNode.scrollLeft += width;
                }
            });
        } else if (lastPos && lastPos - evt.target.scrollLeft < 0) {
            document.querySelectorAll('.element').forEach(elem => {
                if (isLeftOfContainer(elem)) {
                    const width = elem.getBoundingClientRect().width;
                    elem.parentNode.append(elem)
                    elem.parentNode.parentNode.scrollLeft -= width;
                }
            });
        }

        lastPos = evt.target.scrollLeft;
    });

    const isLeftOfContainer = element => {
        const bounds = element.getBoundingClientRect();
        return (-bounds.left + element.parentNode.offsetLeft) >= bounds.width;
    };

    const isRightOfContainer = element => {
        const bounds = element.getBoundingClientRect();
        const box = element.parentNode.parentNode.getBoundingClientRect();
        return bounds.left - element.parentNode.offsetLeft > box.width;
    };

    function scrollToX(scrollTargetX, speed, easing) {
        // scrollTargetY: the target scrollY property of the window
        // speed: time in pixels per second
        // easing: easing equation to use

        const scroll = document.getElementById('scroll');

        const scrollX = scroll.scrollX || scroll.scrollLeft
        scrollTargetX = scrollTargetX || 0,
            speed = speed || 2000,
            easing = easing || 'easeOutSine';
        let currentTime = 0;

        // min time .1, max time .8 seconds
        const time = Math.max(.1, Math.min(Math.abs(scrollX - scrollTargetX) / speed, .8));

        // easing equations from https://github.com/danro/easing-js/blob/master/easing.js
        const easingEquations = {
            easeOutSine: (pos) => {
                return Math.sin(pos * (Math.PI / 2));
            },
            easeInOutSine: (pos) => {
                return (-0.5 * (Math.cos(Math.PI * pos) - 1));
            },
            easeInOutQuint: (pos) => {
                if ((pos /= 0.5) < 1) {
                    return 0.5 * Math.pow(pos, 5);
                }
                return 0.5 * (Math.pow((pos - 2), 5) + 2);
            }
        };

        // add animation loop
        function tick() {
            currentTime += 1 / 60;

            const p = currentTime / time;
            const t = easingEquations[easing](p);

            if (p < 1) {
                requestAnimationFrame(tick);

                scroll.scrollTo(scrollX + ((scrollTargetX - scrollX) * t), 0);
            } else {
                console.log('scroll done');
                scroll.scrollTo(scrollTargetX, 0);
            }
        }

        // call it once to get started
        tick();
    }

    scrollToX(1500, 0, 'easeInOutQuint');
})

我正在使用 Angular 6 顺便说一句。

标签: javascriptangularrequestanimationframe

解决方案


推荐阅读