我有一个简单的页面,我将在右侧放置一个大表单,在左侧放置一个导航菜单,允许用户跳转到大表单的各个部分(这也可以用于大文章) - 现在为了模拟尺寸,我用 CSS 添加了一个大的底部填充)。右列的样式已使用 height: 100vh 设置为适合窗口的高度。
当单击右侧的链接并且部分 offsetTop
大于其父级的 scrollTop
时,滚动是平滑的。我使用 JavaScript setTimeout
并使用循环设置超时间隔...这太棒了!但是,我是否应该向上滚动,因为该部分的 offsetTop 小于其父级的 scrollTop
我遇到了问题 - 它很慢,很慢并且没有真正工作......我一直在看这个太久了,所以如果有人可以提供帮助,我将不胜感激。这是我的 JavaScript 函数
function scrollToAchor(where, event) {
event.stopPropagation();
var element = document.querySelector('.aims-form__form').querySelector('a[name="' + where + '"]');
var to = element.offsetTop - 30;
var from = document.querySelector('.aims-form__form').scrollTop
let timeOut = 0;
if(to >= from) {
for(let i = from; i <= to; i+=5) {
// this works and is great!!!
setTimeout(function () {
document.querySelector('.aims-form__form').scrollTop = i;
}, i/2);
}
} else {
for(let k = from; k >= to; k-=5) {
// I need to set the timeout Interval so the animation is smooth but it is really slow
// with the above setInterval above we are counting up... How do I get this smooth
timeOut = timeOut + (to + 15) / 2;
setTimeout(function () {
document.querySelector('.aims-form__form').scrollTop = i;
}, timeOut);
}
}
}
这不应该让我陷入困境,但我无法理解它,现在我有一个精神障碍。要更好地理解滚动功能,请参阅 HTML,但要获得完整图片(包括必要的 CSS),请参阅完整内容的 jsbin https://jsbin.com/nidevaj/edit?html,css,js,output
<div class="aims-form">
<div class="aims-form__navigation">
<ul>
<li>
<a onClick="scrollToAchor('section1', event)" class="aims-form__anchor">Section 1</a>
</li>
<li>
<a onClick="scrollToAchor('section2', event)" class="aims-form__anchor">Section 2</a>
</li>
<li>
<a onClick="scrollToAchor('section3', event)" class="aims-form__anchor">Section 3</a>
</li>
<li>
<a onClick="scrollToAchor('section4', event)" class="aims-form__anchor">Section 4</a>
</li>
</ul>
</div>
<div class="aims-form__form">
<section>
<a name="section1"></a>
Section 1
<br>
... content lots of content
</section>
<section>
<a name="section2"></a>
Section 2
<br>
... content lots of content
</section>
<section>
<a name="section3"></a>
Section 3
<br>
... content lots of content
</section>
<section>
<a name="section4"></a>
Section 4
<br>
... content lots of content
</section>
</div>
</div>
最佳答案
您可以将 CSS 属性 scroll-behavior
设置为 smooth
(大多数现代浏览器都支持),这样就不再需要 Javascript。只需给 anchor 标记一个 #
的 href
加上要滚动到的 anchor 标记的 name
并允许正常滚动发生,除了很多更流畅。
section{
margin: 500px 0px;
}
html, body{
scroll-behavior: smooth;
}
<div class="aims-form">
<div class="aims-form__navigation">
<ul>
<li>
<a href="#section1">Section 1</a>
</li>
<li>
<a href="#section2">Section 2</a>
</li>
<li>
<a href="#section3">Section 3</a>
</li>
<li>
<a href="#section4">Section 4</a>
</li>
</ul>
</div>
<div class="aims-form__form">
<section>
<a name="section1"></a>
Section 1
<br>
... content lots of content
</section>
<section>
<a name="section2"></a>
Section 2
<br>
... content lots of content
</section>
<section>
<a name="section3"></a>
Section 3
<br>
... content lots of content
</section>
<section>
<a name="section4"></a>
Section 4
<br>
... content lots of content
</section>
</div>
</div>
如果你想使用 Javascript,你可以使用 for
循环与 window.scrollTo
和 setTimeout
以及 setInterval
用于平滑滚动。我为此写了一个函数。要滚动到某个元素,请提供该元素的 offsetTop
作为 pos
参数。
function scrollToSmoothly(pos, time) {
if (isNaN(pos)) {
throw "Position must be a number";
}
if (pos < 0) {
throw "Position can not be negative";
}
var currentPos = window.scrollY || window.screenTop;
if (currentPos < pos) {
var t = 10;
for (let i = currentPos; i <= pos; i += 10) {
t += 10;
setTimeout(function() {
window.scrollTo(0, i);
}, t / 2);
}
} else {
time = time || 2;
var i = currentPos;
var x;
x = setInterval(function() {
window.scrollTo(0, i);
i -= 10;
if (i <= pos) {
clearInterval(x);
}
}, time);
}
}
section{
margin: 500px 0px;
}
<div class="aims-form">
<div class="aims-form__navigation">
<ul>
<li>
<a onClick="scrollToAchor('section1', event)" class="aims-form__anchor">Section 1</a>
</li>
<li>
<a onClick="scrollToAchor('section2', event)" class="aims-form__anchor">Section 2</a>
</li>
<li>
<a onClick="scrollToAchor('section3', event)" class="aims-form__anchor">Section 3</a>
</li>
<li>
<a onClick="scrollToAchor('section4', event)" class="aims-form__anchor">Section 4</a>
</li>
</ul>
</div>
<div class="aims-form__form">
<section>
<a name="section1"></a>
Section 1
<br>
... content lots of content
</section>
<section>
<a name="section2"></a>
Section 2
<br>
... content lots of content
</section>
<section>
<a name="section3"></a>
Section 3
<br>
... content lots of content
</section>
<section>
<a name="section4"></a>
Section 4
<br>
... content lots of content
<button onClick="scrollToTop()">
Back To Top
</button>
</section>
</div>
</div>
<script>
function scrollToSmoothly(pos, time) {
if (isNaN(pos)) {
throw "Position must be a number";
}
if (pos < 0) {
throw "Position can not be negative";
}
var currentPos = window.scrollY || window.screenTop;
if (currentPos < pos) {
var t = 10;
for (let i = currentPos; i <= pos; i += 10) {
t += 10;
setTimeout(function() {
window.scrollTo(0, i);
}, t / 2);
}
} else {
time = time || 2;
var i = currentPos;
var x;
x = setInterval(function() {
window.scrollTo(0, i);
i -= 10;
if (i <= pos) {
clearInterval(x);
}
}, time);
}
}
function scrollToAchor(where, event) {
event.stopPropagation();
var element = document.querySelector('.aims-form__form').querySelector('a[name="' + where + '"]');
scrollToSmoothly(element.offsetTop);
}
function scrollToTop(){
scrollToSmoothly(0);
}
</script>
如果你想让div
的内容平滑滚动,可以使用上面的函数,把window.scrollTo
换成elem.scrollTop
并传入元素的 offsetTop
作为 pos
以滚动到元素。
section{
margin: 500px 0px;
}
<div style="border: 1px solid black; margin: auto; height: 250px; width: 50%; overflow-y: auto;" id="parent">
<div class="aims-form">
<div class="aims-form__navigation">
<ul>
<li>
<a onClick="scrollToAnchor('section1', event)" class="aims-form__anchor">Section 1</a>
</li>
<li>
<a onClick="scrollToAnchor('section2', event)" class="aims-form__anchor">Section 2</a>
</li>
<li>
<a onClick="scrollToAnchor('section3', event)" class="aims-form__anchor">Section 3</a>
</li>
<li>
<a onClick="scrollToAnchor('section4', event)" class="aims-form__anchor">Section 4</a>
</li>
</ul>
</div>
<div class="aims-form__form">
<section>
<a name="section1"></a>
Section 1
<br>
... content lots of content
</section>
<section>
<a name="section2"></a>
Section 2
<br>
... content lots of content
</section>
<section>
<a name="section3"></a>
Section 3
<br>
... content lots of content
</section>
<section>
<a name="section4"></a>
Section 4
<br>
... content lots of content
<p/>
<button onClick="scrollToTopOfDiv()">
Back To Top
</button>
</section>
</div>
</div>
</div>
<script>
function scrollToSmoothlyInsideElement(elem, pos, time) {
if (isNaN(pos)) {
throw "Position must be a number";
}
if (pos < 0) {
throw "Position can not be negative";
}
var currentPos = elem.scrollTop;
if (currentPos < pos) {
var t = 10;
for (let i = currentPos; i <= pos; i += 10) {
t += 10;
setTimeout(function() {
elem.scrollTop = i;
}, t / 2);
}
} else {
time = time || 2;
var i = currentPos;
var x;
x = setInterval(function() {
elem.scrollTop = i;
i -= 10;
if (i <= pos) {
clearInterval(x);
}
}, time);
}
}
function scrollToAnchor(where, event){
event.stopPropagation();
var element = document.querySelector('.aims-form__form').querySelector('a[name="' + where + '"]');
var parent = document.querySelector('#parent');
scrollToSmoothlyInsideElement(parent, element.offsetTop);
}
function scrollToTopOfDiv(){
var elem = document.querySelector('#parent');
scrollToSmoothlyInsideElement(elem, 0);
}
</script>
有关平滑滚动的更全面的方法列表,请参阅我的回答 here .
关于javascript - 使用 JavaScript 向下滚动 div 时平滑滚动,向上滚动时卡顿且缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51693706/