Как делать активными пункты меню при прокрутке страницы?

294
10 декабря 2016, 10:32

Сайт одностраничный, при нажатии ссылки переходит на определенную позицию на странице. И никак не получается сделать ссылку меню активной при переходе. Подскажите в чем проблема! Код срабатывает только для 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>
Answer 1

На мой взгляд, задумка в целом правильная, но реализация нерациональна. Кроме очевидной ошибки синтаксиса $("#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; //выходим из цикла, не нужно проверять блоки, которые выше
        }
    }
});
READ ALSO
Что означает атрибут crossorigin у элемента img?

Что означает атрибут crossorigin у элемента img?

Как я понял атрибут crossorigin - для обработки запросов с других источниковПеречитал интернет, так толком и не понял смысл атрибута

241
Проблема с бэкграунд имедж

Проблема с бэкграунд имедж

[![введите сюда описание изображения][1]][1]

204
Есть ли способ закрасить каждое слово?

Есть ли способ закрасить каждое слово?

К примеру есть такая конструкция :

200
Как сделать выпадающий список по клику? [закрыто]

Как сделать выпадающий список по клику? [закрыто]

Верстаю сортировку, нужно чтобы список выпадал при клике и выбирался нужный пунктКак это сделать? Буду благодарен за помощь

298