Сайт одностраничный, при нажатии ссылки переходит на определенную позицию на странице. И никак не получается сделать ссылку меню активной при переходе. Подскажите в чем проблема! Код срабатывает только для id="#price"
<div class="ui large secondary inverted pointing menu">
<a class="toc item">
<i class="sidebar icon"></i>
</a>
<a class="active item" href="#home">Home</a>
<a class="item" href="#services">Services</a>
<a class="item" href="#price">Price</a>`
<script>
$(window).scroll(function() {
$("#home, #services", #price).each(function(){
var pos = $(this).position().top;
var winTop = $(window).scrollTop();
if (pos < winTop + 100) {
$("a").addClass("active");
}
else{
$("a").removeClass("active");
}
});
});
</script>
На мой взгляд, задумка в целом правильная, но реализация нерациональна. Кроме очевидной ошибки синтаксиса $("#home, #services", #price)
и обращения ко всем ссылкам на странице $("a")
есть некоторые претензии. $(window).scroll
вызывается мильён раз за время прокрутки и при каждом вызове вы перебираете свои дивки, получаете их position().top
, ищете на странице все 'a' (ну или все 'а' с определенным href, не важно), при том, что меняется только прокрутка страницы, а эти переменные постоянны.
Почему бы не собрать все это один раз, а в колбеке скролла только проверять, причем проверять с конца.
В процессе понял, что проще написать все с начала) Вот что получилось:
Пример на jsfiddle: https://jsfiddle.net/ipshenicyn/owhLpuv9/
Дальше ключевой код из примера, очищенный от лишнего
HTML
Ссылкам добавил класс .scroll-to
, чтобы удобнее было с ними работать. "Якорным" блокам добавил класс .anchor
, чтобы сделать гибко и не лазить в js-код каждый раз, когда на странице появляется новый блок.
<a href="#div1" class="scroll-to">div1</a>
<a href="#div2" class="scroll-to">div2</a>
<a href="#div3" class="scroll-to">div3</a>
<a href="#div4" class="scroll-to">div4</a>
<div id="div1" class="anchor"></div>
<div id="div2" class="anchor"></div>
<div id="div3" class="anchor"></div>
<div id="div4" class="anchor"></div>
JS
var positions = [], //сюда сложим на загрузке страницы позиции наших "якорных" блоков, чтобы не считать их каждый раз. и сюда же положим ссылки на соответствующие a.scroll-to
currentActive = null, //здесь будет храниться id текущего блока, чтобы не менять классы по 100 раз за одну прокрутку
links = $('.scroll-to'); //сохраним массив всех a.scroll-to
$(".anchor").each(function(){ //перебираем блоки, сохраняем позиции и ссылки на пункты меню
positions.push({
top: $(this).position().top - 100,
a: links.filter('[href="#'+$(this).attr('id')+'"]')
});
});
//делаем реверс массива, чтобы при скролле перебирать его с конца и выходить из цикла при нахождении
//зачем нам проверять каждый блок, если прокрутка уже ниже последнего, верно?
positions = positions.reverse();
$(window).on('scroll',function() {
var winTop = $(window).scrollTop();
for(var i = 0; i < positions.length; i++){
if(positions[i].top < winTop){ //если прокрутка страницы ниже нашего блока
if(currentActive !== i){ //и если мы еще не добавили класс текущему блоку
currentActive = i;
links.filter('.active').removeClass('active'); //снимаем класс .active с текущего пункта меню
positions[i].a.addClass("active");
}
break; //выходим из цикла, не нужно проверять блоки, которые выше
}
}
});
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Как я понял атрибут crossorigin - для обработки запросов с других источниковПеречитал интернет, так толком и не понял смысл атрибута
Верстаю сортировку, нужно чтобы список выпадал при клике и выбирался нужный пунктКак это сделать? Буду благодарен за помощь