以正确方式到达 window 边缘的事件(onscroll)

Event of reaching the edge of window in correct way (onscroll)

以防万一,这是我的第一个问题。

我有: 具有透明背景的导航菜单,并在到达 window.

的顶部边缘时尝试更改背景

window.addEventListener("scroll", navSticky);
function navSticky(){
  let nav = document.getElementById('navbar');
  let bounding = nav.getBoundingClientRect();

  if(bounding.top <= 0 ){
      nav.classList.add("sticky");
  }else{
      nav.classList.remove("sticky");
  }
}
*{
  margin: 0;
  text-align: center;
}

body{
  background: lightgrey;
}

header h1{
  padding: 40px;
}

nav{
  position: sticky;
  top: 0;
  padding: 12px;
  background: linear-gradient(to right, 
  rgba(0,0,0,0),
  rgba(0,255,0, 0.5), 
  rgba(255,0,0, 0.5),
  rgba(0,0,0,0));
  color: black;
}

nav:before{
  content: "now bg transparent";
}

.container{
  min-height: 1000px;
  padding: 20px;
}

nav.sticky{
  background: linear-gradient(to right, 
  rgb(0,255,0), 
  rgb(255,0,0));
  color: white;
}

nav.sticky:before{
  content: "now bg isn't transparent";
}
<body>
  <header>
    <h1>Header, that ask u to scroll page</h1> 
  </header>
  <nav id="navbar">
  </nav>
  <div class ="container">
      When we scroll page, and nav reached top of screen, .sticky add to classList<br>
  </div>
</body>

它的工作,但我有几个问题:

  1. 没有js也能做到吗?
  2. 是否可以优化此脚本,因为滚动事件调用如此频繁..

谢谢!

  1. 很遗憾没有。
  2. 是的,IntersectionObserver API 是针对此特定问题的非常好的高效解决方案。

API 允许您在元素进入或离开视口时观察 元素。它在远离主线程的地方执行此操作,因此您不会获得任何渲染阻塞代码。

在您的具体情况下,请观察 <header> 元素。每当元素离开视图时,navbar 就会变得粘滞。在回调中检查 isIntersecting 属性 是 true 还是 false。 属性 表示观察到的元素是否(部分)在视图中。

const header = document.querySelector('#header');
const nav = document.querySelector('#navbar');

const callback = ([entry]) => {
  const { isIntersecting } = entry;
  nav.classList.toggle('sticky', !isIntersecting);
};

const options = {
  root: null,
  rootMargin: '0px',
  threshold: 0
};

const observer = new IntersectionObserver(callback, options);
observer.observe(header);
* {
  margin: 0;
  text-align: center;
}

body {
  background: lightgrey;
}

header h1 {
  padding: 40px;
}

nav {
  position: sticky;
  top: 0;
  padding: 12px;
  background: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 255, 0, 0.5), rgba(255, 0, 0, 0.5), rgba(0, 0, 0, 0));
  color: black;
}

nav:before {
  content: "now bg transparent";
}

.container {
  min-height: 1000px;
  padding: 20px;
}

nav.sticky {
  background: linear-gradient(to right, rgb(0, 255, 0), rgb(255, 0, 0));
  color: white;
}

nav.sticky:before {
  content: "now bg isn't transparent";
}
<body>
  <header id="header">
    <h1>Header, that ask u to scroll page</h1>
  </header>
  
  <nav id="navbar"></nav>
  
  <div class="container">
    When we scroll page, and nav reached top of screen, .sticky add to classList<br>
  </div>
</body>