30.12.2017, 23:20
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,112
|
|
Nlk,
может сделать рефакторинг, вернутся к минимальному макету и сформулировать задачу по новой, возможно дверь где-то рядом.
|
|
31.12.2017, 17:27
|
|
Кандидат Javascript-наук
|
|
Регистрация: 25.12.2016
Сообщений: 146
|
|
Сообщение от рони
|
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>
|
|
31.12.2017, 18:45
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,112
|
|
Сообщение от Nlk
|
Поясню, в приведённом ниже коде при прокручивании страницы, должен активироваться последующийся блок кораллового цвета.
|
как и прежде туманно ... может вам нужен блок который ближе всего к верхней части окна?
ссылка снова на плавный скролл при нажатии на кнопки клавиатуры(вниз, вверх)
|
|
31.12.2017, 18:55
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,112
|
|
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>
|
|
31.12.2017, 19:46
|
|
Кандидат Javascript-наук
|
|
Регистрация: 25.12.2016
Сообщений: 146
|
|
рони,
Заработало в Firefox, спасибо. Правда в Opera иногда прокручивает, но суть понятна спасибо большое, буду пробовать.
|
|
31.12.2017, 19:52
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,112
|
|
Nlk,
if (-100 < pages[i].getBoundingClientRect().top) эксперементируйте.
|
|
03.01.2018, 04:32
|
|
Кандидат Javascript-наук
|
|
Регистрация: 25.12.2016
Сообщений: 146
|
|
рони,
скажите пожалуйста, в приведённом ниже коде, помимо добавления класса к определённому элементу, можно ещё добавить другой класс к его двум соседним элементам справа и слева, используя методы 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");
});
}
|
|
03.01.2018, 09:29
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,112
|
|
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");
*/
}
});
}
|
|
03.01.2018, 19:31
|
|
Кандидат Javascript-наук
|
|
Регистрация: 25.12.2016
Сообщений: 146
|
|
рони,
огромное вам спасибо. Извините что так часто обращаюсь к вам за помощью.
Но я снова с просьбой, когда я искал решение, касаемо уменьшения количества событий на один 'скрол' в браузере 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);
|
|
03.01.2018, 19:45
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,112
|
|
Nlk,
var myEfficientFn = debounce(eventScroll, 250);
document.addEventListener("scroll", myEfficientFn );
|
|
|
|