我需要完成什么:
我的网站由多个部分组成,每个部分占据整个页面。当用户尝试向下滚动时,我想要完成的是:
- 在滚动达到一定速度阈值之前,页面根本不会移动。
- 当滚动达到阈值时向下滚动整个页面。
示例网站:
我尝试过的:
- CSS
scroll-snap-align
:此方法仅在用户停止滚动后捕捉滚动。
示例代码:
<div id="app">
<section id="page1">Page 1 Content</section>
<section id="page2">Page 2 Content</section>
</div>
#app
{
height: 100vh;
}
section
{
position: relative;
width: 100%;
height: 100%;
}
最佳答案
这里首先要注意的是,scroll
事件无法取消。因此,只能通过在 wheel
或 mousewheel
事件上附加事件监听器来完成(如果还需要触摸屏支持,则为 touchmove
)。
通过使用这些,我能够想出这个。这里的想法是维护一个计数器,它将在每个wheel
事件上增加/减少其值。如果计数器达到某个阈值,就会触发滚动功能。停止鼠标滚轮后,计数器将重置回 0、N 毫秒。
因此,为了触发滚动功能,必须在N毫秒的时间限制内转动鼠标滚轮一定次数才能达到阈值。
这种方法的缺点是 body
元素被赋予了 overflow:hidden
属性来隐藏滚动条。否则,用户将无法滚动页面而达不到预期的效果。如果这不是问题,则可以删除 overflow
属性。
此外,本示例中未处理 touchmove
事件,但其实现也类似。
$(document).ready(function() {
const COUNTER_THRESHOLD = 5; // Change this to decrease/increase senstivity
const COUNTER_RESET_DURATION = 400;
let animating = false;
let counter = 0;
function resetDelta() {
counter = 0
}
let deboucncedReset = debounce(resetDelta, COUNTER_RESET_DURATION);
function handleScroll(event) {
//event.wheelDelta can be positive or negative based on the direction of scroll
counter += 1 * (Math.sign(event.wheelDelta));
//Scroll down if value of counter is negative and absolute value is greater than threshold
if (!animating && (Math.abs(counter) >= COUNTER_THRESHOLD) && counter < 0) {
let targetSection = $('section.active').next('section');
if (targetSection.length) {
scrollToSection(targetSection);
}
}
//Scroll up if value of counter is positive and absolute value is greater than threshold
else if (!animating && (Math.abs(counter) >= COUNTER_THRESHOLD) && counter > 0) {
let targetSection = $('section.active').prev('section');
if (targetSection.length) {
scrollToSection(targetSection);
}
}
// prevent default scrolling behaviour of mouse wheel
event.preventDefault()
//Reset counter to 0 , 400 miliseconds after stopping the mousewheel
deboucncedReset()
}
function scrollToSection(target) {
animating = true;
$('html, body').animate({
scrollTop: target.offset().top
}, 800, function() {
animating = false;
$('section.active').removeClass('active');
target.addClass('active');
});
}
function debounce(func, delay) {
let debounceTimer
return function() {
const context = this
const args = arguments
clearTimeout(debounceTimer)
debounceTimer
= setTimeout(() => func.apply(context, args), delay)
}
}
//Test support for passive listeners
let supportsPassive = false;
try {
let options = Object.defineProperty({}, 'passive', {
get: function() {
supportsPassive = true;
}
});
window.addEventListener("testPassive", null, options);
window.removeEventListener("testPassive", null, options);
} catch (e) {}
let wheelOptions = supportsPassive ? {
passive: false
} : false;
// Older browsers used 'mousewheel' event
let wheelEvent = 'onwheel' in document.createElement('div') ? 'wheel' : 'mousewheel';
document.addEventListener(wheelEvent, handleScroll, wheelOptions);
});
body {
overflow: hidden;
}
#app {
height: 100vh;
}
section {
position: relative;
width: 100%;
height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="app">
<section id="page1" class="active">
<h2>Section 1</h2>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolores sequi quaerat officia non sunt sit, assumenda ullam itaque eos natus sed, aliquam adipisci consectetur nemo eum a reprehenderit fuga, ut consequatur beatae tenetur debitis. Officiis,
quod vitae sapiente tempore odit, quas nemo minus cupiditate laboriosam et cum accusantium porro quam hic soluta? Blanditiis assumenda suscipit accusamus laborum modi, cumque consequatur velit asperiores eius consectetur deserunt fugiat aperiam
recusandae quibusdam, dolore alias doloribus ut quis, voluptatem dolorum dolores harum unde magni. Commodi ducimus distinctio, quos ipsa, itaque illo nostrum laboriosam corporis sunt ad perferendis laborum ut natus magni dolore unde asperiores!</p>
</section>
<section id="page2">
<h2>Section 2</h2>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Repellendus, consequuntur enim ab dolorem rem, animi voluptates ipsam sequi nisi, dolores quod. Unde molestias facere autem nam error laboriosam eum nisi! Placeat voluptatum voluptate aspernatur.
Laboriosam nulla eaque culpa corporis consequuntur suscipit temporibus sed, totam, quia sit aut beatae sunt nihil ducimus fugit dolorum inventore minus dolorem modi eius! Aliquid distinctio sed dolorem? Quos ipsum optio fugit asperiores eligendi
vitae saepe nostrum. Eius minus recusandae quaerat. Fuga inventore temporibus doloremque sequi officia voluptatibus explicabo ad? Distinctio molestiae cupiditate obcaecati eum consequatur, error, illo quidem, maxime expedita veniam assumenda alias
culpa laudantium!</p>
</section>
</div>
为了使其功能齐全,还需要处理箭头键和空格键。但这应该是一件相对容易处理的事情。
关于javascript - HTML - 如何滚动整个部分而不在中间停止?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63144144/