如何使用Javascript而非jQuery实现窗口的滚动动画?

26

我已经搜索过了,虽然有人用 JavaScript 写了,但是回答都是用 jQuery。不管怎样,我该如何使用 JavaScript 来实现 window.scrollTo 的动画效果?我尝试使用 setInterval 但没有成功。非常感谢您的帮助。

4个回答

70

3
行为 smooth 在 Safari 中不被支持。 - charles okojie
1
@charlesokojie 如果你想的话,可以使用polyfill:https://polyfill.io/v3/polyfill.min.js?features=smoothscroll%2Cwindow.scroll - eozzy
现在已经支持Safari(v14)- 在macOS上使用v17进行了测试。 - undefined

8
尝试这个。
window.scrollTo(0, 0);

我已经使用JavaScript将页面从底部向上滚动。它对我有效。
另一种方法:
HTML
<button onclick="scrollToTop(3000);"></button>

JavaScript
 function scrollToTop(scrollDuration) {
  var scrollStep = -window.scrollY / (scrollDuration / 15),
    scrollInterval = setInterval(function(){
    if ( window.scrollY != 0 ) {
        window.scrollBy( 0, scrollStep );
    }
    else clearInterval(scrollInterval); 
 },15);
}

但那只是跳跃。OP想要动画滚动。 - Rup
@SachinShah 我自己写了代码,使用了 window.scrollTo,但是动画效果有问题。 - user9645391
@SachinShah 我认为它只是到达了顶部,我不需要只往上走,我有不同的值。 - user9645391
@AliBahaari 不同的值意味着传递X和Y的值吗? - Sachin Shah
优雅的解决方案!快速问题:为什么要将 scrollDuration 除以 15?可以称其为“平滑度”因子或变量(以毫秒为单位)吗? - KeshavDulal
显示剩余4条评论

0

我根据@SachinShah的答案为我的自定义需求编写了一个非常漂亮的滚动条。

对某些人可能会有用。

但首先让我告诉你它是做什么的。它可以:

  • 滚动到指定元素的id
  • 按照指定的时间间隔滚动
  • 可以偏移目标。在使用粘性/智能标题时非常方便
  • 控制平滑滚动/setInterval函数的平滑度

请记住:

  • 相对滚动方法window.scrollBy被使用,因此需要在逻辑中确定滚动方向(上/下)
  • scrollDuration和scrollSmoothness以毫秒为单位
/**
 * Scroll to the top of the page in a specified duration(ms) and smoothness(ms)
 * ref: https://dev59.com/j1QK5IYBdhLWcg3wF8F6#52478645
 * @param {String} elementID
 * @param {Int} scrollDuration
 * @param {Int} offset
 * @param {Int} scrollSmoothness
 */

const fancyAScroll = (
  elementID = 'main-content',
  scrollDuration = 500,
  offset = 0, // I  had to use 120 to compensate for a sticky header
  scrollSmoothness = 10
) => {
  const accuracyBuffer = 10
  try {

    // #1 Calculate the final offset position to scroll-to
    const element = document?.getElementById(elementID)
    const bodyRect = document?.body?.getBoundingClientRect().top
    const elementRect = element?.getBoundingClientRect().top
    const elementPosition = elementRect - bodyRect
    const offsetPosition = elementPosition - offset // final - target position to scroll

    // #2 calculate steps & direction (up or down)
    const scrollStepUnit = offsetPosition / (scrollDuration / scrollSmoothness)
    const scrollStepDirection = offsetPosition > window?.scrollY ? '' : '-'
    const scrollStepY = `${scrollStepDirection}${scrollStepUnit}`

    // #3 keep on relatively scrolling untill reached to the destination
    const scrollInterval = setInterval(() => {
      let targetRangeReached =
        offsetPosition - accuracyBuffer < window.scrollY &&
        window.scrollY < offsetPosition + accuracyBuffer

      targetRangeReached ? clearInterval(scrollInterval) : window.scrollBy(0, scrollStepY)
    }, scrollSmoothness)
  }
  catch (error) {
    console.error('Error @scrollTopWithDuration\n', error)
  }
}

export default fancyAScroll


window.scrollIntoView也基本上是一样的,但没有持续时间的自定义选项。 - KeshavDulal

0

这种方法对我有效:

function slideTo(id) {
    var element = document.getElementById(id);
    document.body.scrollTo({
        top: element.offsetTop,
        behavior: 'smooth'
    });
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接