Цитата:
|
плавный скроллинг к блоку 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"> ⇑ </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); 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> |
Цитата:
|
рони,
А как условия тут работают, хотя бы в двух словах. Просто когда загружается страница кнопка вверх он активна и ее можно нажать. а по идеи не должна быть потому что вверху нету блоков тоже самое внизу тоже можно нажать еще раз вниз и придешь снова 8 блок хотя по идее внизу нету больше блоков |
Сергей Ракипов,
условия для кнопок на данный момент, фиксируют только факт достижения первого или последнего блока. |
Сергей Ракипов,
класс и работа кнопки зависят от наличия блоков далее, согласно направлению. <!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> |
рони,
Просто одно слово ОГНИЩЕ!!! спасибо !!! |
|
Часовой пояс GMT +3, время: 14:37. |