英文:
How to hide NavBar when the user stops scrolling?
问题
我在我的网站中实现了一段代码,当向下滚动时隐藏导航栏,当向上滚动时显示导航栏。
问题是,我希望当用户向上滚动并停止滚动以阅读网站上的内容时,大约5秒后导航栏会再次隐藏,直到用户再次开始滚动。
我该如何实现这个功能?
这是我用于显示/隐藏导航栏的脚本:
<script>
const nav = document.querySelector("nav");
const navHeight = 70;
// 滚动开始的位置(以像素为单位)
let lastScrollY = 0;
// 触发滚动之前要滚动的距离(以像素为单位)
const delta = 10;
// 滚动时运行的函数
function scrolled() {
let sy = window.scrollY;
// 仅在滚动超过 delta 时触发
if (Math.abs(lastScrollY - sy) > delta) {
// 向下滚动 -> 隐藏导航栏
if (sy > lastScrollY && sy > navHeight) {
nav.classList.add("nav-up");
}
// 向上滚动 -> 显示导航栏
else if (sy < lastScrollY) {
nav.classList.remove("nav-up");
}
// 更新当前滚动位置
lastScrollY = sy;
}
}
// 添加事件监听器和防抖,以免不断检查滚动
let didScroll = false;
window.addEventListener("scroll", function(e){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
scrolled();
didScroll = false;
}
}, 250);
</script>
我应该添加什么内容,以便当用户向上滚动并停止滚动时,导航栏会自动隐藏?
英文:
I have implemented a code in my website that will hide the navbar when scrolling down and show it when scrolling up.
the problem is I want when the user scroll up and stops scrolling to read something on the website after like 5 sec the navbar will hide again until the user starts scrolling again.
how can I do this?
this is the script I used for show/hide nav bar:
<script>
const nav = document.querySelector("nav");
const navHeight = 70;
// the point the scroll starts from (in px)
let lastScrollY = 0;
// how far to scroll (in px) before triggering
const delta = 10;
// function to run on scrolling
function scrolled() {
let sy = window.scrollY;
// only trigger if scrolled more than delta
if (Math.abs(lastScrollY - sy) > delta) {
// scroll down -> hide nav bar
if (sy > lastScrollY && sy > navHeight) {
nav.classList.add("nav-up");
}
// scroll up -> show nav bar
else if (sy < lastScrollY) {
nav.classList.remove("nav-up");
}
// update current scroll point
lastScrollY = sy
}
}
// Add event listener & debounce so not constantly checking for scroll
let didScroll = false;
window.addEventListener("scroll", function(e){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
scrolled();
didScroll = false;
}
}, 250)
</script>
what can I add to it so the navbar will automatically hide when the user scrolls up and then stops scrolling?
答案1
得分: 1
<script>
const nav = document.querySelector("nav");
const navHeight = 70;
// 滚动开始的位置(以像素为单位)
let lastScrollY = 0;
// 触发滚动的距离(以像素为单位)
const delta = 10;
// 导航栏隐藏的不活动持续时间(以毫秒为单位)
const hideDelay = 5000; // 5秒
let hideTimeout;
// 隐藏导航栏的函数
function hideNavbar() {
nav.classList.add("nav-up");
}
// 显示导航栏的函数
function showNavbar() {
nav.classList.remove("nav-up");
}
// 滚动时运行的函数
function scrolled() {
let sy = window.scrollY;
// 仅当滚动超过 delta 时触发
if (Math.abs(lastScrollY - sy) > delta) {
// 向下滚动 -> 隐藏导航栏
if (sy > lastScrollY && sy > navHeight) {
hideNavbar();
}
// 向上滚动 -> 显示导航栏
else if (sy < lastScrollY) {
showNavbar();
}
// 更新当前滚动位置
lastScrollY = sy;
// 如果存在先前的超时,则清除它
clearTimeout(hideTimeout);
// 设置新的超时,在指定的不活动持续时间后隐藏导航栏
hideTimeout = setTimeout(hideNavbar, hideDelay);
}
}
// 添加事件侦听器和防抖,以免不断检查滚动
let didScroll = false;
window.addEventListener("scroll", function(e) {
didScroll = true;
});
setInterval(function() {
if (didScroll) {
scrolled();
didScroll = false;
}
}, 250);
</script>
英文:
<script>
const nav = document.querySelector("nav");
const navHeight = 70;
// the point the scroll starts from (in px)
let lastScrollY = 0;
// how far to scroll (in px) before triggering
const delta = 10;
// the duration of inactivity after which the navbar will be hidden (in ms)
const hideDelay = 5000; // 5 seconds
let hideTimeout;
// function to hide the navbar
function hideNavbar() {
nav.classList.add("nav-up");
}
// function to show the navbar
function showNavbar() {
nav.classList.remove("nav-up");
}
// function to run on scrolling
function scrolled() {
let sy = window.scrollY;
// only trigger if scrolled more than delta
if (Math.abs(lastScrollY - sy) > delta) {
// scroll down -> hide nav bar
if (sy > lastScrollY && sy > navHeight) {
hideNavbar();
}
// scroll up -> show nav bar
else if (sy < lastScrollY) {
showNavbar();
}
// update current scroll point
lastScrollY = sy;
// Clear the previous timeout if exists
clearTimeout(hideTimeout);
// Set a new timeout to hide the navbar after the specified duration of inactivity
hideTimeout = setTimeout(hideNavbar, hideDelay);
}
}
// Add event listener & debounce so not constantly checking for scroll
let didScroll = false;
window.addEventListener("scroll", function(e) {
didScroll = true;
});
setInterval(function() {
if (didScroll) {
scrolled();
didScroll = false;
}
}, 250);
</script>
答案2
得分: 1
只需使用一个5000毫秒的setTimeout
函数来隐藏导航栏。然后,使用addEventListener
来在窗口发生滚动事件时重置计时器:
const NAV = document.querySelector('nav');
let timer = null;
window.addEventListener('scroll', function() {
if (timer !== null) {
clearTimeout(timer);
NAV.classList.add('d-block');
}
timer = setTimeout(function() {
NAV.classList.remove('d-block');
}, 5000);
}, false);
nav {
position: sticky;
top: 0;
display: none;
}
.d-block {
display: block;
}
/* 仅用于演示目的 */
body {
min-height: 100000vh;
}
<nav>这是导航栏</nav>
英文:
Simply use a setTimeout
function with a 5000ms timer to hide the navbar. Then use an addEventListener
to reset the timer if a scroll event within the window occurred:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const NAV = document.querySelector('nav');
let timer = null;
window.addEventListener('scroll', function() {
if (timer !== null) {
clearTimeout(timer);
NAV.classList.add('d-block');
}
timer = setTimeout(function() {
NAV.classList.remove('d-block');
}, 5000);
}, false);
<!-- language: lang-css -->
nav {
position: sticky;
top: 0;
display: none;
}
.d-block {
display: block;
}
/* for demonstrationpurpose only */
body {
min-height: 100000vh;
}
<!-- language: lang-html -->
<nav>THIS is the Navbar</nav>
<!-- end snippet -->
答案3
得分: 1
逻辑非常简单:
- 如果距离顶部较远 并且 用户向下滚动,则始终隐藏 nav。
- 如果距离顶部较远 并且 用户向上滚动,则在 5000ms 后隐藏 nav。
根据上述逻辑,当满足以下条件时 nav 将可见:
- 距离顶部较近(滚动 < ~70px 或者 nav 的
clientHeight
) - 立即在向上滚动时
- 如果鼠标悬停在上面(你忘记了这个吗?)
以下是翻译好的代码部分:
const elNav = document.querySelector("#nav");
let lastScrollY = 0;
let scrollTimeout;
const toggleNav = () => {
clearTimeout(scrollTimeout); // 在每次滚动时清除计时器
const isScrollDown = (lastScrollY - scrollY) < 0;
const isDistant = scrollY > elNav.offsetHeight;
lastScrollY = scrollY;
elNav.classList.toggle("nav-up", isDistant && isScrollDown);
if (isDistant && !isScrollDown) {
scrollTimeout = setTimeout(() => {
elNav.classList.add("nav-up");
}, 2000); // 为了加快演示速度,设置为 2000
}
};
// 如果鼠标在上面,防止隐藏 #nav
elNav.addEventListener("mouseenter", () => {
clearTimeout(scrollTimeout);
});
toggleNav(); // 初始化时执行
addEventListener("scroll", toggleNav, {passive: true}); // 滚动时执行
* { margin: 0; }
body { min-height: 300vh; } /* 演示,强制显示滚动条 */
#nav {
position: fixed;
top: 0;
left: 0;
width: 100%;
padding: 2rem;
background: gold;
transition: translate 0.5s;
}
#nav.nav-up {
translate: 0 -100%;
}
<nav id="nav">导航</nav>
英文:
The logic is pretty simple:
- Always hide the nav if:
is distant from top AND user is scrolling down - Hide nav after 5000ms if:
is distant from top AND user is scrolling up
Given the above logic nav will be visible when:
- is near the top (scrolled < ~70px or rather the nav's
clientHeight
) - immediately on a scroll-up
- if mouse is hovering it (you forgot about that one?)
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const elNav = document.querySelector("#nav");
let lastScrollY = 0;
let scrollTimeout;
const toggleNav = () => {
clearTimeout(scrollTimeout); // Clear on every scroll tick
const isScrollDown = (lastScrollY - scrollY) < 0;
const isDistant = scrollY > elNav.offsetHeight;
lastScrollY = scrollY;
elNav.classList.toggle("nav-up", isDistant && isScrollDown);
if (isDistant && !isScrollDown) {
scrollTimeout = setTimeout(() => {
elNav.classList.add("nav-up");
}, 2000); // 2000 just to speed up things in this demo
}
};
// Prevent hiding #nav if mouse is on it
elNav.addEventListener("mouseenter", () => {
clearTimeout(scrollTimeout);
});
toggleNav(); // Do on init
addEventListener("scroll", toggleNav, {passive: true}); // and on scroll
<!-- language: lang-css -->
* { margin: 0; }
body { min-height: 300vh; } /* Demo. To force scrollbars */
#nav {
position: fixed;
top: 0;
left: 0;
width: 100%;
padding: 2rem;
background: gold;
transition: translate 0.5s;
}
#nav.nav-up {
translate: 0 -100%;
}
<!-- language: lang-html -->
<nav id="nav">NAVIGATION</nav>
<!-- end snippet -->
答案4
得分: 0
你可以尝试在用户停止滚动后等待一段时间,然后再隐藏导航栏,可以添加一个计时器来实现:
const nav = document.querySelector("nav");
const navHeight = 70;
let lastScrollY = 0;
const delta = 10;
let didScroll = false;
let hideTimeout;
function scrolled() {
let sy = window.scrollY;
if (Math.abs(lastScrollY - sy) > delta) {
if (sy > lastScrollY && sy > navHeight) {
nav.classList.add("nav-up");
} else if (sy < lastScrollY) {
nav.classList.remove("nav-up");
}
lastScrollY = sy;
resetHideTimeout(); // 每次滚动事件发生时重置计时器
}
}
function resetHideTimeout() {
clearTimeout(hideTimeout);
hideTimeout = setTimeout(() => {
nav.classList.add("nav-up");
}, 5000); // 每5秒钟
}
window.addEventListener("scroll", function(e) {
didScroll = true;
});
setInterval(function() {
if (didScroll) {
scrolled();
didScroll = false;
}
}, 250);
// 页面加载时初始化计时器
resetHideTimeout();
英文:
You can try adding a timer that waits for some time after the user stops scrolling before hiding the navbar again:
<script>
const nav = document.querySelector("nav");
const navHeight = 70;
let lastScrollY = 0;
const delta = 10;
let didScroll = false;
let hideTimeout;
function scrolled() {
let sy = window.scrollY;
if (Math.abs(lastScrollY - sy) > delta) {
if (sy > lastScrollY && sy > navHeight) {
nav.classList.add("nav-up");
} else if (sy < lastScrollY) {
nav.classList.remove("nav-up");
}
lastScrollY = sy;
resetHideTimeout(); // Reset the timer every time there's a scroll event
}
}
function resetHideTimeout() {
clearTimeout(hideTimeout);
hideTimeout = setTimeout(() => {
nav.classList.add("nav-up");
}, 5000); // Every 5 seconds
}
window.addEventListener("scroll", function(e) {
didScroll = true;
});
setInterval(function() {
if (didScroll) {
scrolled();
didScroll = false;
}
}, 250);
// Initial timer setup on page load
resetHideTimeout();
</script>
答案5
得分: -3
以下代码片段可以解决问题。
let element = document.querySelector("#yourElement");
const onScrollStop = callback => {
let isScrolling;
window.addEventListener(
'scroll',
e => {
element.style.display = "unset";
clearTimeout(isScrolling);
isScrolling = setTimeout(() => {
callback();
}, 5000);
},
false
);
};
onScrollStop(() => {
element.style.display = "none";
});
解释:你想要为窗口滚动添加一个事件监听器,设置一个五秒的超时,在执行 onScrollStop 函数之前等待。每当用户滚动时,我们重置超时,因为我们希望等待五秒钟,直到用户停止滚动,而不是在他停止一两秒后立即执行。如果满足条件(5秒内没有滚动),我们执行 onScrollStop 函数,将头部的 display 属性设置为 none,使其消失。每当用户滚动时,我们将头部的 display 属性设置为 unset,使其重新出现。
希望对你有帮助!
愉快编码!
英文:
The following snippet should do the trick.
let element = document.querySelector("#yourElement");
const onScrollStop = callback => {
let isScrolling;
window.addEventListener(
'scroll',
e => {
element.style.display="unset"
clearTimeout(isScrolling);
isScrolling = setTimeout(() => {
callback();
}, 5000);
},
false
);
};
onScrollStop(() => {
element.style.display="none"
});
Explanation: You want to add an eventlistener for scrolling the window, that sets a timeout of five seconds, before executing the onScrollStop function. Every time the user scrolls, we reset the timeout, because we want to wait five seconds, after the user STOPS scrolling, not when he stops for a just one or two seconds. If the condition (no scrolling for 5s) is met, we execute the onScrollStop function, which sets the display property of our header to none, making it disappear. Everytime the user scrolls, we set the header's display property to unset, to make it appear. again.
Hope this helps
Happy coding!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论