Сергей Ракипов,
класс и работа кнопки зависят от наличия блоков далее, согласно направлению.
<!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">
⇑
</div>
<div class="nav_down">
⇓
</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);
if(sections[0].getBoundingClientRect().top >= 5) return -1;
if(sections[sections.length - 1].getBoundingClientRect().top <= -5) return sections.length;
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") {
if(navUp.classList.contains('not_found')) return;
nextIndex = Math.max(currentIndex - 1, 0);
} else if (direction === "down") {
if(navDown.classList.contains('not_found')) return;
nextIndex = Math.min(currentIndex + 1, sections.length - 1);
}
smooth(sections[nextIndex]);
}
// обработчики для кнопок
navUp.addEventListener("click", () => {
if(navUp.classList.contains('not_found')) return;
scrollToSection("up");
});
navDown.addEventListener("click", () => {
if(navDown.classList.contains('not_found')) return;
scrollToSection("down");
});
// обработчики для клавиш вверх и вниз
document.addEventListener("keydown", (event) => {
event.preventDefault();
if (event.code === "ArrowUp") {
scrollToSection("up");
} else if (event.code === "ArrowDown") {
scrollToSection("down");
}
});
let addClass = () => {
const up = sections[0].getBoundingClientRect().bottom >= 1;
const down = sections[sections.length - 1].getBoundingClientRect().top <= 1;
navUp.classList.toggle("not_found", up);
navDown.classList.toggle("not_found", down);
}
addClass()
window.addEventListener("scroll", addClass);
</script>
</body>
</html>