导航栏向下滚动时隐藏,向上滚动时再次出现

问题描述 投票:0回答:3

我已经探索了几种方法,但似乎没有一种真正能像我想要的那样工作:

  • 我希望向下滚动时,导航栏以用户向下滚动的速度向上移动,就像此时是静态的一样。
  • 当它消失时,我希望它的底部仍然可见,因为这是我有一个进度条的地方(但也许进度条应该在那时分离并位于视口的顶部)。
  • 当您向上滚动时,我希望导航栏再次以滚动的速度出现,就像它是静态的一样,直到您看到整个导航栏,此时它应该粘在视口的顶部。

这是我想要的行为的示例,但不是性能/体验(因为行为是使用

scroll
事件实现的,所以并不顺利)。

我还尝试使用 CSS 变换,它会在向下滚动时添加一个类来隐藏导航栏,然后向上滚动删除该类,从而为导航栏隐藏/显示设置动画,但问题是动画速度与滚动脱节速度。

我也尝试过 CSS 粘性位置,但看起来我需要与它提供的相反的内容。

还有其他方法可以让这项工作顺利进行吗?

javascript css dom
3个回答
1
投票

检查您提供的链接,它似乎按预期工作(您希望它链接到滚动事件,因为您希望它作为“静态”移动)。但是,如果由于滚动事件不一致而在某些系统上出现不稳定,您可以尝试添加持续时间足够小的

transition
属性。请记住,只有在位置属性保持不变时才应启用此功能,否则当从“绝对”更改为“固定”时,由于坐标原点发生变化,它会弄乱事情。

因此您可以添加另一个变量

let changedPosition = false;
,每当您更改
position
属性时,您都可以这样做

if (position !== "absolute") {
  changedPosition = true;
} else {
  changedPosition = false;
}
position = "absolute";

if (position !== "fixed") {
  changedPosition = true;
} else {
  changedPosition = false;
}
position = "fixed";

当你应用这种风格时

navbar.style = `position: ${position}; top: ${navbarTop}px; transitiona: ${
    changedPosition ? "none" : "100ms linear"
  }`;

喜欢https://codepen.io/gpetrioli/pen/XWVKxNG?editors=0010


您应该尝试一下您提供的过渡属性,我只是在那里放置了一些示例值。


0
投票

我看过你的问题,我想我找到了一个简单的方法。

通过这个简单的函数,您可以获得用户滚动的像素数量。

window.onscroll = function (e) {
    console.log(window.scrollY); // Value of scroll Y in px
};

用户滚动所需的像素数量后,使进度条

fixed top
(或
position:fixed;top:0


0
投票

Gabriele Petrioli 给出了一个很好的答案,但“transitiona”一词有一个拼写错误。 这是一个面向性能的代码,带有一些 onScroll 限制和代码改进:

<script>
let throttling = false;

function onScrollThrottled() {
  if (!throttling) {
    throttling = true;
    requestAnimationFrame(() => {
      onScroll();
      throttling = false;
    });
  }
}


let navbarTop = 0;
let transition = true;
let position = "absolute";
let lastScrollPosition = 0;

const navbar = document.getElementById("navbar");

function onScroll() {

  const currentScrollPosition = window.pageYOffset || document.documentElement.scrollTop;

  if (currentScrollPosition <= 0) {

    lastScrollPosition = 0;
    navbarTop = 0;

    if (position !== "absolute") { transition = true; }
    else { transition = false; }
    position = "absolute";

  } else {
    
    if (currentScrollPosition > lastScrollPosition) {

      if (position !== "absolute") { transition = true; }
      else { transition = false; }
      position = "absolute";

      let { top, height } = navbar.getBoundingClientRect()
      navbarTop = currentScrollPosition + Math.max(top, -height);

    } else {

      const { top } = navbar.getBoundingClientRect()

      if (top >= 0) {

        navbarTop = 0;

        if (position !== "fixed") { transition = true; }
        else { transition = false; }
        position = "fixed";

      }

    }

    lastScrollPosition = currentScrollPosition;

  }
  navbar.style = `position: ${position}; top: ${navbarTop}px; transition: ${ transition ? "none" : "100ms linear" }`;
}

window.addEventListener("scroll", onScrollThrottled, { passive: true });
</script>
© www.soinside.com 2019 - 2024. All rights reserved.