滚动事件触发得太早

时间:2019-01-30 10:16:44

标签: javascript html css scroll

我的网站上有两个固定的标题;其中一个被另一个覆盖着-除非您一直滚动到彩色部分,否则应该剪掉顶部的颜色并在底部露出一个颜色:

    let invertedNavbar = document.querySelector('.navbar--inverted'),
      navbarHeight = invertedNavbar.scrollHeight,
      element = document.querySelector('.color-section')

    function intersectionChecker(e) {
        let elementPosition = element.getBoundingClientRect()
        if (elementPosition.bottom < navbarHeight && elementPosition.bottom > 0) {
          invertedNavbar.style.clipPath = 'polygon( 0% 1000px, 100% 1000px, 100% ' + elementPosition.bottom + 'px, 0% ' + elementPosition.bottom + 'px)'
        }
        if (elementPosition.top > 0 && elementPosition.top < navbarHeight) {
          invertedNavbar.style.clipPath = 'polygon( 0% 0px, 100% 0px, 100% ' + elementPosition.top + 'px, 0% ' + elementPosition.top + 'px)'
        }
        if (elementPosition.top < 0 && elementPosition.bottom > navbarHeight) {
          invertedNavbar.style.clipPath = 'polygon( 0% -10px, 0% -10px, 0% -20px, 0% -20px )'
        }
    }
    intersectionChecker()

    window.addEventListener('scroll', intersectionChecker)
*{
  margin: 0;
}

.navbar{
  background-color: red;
  height: 30px;
  width: 100%;
  position: fixed;
  top: 0; left: 0;
}
.navbar--inverted{
  background-color: blue;
}

.spacer{
  height: 100vh;
}

.color-section{
  background-color: orange;
  height: 300px;
}
<div class="navbar"></div>
<div class="navbar navbar--inverted"></div>
<div class="spacer"></div>
<div class="color-section"></div>
<div class="spacer"></div>

现在,它工作得很好-除了当您滚动到该部分之外时,导航栏还剩下一些剪辑。似乎在实际滚动结束之前就触发了滚动事件。

我尝试了一些不同的选项-推迟使用requestAnimationFrame进行位置检查(完全没有结果,甚至尝试等待两帧,出于某种原因也没有任何改变);顺应setTimeout 100-效果很好,但也使整个过程看起来很滞后;将检查条件加倍,将其变为elementPosition.bottom < 2 * navbarHeight && elementPosition.bottom > -navbarHeight-效果相对较好,但它既简单又不完全安全,用户仍然可以滚动得太快而无法抓住它。您有任何改进的想法吗?

1 个答案:

答案 0 :(得分:1)

实际上,我们误以为该问题来自事件被触发的那一刻,而不是……。这完全是您的情况所致!保留在剪辑中的部分是因为,例如,当滚动达到0时,由于严格的>比较而未触发样式更改。

不知道是否全部都是必需的,但是将它们更改为>=<=可以部分解决问题。

还需要为元素完全低于导航栏添加一个案例:

    let invertedNavbar = document.querySelector('.navbar--inverted'),
      navbarHeight = invertedNavbar.scrollHeight,
      element = document.querySelector('.color-section')

    function intersectionChecker(e) {
        let elementPosition = element.getBoundingClientRect()
        if (elementPosition.top > navbarHeight) {
          invertedNavbar.style.clipPath = ''
        }else{
          if (elementPosition.bottom <= navbarHeight && elementPosition.bottom >= 0) {
            invertedNavbar.style.clipPath = 'polygon( 0% 1000px, 100% 1000px, 100% ' + elementPosition.bottom + 'px, 0% ' + elementPosition.bottom + 'px)'
          }
          if (elementPosition.top >= 0 && elementPosition.top <= navbarHeight) {
            invertedNavbar.style.clipPath = 'polygon( 0% 0px, 100% 0px, 100% ' + elementPosition.top + 'px, 0% ' + elementPosition.top + 'px)'
          }
          if (elementPosition.top <= 0 && elementPosition.bottom >= navbarHeight) {
            invertedNavbar.style.clipPath = 'polygon( 0% -10px, 0% -10px, 0% -20px, 0% -20px )'
          }
        }
    }
    intersectionChecker()

    window.addEventListener('scroll', intersectionChecker)
*{
  margin: 0;
}

.navbar{
  background-color: red;
  height: 30px;
  width: 100%;
  position: fixed;
  top: 0; left: 0;
}
.navbar--inverted{
  background-color: blue;
}

.spacer{
  height: 100vh;
}

.color-section{
  background-color: orange;
  height: 300px;
}
<div class="navbar"></div>
<div class="navbar navbar--inverted"></div>
<div class="spacer"></div>
<div class="color-section"></div>
<div class="spacer"></div>