我想用scrollTo
实现平滑滚动。如果我使用scrollIntoView({ behavior: 'smooth' }
选项,我无法控制速度。因此我使用performance.now()
和requestAnimationFrame
的组合来实现效果。
它在鼠标轮事件上工作得很好,问题是我有三个按钮,当我点击时它应该转到相对部分。但是它对按钮不起作用。
鼠标滚轮事件使用window.scrollTo(0, startY + distance * progress);
,而按钮使用window.scrollTo(0, manualPosition * progress);
,其中manualPosition
是lis[index].getBoundingClientRect().top
的部分位置。
请尝试运行代码并点击按钮,或使用鼠标滚轮查看效果。
(function () {
const lis = document.querySelectorAll('.section'),
btnsNav = document.querySelectorAll('.button'),
speed = 500;
let currentSection = 0,
isScrolling = false;
function smoothScrollTo(time, direction, mode = 'auto', index = 1) {
if (isScrolling) {
return;
}
isScrolling = true;
const start = performance.now(),
startY = window.scrollY,
distance =
direction === 'up' ? -window.innerHeight : window.innerHeight;
function animateScroll() {
const now = performance.now(),
elapsed = now - start,
progress = elapsed / time,
manualPosition = lis[index].getBoundingClientRect().top;
if (mode === 'auto') {
window.scrollTo(0, startY + distance * progress);
} else if (mode === 'manual') {
window.scrollTo(0, manualPosition * progress);
}
if (elapsed < time) {
requestAnimationFrame(animateScroll);
} else {
isScrolling = false;
}
}
requestAnimationFrame(animateScroll);
if (direction === 'down') {
currentSection++;
} else if (direction === 'up') {
currentSection--;
}
}
document.addEventListener('wheel', function (event) {
if (event.deltaY > 0 && currentSection < lis.length - 1) {
smoothScrollTo(speed, 'down');
} else if (event.deltaY < 0 && currentSection > 0) {
smoothScrollTo(speed, 'up');
}
});
for (let index = 0; index < btnsNav.length; index++) {
btnsNav[index].addEventListener('click', function () {
smoothScrollTo(speed, 'down', 'manual', index);
});
}
})();
body {
margin: 0;
}
#div {
position: fixed;
top: 0;
left: 0;
display: flex;
column-gap: 10px;
}
.section {
height: 100vh;
width: 100%;
}
.section:nth-of-type(1) {
background-color: red;
}
.section:nth-of-type(2) {
background-color: yellow;
}
.section:nth-of-type(3) {
background-color: green;
}
<div id="div">
<button class="button" type="button">Go to 1</button>
<button class="button" type="button">Go to 2</button>
<button class="button" type="button">Go to 3</button>
</div>
<section class="section"></section>
<section class="section"></section>
<section class="section"></section>
2条答案
按热度按时间9gm1akwq1#
代码中的问题
我在你的代码中发现了两个问题,
.button
字符串
1.在for循环中调用
smoothScrollTo
函数时,将manual
作为mode
传递。将mode作为auto传递似乎可以解决这个问题。型
注意:还有一些逻辑上需要更多的变化,我会离开你来修复,因为我已经能够向下进入所需的页面,但按钮点击不带我们向上到页面.干杯!
**提示:**在for循环中传递给
smoothScrollTo
的方向总是向下的。而不是使用'up'/'down'我会使用currentSection
和正在传递的索引来标识是向上滚动还是向下滚动。请忽略逻辑;)修复代码:
lskq00tm2#
实际上,你可以在没有任何JavaScript的情况下实现这种效果-这是可能的HTML + CSS。
有三个步骤:
1.将
scroll-behavior: smooth
应用于文档根(即<html>
元素):字符串
1.用hashfragment链接包围每个按钮:
型
1.将对应的
id
添加到每个.section
,以指示散列片段链接的目的地:型
示例: