Показать сообщение отдельно
  #12 (permalink)  
Старый 05.06.2023, 10:10
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,118

плавный скроллинг к блоку requestAnimationFrame
Сергей Ракипов,
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body {
            font-family: 'Courier New', Courier, monospace;
            font-size: 16px;
        }

        section {
            height: 600px;
            padding: 0px 0px 0px 60px;
            font-weight: bold;
            border: 1px solid #8B4513;
        }

        header {
            height: 600px;
        }

        footer {
            height: 600px;
        }

        nav {
            position: fixed;
            top: 30px;
            left: 8px;
            right: 0px;
        }

        .nav_up {
            height: 50px;
            width: 50px;
            display: flex;
            justify-content: center;
            align-items: center;
            background-color: #98FB98;
            color: #fff;
            font-size: 25px;
            cursor: pointer;
        }

        .nav_down {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 50px;
            width: 50px;
            background-color: #755D9A;
            color: #fff;
            font-size: 24px;
            cursor: pointer;
        }

        .not_found {
            opacity: .2;
        }
    </style>
</head>

<body>
    <nav>
        <div class="nav_up">
            &uArr;
        </div>
        <div class="nav_down">
            &dArr;
        </div>
    </nav>
    <header>
        Шапка
    </header>
    <section>
        Блок 1
    </section>
    <section>
        Блок 2
    </section>
    <section>
        Блок 3
    </section>
    <section>
        Блок 4
    </section>
    <section>
        Блок 5
    </section>
    <section>
        Блок 6
    </section>
    <section>
        Блок 7
    </section>
    <section>
        Блок 8
    </section>
    <footer>
        Подвал
    </footer>
    <script>
        const sections = document.querySelectorAll("section");
        const navUp = document.querySelector(".nav_up");
        const navDown = document.querySelector(".nav_down");

        function anim(speed) {
            let temp;
            return function(elem) {
                cancelAnimationFrame(temp);
                let start = performance.now();
                let from = window.pageYOffset || document.documentElement.scrollTop,
                    to = elem.getBoundingClientRect().top;
                let duration = Math.abs(to) * speed;
                requestAnimationFrame(function step(timestamp) {
                    let progress = (timestamp - start) / duration;
                    1 <= progress && (progress = 1);
                    window.scrollTo(0, from + to * progress | 0);
                    1 > progress && (temp = requestAnimationFrame(step))
                })
            }
        };
        const smooth = anim(1.8);

        function getCurrentIndex() {
            let currentIndex = 0,
                arr = Array.from(sections);
            let item = arr.slice(0).sort(function(a, b) {
                return Math.abs(a.getBoundingClientRect().top) - Math.abs(b.getBoundingClientRect().top);
            })[0];
            currentIndex = arr.indexOf(item);
            return currentIndex;
        }

        function scrollToSection(direction) {
            const currentIndex = getCurrentIndex();
            let nextIndex;
            if (direction === "up") {
                nextIndex = Math.max(currentIndex - 1, 0);
            } else if (direction === "down") {
                nextIndex = Math.min(currentIndex + 1, sections.length - 1);
            }
            smooth(sections[nextIndex]);
        }
        // обработчики для кнопок
        navUp.addEventListener("click", () => {
            scrollToSection("up");
        });
        navDown.addEventListener("click", () => {
            scrollToSection("down");
        });
        // обработчики для клавиш вверх и вниз
        document.addEventListener("keydown", (event) => {
            event.preventDefault();
            if (event.code === "ArrowUp") {
                scrollToSection("up");
            } else if (event.code === "ArrowDown") {
                scrollToSection("down");
            }
        });
        window.addEventListener("scroll", () => {
            const currentIndex = getCurrentIndex();
            const show = Math.abs(sections[currentIndex].getBoundingClientRect().top) < 1;
            navUp.classList.toggle("not_found", !currentIndex && show);
            navDown.classList.toggle("not_found", currentIndex == sections.length - 1 && show);
        })
    </script>
</body>

</html>

Последний раз редактировалось рони, 05.06.2023 в 16:40. Причина: изменена скорость прокрутки
Ответить с цитированием