Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

平滑滚动到顶部或底部的几种方案 #32

Open
cookiepool opened this issue Jan 9, 2020 · 0 comments
Open

平滑滚动到顶部或底部的几种方案 #32

cookiepool opened this issue Jan 9, 2020 · 0 comments
Labels
前端相关 前端相关

Comments

@cookiepool
Copy link
Owner

开始

最近项目在做列表展示相关的需求,要求有滚动到顶部和底部的快捷按钮,在参考过社区的一些文章后,写下这篇文章,供大家参考!

很多时候我们使用的滚动效果都是类似于锚点那种,一闪而过,给人的体验十分不友好。所以这里介绍一些平滑滚动的方式。

使用CSS的scroll-behavior

scroll-behavior: auto | smooth | inherit | unset

一般我们使用auto和smooth就可以了,smooth表示滚动很平滑,有过渡效果,auto没有过渡效果,一闪而过。

我们一般回到顶部的话把这个属性设置在html上即可。代码如下

<div id="container" class="box">
  <p>Hello, Backtotop</p>
  <br/>
  <p>Hello, Backtotop</p>
  <br/>
  <p>Hello, Backtotop</p>
  <br/>
  <p>Hello, Backtotop</p>
  <br/>
  /* 省略部分代码 */
</div>
<a href="#container" class="backto-top-btn">回到顶部按钮</a>

css样式代码:

html {
  scroll-behavior: smooth;
}

注意:上面那个我用的a标检加id,这种可能不太好,因为a标签的默认行为会给地址加一个hash,这对vue的路由使用hash模式来说会出现问题。

更简单的方法

  • 回到顶部
    上面a标签的默认行为会出问题,我们可以使用更简便的方式来实现,首先在你的页面的给html加一个样式:
html {
  scroll-behavior: smooth;
}

给你的回到顶部的按钮绑定一个事件,比如点击事件,里面加入我们平时使用的回到顶部的代码

window.scrollTo(0, 0);

然后这样的话,只要你的设备及浏览器支持这个CSS属性的话,那么也会有过渡平滑的效果。

  • 回到底部
    回到底部可以这样操作,我们计算出DOM元素的高度,减去我们视窗的高度,那么就是底部了
window.scrollTo(0, document.documentElement.scrollHeight - window.innerHeight);

手头设备支持情况

  • iOS 13.3 Safari 不支持smooth
  • iOS 11.4.1 Safari 不支持smooth
  • Galaxy S9 Android 9.0 自带浏览器 支持smooth
  • Chrome 79 支持smooth

使用JS的Element.scrollIntoView()

element.scrollIntoView(); // 等同于element.scrollIntoView(true) 
element.scrollIntoView(alignToTop); // Boolean型参数 
element.scrollIntoView(scrollIntoViewOptions); // Object型参数

这个是浏览器自带的滚动函数,目前也是属于新功能,可能很多设备及浏览器不支持。这里贴一张MDN的参数解释

这个感觉用起来比CSS还要简单些,给你要滚动的DOM元素绑定这个函数即可

// 滚动到顶部
this.$refs.container.scrollIntoView(true);

// 滚动到底部
this.$refs.container.scrollIntoView(false);

手头设备支持情况

  • iOS 13.3 Safari 不支持smooth
  • iOS 11.4.1 Safari 不支持smooth
  • Galaxy S9 Android 9.0 自带浏览器 支持smooth
  • Chrome 79 支持smooth

多设备支持的缓冲方案

// 封装一个回到底部或者顶部的函数
scrollToTop(position) {
  // 使用requestAnimationFrame,如果没有则使用setTimeOut
  if(!window.requestAnimationFrame) {
    window.requestAnimationFrame = function(callback) {
      return setTimeout(callback, 20)
    }
  }

  // 获取当前元素滚动的距离
  let scrollTopDistance = document.documentElement.scrollTop || document.body.scrollTop;

  function smoothScroll() {
    // 如果你要滚到顶部,那么position传过来的就是0,下面这个distance肯定就是负值。
    let distance = position - scrollTopDistance;
    // 每次滚动的距离要不一样,制造一个缓冲效果
    scrollTopDistance = scrollTopDistance + distance / 5;
    // 判断条件
    if(Math.abs(distance) < 1) {
      window.scrollTo(0, position);
    }else {
      window.scrollTo(0, scrollTopDistance);
      requestAnimationFrame(smoothScroll);
    }
  }

  smoothScroll();

调用这个函数

// 回到顶部
scrollToTop(0);

// 滚到底部
scrollToTop(document.documentElement.scrollHeight - window.innerHeight);

这里给出一下效果展示


手头设备支持情况

  • iOS 13.3 Safari 支持
  • iOS 11.4.1 Safari 支持
  • Galaxy S9 Android 9.0 自带浏览器 支持
  • Chrome 79 支持

参考资料

链接地址

感谢上面这位大佬的文章!

@cookiepool cookiepool added the 前端相关 前端相关 label Jan 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
前端相关 前端相关
Projects
None yet
Development

No branches or pull requests

1 participant