Nlk,
может сделать рефакторинг, вернутся к минимальному макету и сформулировать задачу по новой, возможно дверь где-то рядом. |
Цитата:
Ребята, подскажите пожалуйста. Очень долго уже ломаю голову) Проблема данного кода в том, что в некоторых браузерах, при единождом 'скроле' страницы, происходит сразу несколько событий. Поясню, в приведённом ниже коде при прокручивании страницы, должен активироваться последующийся блок кораллового цвета. Но в некоторых браузерах, при первом же 'скроле', у нас сразу активируется последний блок. По причине того, что за один 'скрол', класс .active успевает назначиться сразу всем последующим блокам, и остановиться на последнем. <!DOCTYPE html><head><meta charset="UTF-8"><style> body {min-height: 200vh;} .page {height: 25vh; width: 100%; background: gray; border: 2px solid white;} .active {background: coral;} </style></head><body> <section class="page"></section> <section class="page"></section> <section class="page"></section> <section class="page"></section> <script>'use strict'; window.addEventListener("DOMContentLoaded", function() { document.addEventListener("scroll", eventScroll); const pages = document.querySelectorAll(".page"); let lastScrolled = 0; function showPage() { [].forEach.call(pages, function(el, i) { i == pageIndex ? el.classList.add("active") : el.classList.remove("active"); }); } let pageIndex = 0; showPage(); function eventScroll() { let scrolled = window.pageYOffset || document.documentElement.scrollTop; if (scrolled < lastScrolled) { --pageIndex; } else { ++pageIndex; }; pageIndex < 0 && (pageIndex = 0); pageIndex > pages.length - 1 && (pageIndex = pages.length - 1); showPage(); lastScrolled = scrolled; } }); </script></body></html> |
Цитата:
ссылка снова на плавный скролл при нажатии на кнопки клавиатуры(вниз, вверх) |
Nlk,
<!DOCTYPE html> <html> <head><meta charset="UTF-8"><style> body {min-height: 200vh;} .page {height: 25vh; width: 100%; background: gray; border: 2px solid white;} .active {background: coral;} </style></head><body> <section class="page"></section> <section class="page"></section> <section class="page"></section> <section class="page"></section> <script> window.addEventListener("DOMContentLoaded", function() { document.addEventListener("scroll", eventScroll); var pages = document.querySelectorAll(".page"); function showPage(pageIndex) { [].forEach.call(pages, function(el, i) { i === pageIndex ? el.classList.add("active") : el.classList.remove("active"); }); } function eventScroll() { for (var i = 0; i < pages.length; i++) { if (0 < pages[i].getBoundingClientRect().top) { break; } } showPage(i); } eventScroll() }); </script></body></html> |
рони,
Заработало в Firefox, спасибо. Правда в Opera иногда прокручивает, но суть понятна спасибо большое, буду пробовать. |
Nlk,
if (-100 < pages[i].getBoundingClientRect().top) эксперементируйте. :) |
рони,
скажите пожалуйста, в приведённом ниже коде, помимо добавления класса к определённому элементу, можно ещё добавить другой класс к его двум соседним элементам справа и слева, используя методы nextElementSibling и previousElementSibling? function showPage() { [].forEach.call(pages, function(el, i) { i == pageIndex ? el.classList.add("active") && el.nextElementSibling.classList.add("new") : el.classList.remove("active"); }); } |
Nlk,
добавить можно, но как правильно отменить не знаю, алгоритм нужен или два цикла, первый для отмены всех классов второй для установки function showPage() { [].forEach.call(pages, function(el, i, p) { el.classList.remove("active"); el.classList.remove("new"); }); [].forEach.call(pages, function(el, i, p) { if(i == pageIndex ) { el.classList.add("active"); el.nextElementSibling && el.nextElementSibling.classList.add("new"); el.previousElementSibling && el.previousElementSibling.classList.add("new"); /* или так p[i-1] && p[i-1].classList.add("new"); p[i+1] && p[i+1].classList.add("new"); */ } }); } |
рони,
огромное вам спасибо. Извините что так часто обращаюсь к вам за помощью. Но я снова с просьбой, когда я искал решение, касаемо уменьшения количества событий на один 'скрол' в браузере Mozilla. То натолкнулся на материал, про функцию debounce, которая не позволяет обработчику события выполниться более одного раза в заданный промежуток времени. Могу ли я проецировать это к своему коду и как? В интернете мне попался такой пример, но я не понимаю как могу его использовать: // Returns a function, that, as long as it continues to be invoked, will not // be triggered. The function will be called after it stops being called for // N milliseconds. If `immediate` is passed, trigger the function on the // leading edge, instead of the trailing. function debounce(func, wait, immediate) { var timeout; return function() { var context = this, args = arguments; var later = function() { timeout = null; if (!immediate) func.apply(context, args); }; var callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; }; // Usage var myEfficientFn = debounce(function() { // All the taxing stuff you do }, 250); window.addEventListener('resize', myEfficientFn); |
Nlk,
var myEfficientFn = debounce(eventScroll, 250); document.addEventListener("scroll", myEfficientFn ); |
Часовой пояс GMT +3, время: 02:23. |