Add class to the link menu by scrolling in the corresponding section

1

var className = "scroll-link";
var links = document.getElementsByClassName(className);

for (var i = 0; i < links.length; i++) {
    links[i].onclick = scroll;
}

function scroll(e) {

    for (i = 0; i <= links.length; i++) { if (links[i]) { links[i].className = className; } }
    e.target.className = '${className} novaClasse';
    //console.log(e.target.className);
    e.preventDefault();
    var id = this.getAttribute('href').replace('#', '');
    var target = document.getElementById(id).getBoundingClientRect().top;
    animateScroll(target);
}

function animateScroll(targetHeight) {
    targetHeight = document.body.scrollHeight - window.innerHeight > targetHeight + scrollY ?
        targetHeight : document.body.scrollHeight - window.innerHeight;
    var initialPosition = window.scrollY;
    var SCROLL_DURATION = 30;
    var step_x = Math.PI / SCROLL_DURATION;
    var step_count = 0;
    requestAnimationFrame(step);
    function step() {
        if (step_count < SCROLL_DURATION) {
            requestAnimationFrame(step);
            step_count++;
            window.scrollTo(0, initialPosition + targetHeight * 0.25 * Math.pow((1 - Math.cos(step_x * step_count)), 2));
        }
    }
}
 body {
        padding: 0;
        margin: 0;
        font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
    }

    header {
        position: fixed;
        width: 100%;
        top: 0;
        background: #000;
    }

    nav {
        width: 100%;
        text-align: center;
    }

    nav ul {
        padding: 0;
        list-style: none;
    }

    nav ul li {
        display: inline-block;
    }

    nav ul li a{
        text-decoration: none;
        color: #fff;
        margin: 0 1rem;
        font-size: 2.rem;
        text-transform: uppercase;
    } 

    nav ul li a.active {
        color: yellow
        
    }

    main > section {
        padding-top: 5rem;
        height: 100vh;
    }

    #section1 {
        background-color: aqua;
    }

    #section2 {
        background-color: red;
    }

    #section3 {
        background-color: greenyellow;
    }

    #section4 {
        background-color: fuchsia;
    }
 <header id="main-header">
            <nav class="main-menu">
                <ul>
                    <li><a class="scroll-link" href="#section1">Section1</a></li>
                    <li><a class="scroll-link" href="#section2">Section2</a></li>
                    <li><a class="scroll-link" href="#section3">Section3</a></li>
                    <li><a class="scroll-link" href="#section4">Section4</a></li>
                </ul>
            </nav>
    </header>

    <main id="main-content">

        <section id="section1"><h1>Section1</h1></section>
        <section id="section2"><h1>Section2</h1></section>
        <section id="section3"><h1>Section3</h1></section>
        <section id="section4"><h1>Section4</h1></section>

    </main>
    
asked by anonymous 27.07.2018 / 18:12

1 answer

0

Use a onscroll event and verify that the distance from section to top is greater than 0 and less than altura da tela / 2 . This /2 is for the class to only be added when section is at least halfway.

I've also set a flag variable to prevent the onscroll code from being executed by clicking the menu.

In the example I put color: red in the class to see the change in the links:

var className = "scroll-link";
var links = document.getElementsByClassName(className);
var flag = true;

window.onscroll = function(){
   
   if(flag){
      var sections = document.querySelectorAll("#main-content > section");
      
      for(var x=0; x<sections.length; x++){
         var target = sections[x].getBoundingClientRect().top;
         if(target >= 0 && target < window.innerHeight/2){
            
            var ativo = document.querySelector("a.novaClasse");
            if(ativo){
               ativo.classList.remove("novaClasse");
            }
            
            document.querySelectorAll("a.scroll-link")[x].classList.add("novaClasse");
            
         }
      }
   }
}

for (var i = 0; i < links.length; i++) {
    links[i].onclick = scroll;
}

function scroll(e) {

   flag = false;

    for (i = 0; i <= links.length; i++) { if (links[i]) { links[i].className = className; } }
    e.target.className = '${className} novaClasse';
    //console.log(e.target.className);
    e.preventDefault();
    var id = this.getAttribute('href').replace('#', '');
    var target = document.getElementById(id).getBoundingClientRect().top;
    animateScroll(target);
}

function animateScroll(targetHeight) {
    targetHeight = document.body.scrollHeight - window.innerHeight > targetHeight + scrollY ?
        targetHeight : document.body.scrollHeight - window.innerHeight;
    var initialPosition = window.scrollY;
    var SCROLL_DURATION = 30;
    var step_x = Math.PI / SCROLL_DURATION;
    var step_count = 0;
    requestAnimationFrame(step);
    function step() {
        if (step_count < SCROLL_DURATION) {
            requestAnimationFrame(step);
            step_count++;
            window.scrollTo(0, initialPosition + targetHeight * 0.25 * Math.pow((1 - Math.cos(step_x * step_count)), 2));
        }else{
           flag = true;
        }
    }
}
body {
        padding: 0;
        margin: 0;
        font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
    }

    header {
        position: fixed;
        width: 100%;
        top: 0;
        background: #000;
    }

    nav {
        width: 100%;
        text-align: center;
    }

    nav ul {
        padding: 0;
        list-style: none;
    }

    nav ul li {
        display: inline-block;
    }

    nav ul li a{
        text-decoration: none;
        color: #fff;
        margin: 0 1rem;
        font-size: 2.rem;
        text-transform: uppercase;
    } 

    nav ul li a.active {
        color: yellow
        
    }

    main > section {
        padding-top: 5rem;
        height: 100vh;
    }

    #section1 {
        background-color: aqua;
    }

    #section2 {
        background-color: red;
    }

    #section3 {
        background-color: greenyellow;
    }

    #section4 {
        background-color: fuchsia;
    }

.novaClasse{
   color: red;
}
<header id="main-header">
            <nav class="main-menu">
                <ul>
                    <li><a class="scroll-link" href="#section1">Section1</a></li>
                    <li><a class="scroll-link" href="#section2">Section2</a></li>
                    <li><a class="scroll-link" href="#section3">Section3</a></li>
                    <li><a class="scroll-link" href="#section4">Section4</a></li>
                </ul>
            </nav>
    </header>

    <main id="main-content">

        <section id="section1"><h1>Section1</h1></section>
        <section id="section2"><h1>Section2</h1></section>
        <section id="section3"><h1>Section3</h1></section>
        <section id="section4"><h1>Section4</h1></section>

    </main>
    
27.07.2018 / 18:54