首页 > 解决方案 > 在滚动时突出显示侧边栏项目

问题描述

简单地说,我有一个带有类别列表的侧边栏。在正文中,我列出了许多卡片,其中每张卡片对应于侧边栏列表中的一个类别。

目标:当我滚动页面时,我希望在侧边栏中突出显示正确的类别。

尝试:我在这个CodePen中尝试了一段时间,但不知何故,我似乎无法做到恰到好处。

这是我的代码:

    /* Menu - Show active */
    const newsItems = document.querySelectorAll('.item');
    function highlightMenuItem() {
        newsItems.forEach((el) => {
            let bounding = el.getBoundingClientRect();
            let elementHeight = el.offsetHeight / 2;

            if (bounding.top >= 0 && bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) + elementHeight) {
                let activeMenu = el.getAttribute('data-category');
                document.querySelector('.' + activeMenu).classList.add('menu-active');
                console.log(document.querySelectorAll('.menu-active'));


                 if (document.querySelectorAll('.menu-active').length > 1) {
                     document.querySelectorAll('.menu-active')[0].classList.remove('menu-active');
                 }

            } else {
                let inActiveMenu = el.getAttribute('data-category');

                if (document.querySelector('.' + inActiveMenu).classList.contains('menu-active')) {
                    document.querySelector('.' + inActiveMenu).classList.remove('menu-active');
                }
            }

        });
    }

document.addEventListener('scroll', function() {
  window.requestAnimationFrame(function() {
    highlightMenuItem();
  });
});
* {
  box-sizing: border-box;
}    

.menu__list {
        background-color: #fff;
        display: flex;
        box-sizing: border-box;
        flex-direction: column;
        justify-content: space-around;
        position: fixed;
        top: 0;
        bottom: 0;
        right: 0;
        width: 50px;
    }

    .menu__item {
        border: solid 1px #000;
        flex: 1 1 0;
        border-top: none;
        text-align: center;
        transition: all .3s;

        a {
            font-weight: 300;
            font-size: 10px;
            line-height: 1.8;
            letter-spacing: -0.2px;
            height: 100%;
            width: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        span {
            transform: rotate(-90deg);
            display: block;
        }

        &.menu-active {
            color: #fff;
            background: #000;
        }
    }


.wrapper {
  display: grid;
  padding-right: 50px;
  grid-template-columns: 1fr 1fr 1fr;
}


.item {
  text-align: center;
  border: solid 1px #000;
  height: 200px;
  display: flex;
  justify-content: center;
  align-items: center;
}
  <div class="menu__list">
    <div class="next-space menu__item">
      <a href="{{link_url::288}}#next-space"><span>Space</span></a>
    </div>
    <div class="next-intelligence menu__item">
      <a href="{{link_url::288}}#next-intelligence"><span>Intelligence</span></a>
    </div>
    <div class="next-mobility menu__item">
      <a href="{{link_url::288}}#next-mobility"><span>Mobility</span></a>
    </div>
    <div class="next-security menu__item">
      <a href="{{link_url::288}}#next-security"><span>Security</span></a>
    </div>
    <div class="next-medtech menu__item">
      <a href="{{link_url::288}}#next-medtech"><span>Medtech</span></a>
    </div>
    <div class="next-money menu__item">
      <a href="{{link_url::288}}#next-money"><span>Money</span></a>
    </div>
  </div>

<div class="wrapper">
  <div class="item next-space" data-category="next-space">Space</div>
  <div class="item next-space" data-category="next-space">Space</div>
  <div class="item next-space" data-category="next-space">Space</div>
  <div class="item next-space" data-category="next-space">Space</div>
  <div class="item next-intelligence" data-category="next-intelligence">Intelligence</div>
  <div class="item next-intelligence" data-category="next-intelligence">Intelligence</div>
  <div class="item next-intelligence" data-category="next-intelligence">Intelligence</div>
  <div class="item next-intelligence" data-category="next-intelligence">Intelligence</div>
  <div class="item next-mobility" data-category="next-mobility">Mobility</div>
  <div class="item next-mobility" data-category="next-mobility">Mobility</div>
    <div class="item next-security" data-category="next-security">Security</div>
  <div class="item next-security" data-category="next-security">Security</div>
  <div class="item next-security" data-category="next-security">Security</div>
  <div class="item next-security" data-category="next-security">Security</div>
  <div class="item next-mobility" data-category="next-mobility">Mobility</div>
  <div class="item next-medtech" data-category="next-medtech">Medtech</div>
  <div class="item next-medtech" data-category="next-medtech">Medtech</div>
  <div class="item next-medtech" data-category="next-medtech">Medtech</div>
  <div class="item next-medtech" data-category="next-medtech">Medtech</div>
  <div class="item next-medtech" data-category="next-medtech">Medtech</div>
  <div class="item next-medtech" data-category="next-medtech">Medtech</div>
  <div class="item next-money" data-category="next-money">Money</div>
  
  

</div>

标签: javascripthtmlcss

解决方案


您可以使用 isInViewPort 函数,通过它您可以确定 html 元素是否在屏幕上。因此,您可以突出显示侧边栏项目。

function isInViewport(element) {
    const rect = element.getBoundingClientRect();
    return (
        rect.top >= 0 &&
        rect.left >= 0 &&
        rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
        rect.right <= (window.innerWidth || document.documentElement.clientWidth)
    );
}

将html元素传递给函数,函数将返回true或false,true在屏幕上,false不在屏幕上。如果您在用户向下滚动页面时对此进行控制,则可以突出显示正确的侧边栏项目。

也可以查看此链接: https ://www.javascripttutorial.net/dom/css/check-if-an-element-is-visible-in-the-viewport/


推荐阅读