向下滚动到部分时,用anime.js动画菜单项

问题描述

我正在尝试将@David中的代码@Luisdanielroviracontreras中的代码结合起来,为我的投资组合案例研究提供一个很酷的索引菜单。到目前为止,单击时我已经可以对项目背景进行动画处理: https://codepen.io/andyradall/pen/BaKJpbM

但是,正如您所看到的,在尝试根据滚动位置为菜单项的背景设置动画时,我遇到了问题。后台项目以错误的位置结尾:https://codepen.io/andyradall/pen/WNwdRLq

注意。我的问题:

  1. 特殊性,然后在js中选择正确的HTML元素。
  2. 将活动班级附加到按钮,而不只是 a
  3. 或者,我需要删除按钮并将 .effect 附加到 a

这是我的重点导航部分的当前代码

// Header Sticky
window.onscroll = function() {myFunction()};

var header = document.getElementById("navigation");
var sticky = header.offsetTop;

function myFunction() {
  if (window.pageYOffset > sticky) {
    header.classList.add("sticky");
  } else {
    header.classList.remove("sticky");
  }
}

/* Header buttons Luis that attatches active to buttons on click. */
/*
const buttons = document.querySelectorAll('.header-navbar button')
const effect = document.querySelector('.effect')

buttons.forEach((item) => {
  item.addEventListener('click',(evt) => {
      const x = evt.target.offsetLeft
      buttons.forEach((btn) => { btn.classList.remove('active') })
      evt.target.classList.add('active')
      anime({
          targets: '.effect',left: `${x}px`,duration: 600,})
  })
})
*/

/* header buttons on scroll from @Daniel at stackoverflow that misses the buttons and only attatches the active to the link*/

// caches the navigation links
var $navigationLinks = $('#navigation > ul > li > a');

// what I really want:
/*var buttons = document.querySelectorAll('.header-navbar button')
var effect = document.querySelector('.effect')*/

// cache (in reversed order) the sections
var $sections = $($(".section").get().reverse());

// map each section id to their corresponding navigation link
// here i really want to map each section id to the corresponding button
var sectionIdTonavigationLink = {};
$sections.each(function() {
    var id = $(this).attr('id');
    sectionIdTonavigationLink[id] = $('#navigation > ul > li > a[href=\\#' + id + ']');
});

// throttle function,enforces a minimum time interval
function throttle(fn,interval) {
    var lastCall,timeoutId;
    return function () {
        var Now = new Date().getTime();
        if (lastCall && Now < (lastCall + interval) ) {
            // if we are inside the interval we wait
            clearTimeout(timeoutId);
            timeoutId = setTimeout(function () {
                lastCall = Now;
                fn.call();
            },interval - (Now - lastCall) );
        } else {
            // otherwise,we directly call the function 
            lastCall = Now;
            fn.call();
        }
    };
}

function highlightNavigation() {
    // get the current vertical position of the scroll bar
    var scrollPosition = $(window).scrollTop();
    const effect = document.querySelector('.effect')
   
    // iterate the sections
    $sections.each(function() {
        var currentSection = $(this);
        // get the position of the section
        var sectionTop = currentSection.offset().top;
        var x = currentSection.offset().top;
        console.log(x);
        // if the user has scrolled over the top of the section  
        if (scrollPosition >= sectionTop) {
            // get the section id
            var id = currentSection.attr('id');
            // get the corresponding navigation link
            var $navigationLink = sectionIdTonavigationLink[id];
            // if the link is not active
            if ($navigationLink.hasClass('active')) {
                // remove .active class from all the links
                $navigationLinks.removeClass('active');
                // add .active class to the current link
                $navigationLink.addClass('active')
               anime({
                targets: '.effect',});
            }
            // we have found our section,so we return false to exit the each loop
            return false;
        }
    });
}

$(window).scroll( throttle(highlightNavigation,100) );

// if you don't want to throttle the function use this instead:
//$(window).scroll( highlightNavigation );
/* Global */

* {
  list-style: none;
  outline: none;
  padding: 0;
  margin: 0;
  font-family: 'Poppins',sans-serif;
  Box-sizing: border-Box;
}

body {
  --primary: 25,91,255;
  --color: 44,62,80;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  background: #f4f7f8;
 /* height: calc(var(--vh,1vh) * 100); */
 /* overflow: hidden; */
  color: rgb(var(--color));
  width: 100%;
}

main {
  width: 100%;
}

/* .sticky attatch to #navigation on scroll past #navigation */
.sticky {
  position: fixed;
  top: 0;
}

.header-navbar ul {
list-style: none;
display: flex;
align-items: center;
justify-content: space-evenly;
width: 100%;
background: #fff;
}

.header-navbar {
  display: flex;
  align-items: center;
  justify-content: space-evenly;
  width: 100%;
  background: #fff;
  padding: 24px 8px 24px 8px;
  Box-shadow: 0px 0px 30px 0px rgba(0,.05);
}

.header-navbar button {
  width: 140px;
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0px;
  background: transparent;
  border-radius: 20px;
  transition: all .25s ease;
}

/*.header-navbar a {
  width: 160px;
  height: 50px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0px;
  background: transparent;
  border-radius: 20px;
  transition: all .25s ease;
}*/

.header-navbar a{
  /*color: #333; */
  font-size: 1rem;
  padding: 10px 10px 10px 10px;
  text-decoration: none;
}

/* to use if adding back link*/
.header-navbar a:active:not(.float) {
  transform: scale(1.2);
}

.header-navbar button.active {
  color: rgb(232,76,79);
}

/* if icon not text */
.header-navbar button i {
  font-size: 1.2rem;
  pointer-events: none;
}

/*background effect*/

.con-effect {
  position: absolute;
  width: 100%;
  height: 100%;
  /*top: 0px;
  left: 0px;*/
  overflow: hidden;
  pointer-events: none;
  display: flex;
  align-items: center;
  justify-content: center;
}

.effect {
  background: rgba(232,232,0.15);
  width: 160px;
  height: 70px;
  position: absolute;
  left: 100px;
  border-radius: 20px;
}

/* Content sections styling */

.hero {
  width:100%;
  padding: 32px;
}

.section{
width:100%;
height: 500px;
padding: 32px;
}

#first {
  background-color: #8face0;
}

#second {
  background-color: #a388e8;
}

#third {
  background-color: #f4769e;
}

#fourth {
  background-color: #8face0;
}

#fifth {
  background-color: #a388e8;
}

#bottom-spacer {
  height: 2200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src=https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.0/anime.min.js></script>
<body>
    <main>
        <section id="intro" class="hero">
            <div>
              <h1>This will be the hero section</h1>
            </div>
        </section>    
        <div id="navigation" class="header-navbar">
            <div class="con-effect">
            <div class="effect"></div>
            </div>

            <ul>
            <li><a href="#intro"><button>Introduction</button></a></li>
            <li><a href="#first"><button>1. User research</button></a></li>
            <li><a href="#second"><button>2. Ideation</button></a></li>
            <li><a href="#third"><button>3. Design phase</button></a></li>
            <li><a href="#fourth"><button>4. Testing</button></a></li>
            <li><a href="#fifth"><button>5. Results</button></a></li>
        </ul>    
</div>

        </div>  
               <section class="sections">
                   <section id="first" class="section">
                       <h2>1. User research</h2>
                   </section>    
                   <section id="second" class="section">
                       <h2>2. Ideate</h2>
                   </section>  
                   <section id="third" class="section">
                       <h2>3. Design phase</h2>
                   </section>
                   <section id="fourth" class="section">
                       <h2>4. Testing</h2>
                   </section>
                   <section id="fifth" class="section">
                       <h2>5. Results</h2>
                    </section>                    
                    <section id="bottom-spacer">
                     </section>   
           </section>
</main>
   
</body>

解决方法

终于解决了! 解决方案:

  1. 找到左侧的活动导航链接偏移量,并将其存储在var x
  2. 使用Navigationlink偏移量左值( x )放置背景效果

现在,仅剩下样式和微调了:) 决赛将在这里收到更新:https://codepen.io/andyradall/pen/WNwdRLq

// sticky header
window.onscroll = function() {myFunction()};

var header = document.getElementById("navigation");
//var effectClass = document.getElementById("effectClass")
var sticky = header.offsetTop;

function myFunction() {
  if (window.pageYOffset > sticky) {
    header.classList.add("sticky");
    //effectClass.classList.add("effect")
  } else {
    header.classList.remove("sticky");
    //effectClass.classList.remove("effect")
  }
}


// cache the navigation links 
var $navigationLinks = $('#navigation > ul > li > a');
// cache (in reversed order) the sections
var $sections = $($(".section").get().reverse());

// map each section id to their corresponding navigation link
var sectionIdTonavigationLink = {};
$sections.each(function() {
    var id = $(this).attr('id');
    sectionIdTonavigationLink[id] = $('#navigation > ul > li > a[href=\\#' + id + ']');
});

// throttle function,enforces a minimum time interval
function throttle(fn,interval) {
    var lastCall,timeoutId;
    return function () {
        var now = new Date().getTime();
        if (lastCall && now < (lastCall + interval) ) {
            // if we are inside the interval we wait
            clearTimeout(timeoutId);
            timeoutId = setTimeout(function () {
                lastCall = now;
                fn.call();
            },interval - (now - lastCall) );
        } else {
            // otherwise,we directly call the function 
            lastCall = now;
            fn.call();
        }
    };
}

function highlightNavigation() {
    // get the current vertical position of the scroll bar
    var scrollPosition = $(window).scrollTop();
    const effect = document.querySelector('.effect')

    // iterate the sections
    $sections.each(function() {
        var currentSection = $(this);
        // get the position of the section
        var sectionTop = currentSection.offset().top;
        // if the user has scrolled over the top of the section  
        if (scrollPosition >= sectionTop) {
            // get the section id
            var id = currentSection.attr('id');
            // get the corresponding navigation link
            var $navigationLink = sectionIdTonavigationLink[id];
            // if the link is not active
            if (!$navigationLink.hasClass('active')) {
                // remove .active class from all the links
                $navigationLinks.removeClass('active');
                // add .active class to the current link
                $navigationLink.addClass('active');
                var x = $navigationLink.offset().left;
                anime({
                    targets: '.effect',left: `${x-28}px`,duration: 600,endDelay: 1000,})
            }
            // we have found our section,so we return false to exit the each loop
            return false;
        }
    });
}

 $(window).scroll( throttle(highlightNavigation,100) );

// if you don't want to throttle the function use this instead:
// $(window).scroll( highlightNavigation );
* {
  list-style: none;
  outline: none;
  padding: 0;
  margin: 0;
  font-family: 'Poppins',sans-serif;
  box-sizing: border-box;
}

body {
  --primary: 25,91,255;
  --color: 44,62,80;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  background: #f4f7f8;
 /* height: calc(var(--vh,1vh) * 100); */
 /* overflow: hidden; */
  color: rgb(var(--color));
  width: 100%;
}

main {
  width: 100%;
}

/* .sticky attatch to #navigation on scroll past #navigation */
.sticky {
  position: fixed;
  top: 0;
}

.header-navbar ul {
list-style: none;
display: flex;
align-items: center;
justify-content: space-evenly;
width: 100%;
background: #fafafa;
}

.header-navbar {
  display: flex;
  align-items: center;
  justify-content: space-evenly;
  width: 100%;
  background: #fafafa;
  padding: 2px 0 2px 0;
  box-shadow: 0 1px 2px rgba(0,0.06),0 2px 4px rgba(0,0 4px 8px rgba(0,0 8px 16px rgba(0,0 16px 32px rgba(0,0 32px 64px rgba(0,0.06);
}

.header-navbar li {
  width: 160px;
  height: 50px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0px;
  background: transparent;
  border-radius: 20px;
  transition: all .25s ease;
}

/*.header-navbar a {
  width: 160px;
  height: 50px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0px;
  background: transparent;
  border-radius: 20px;
  transition: all .25s ease;
}*/

.header-navbar a{
  color: #333;
  font-size: 1rem;
  /*padding: 8px 8px 8px 8px;*/
  text-decoration: none;
}

/* :not excludes class for specific use */
.header-navbar a:active:not(.float) {
  transform: scale(1.2);
}

.active {
  
  color: rgb(232,76,79)!important;
}

.header-navbar a:active {
 
  color: rgb(232,79)!important;
}

/* if icon not text */
.header-navbar a i {
  font-size: 1.2rem;
  pointer-events: none;
}

/*background effect*/

.con-effect {
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0px;
  left: 0px;
  overflow: hidden;
  pointer-events: none;
  display: flex;
  align-items: center;
  justify-content: center;
}

.effect {
  background: rgba(232,232,0.15);
  width: 178px;
  height: 40px;
  position: absolute;
  left: 1px;
  border-radius: 40px;
}

/* Content sections styling */

.hero {
  width:100%;
  padding: 32px;
}

.section{
  color: #666;
width:100%;
/*height: 500px;*/
padding: 32px;
}

#first {
  background-color: #8face0;
}

#second {
  background-color: #a388e8;
}

#third {
  background-color: #f4769e;
}

#fourth {
  background-color: #8face0;
}

#fifth {
  background-color: #a388e8;
}

#bottom-spacer {
  height: 2200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.0/anime.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
     <main>
        <section id="intro" class="hero section">
            <div>
              <h1>This will be the hero section</h1>
            </div>
        </section>    
        <div id="navigation" class="header-navbar">
            <div class="con-effect">
            <div id="effectClass" class="effect"></div>
            </div>
        <ul>
            <li><a href="#intro">Introduction</a></li>
            <li><a href="#first">1. User research</a></li>
            <li><a href="#second">2. Ideation</a></li>
            <li><a href="#third">3. Design phase</a></li>
            <li><a href="#fourth">4. Testing</a></li>
            <li><a href="#fifth">5. Results</a></li>
        </ul> 
        </div>  
               <section class="sections">
                   <section id="first" class="section">
                       <h2>1. User research</h2>
                   </section>    
                   <section id="second" class="section">
                       <h2>2. Ideate</h2>
                   </section>  
                   <section id="third" class="section">
                       <h2>3. Design phase</h2>
                   </section>
                   <section id="fourth" class="section">
                       <h2>4. Testing</h2>
                   </section>
                   <section id="fifth" class="section">
                       <h2>5. Results</h2>
                    </section>                    
                    <section id="bottom-spacer">
                     </section>   
           </section>
</main>
</body>