JS - 设配设备的的平滑滚动

最近项目需要做一个H5页面的问答类互动,类似向上向下的滚动效果,所以做个总结

一、 CSS

使用CSS的scroll-behavior,可以达到比较平滑的滚动,有过渡效果

scroll-behavior: auto | smooth | inherit | unset
// html
<div id="box">
    <p id="container">Hello, Backtotop</p>
    <br/>
    <p>Hello, Backtotop</p>
    <br/>
    <p>Hello, Backtotop</p>
    <br/>
    <p>Hello, Backtotop</p>
    <br/>
 </div>
 <a href="#container" >回到顶部按钮</a>
 // css
 #box {
     height: 150px;
     overflow: scroll;
     scroll-behavior: smooth;
 }

这种方法虽然可以平滑滚动到顶部,但是因为a标签的默认行为会给地址加一个hash,这对路由使用hash模式来说会出现问题。

二、ScrollTo
回到顶部
target.clientHeight
// html
<div id="box">
    <p id="container">Hello, Backtotop</p>
    <br/>
    <p>Hello, Backtotop</p>
    <br/>
    <p>Hello, Backtotop</p>
    <br/>
    <p>Hello, Backtotop</p>
    <br/>
 </div>
<a onclick="up()" href="#">回到顶部按钮</a>
 // css
 #box {
     height: 150px;
     overflow: scroll;
     scroll-behavior: smooth;
 }
// js
function up() {
     const target = document.getElementById("box");
     target.scrollTo(0, 0);
 }
回到底部

DOM元素的高度,减去我们视窗的高度,就是底部了

window.scrollTo(0, document.documentElement.scrollHeight - window.innerHeight);
 function down() {
     const target = document.getElementById("box");
     target.scrollTo(0, target.scrollHeight - target.clientHeight);
 }
设备支持情况
  • iOS 13.3 Safari 不支持smooth
  • iOS 11.4.1 Safari 不支持smooth
  • Galaxy S9 Android 9.0 自带浏览器 支持smooth
  • Chrome 79 支持smooth
三、ScrollIntoView
element.scrollIntoView(); // 等同于element.scrollIntoView(true) 
element.scrollIntoView(alignToTop); // Boolean型参数 
element.scrollIntoView(scrollIntoViewOptions); // Object型参数
// html
<div id="box">
    <p id="top">Hello, Backtotop</p>
    <br/>
    <p>Hello, Backtotop1</p>
    <br/>
    <p>Hello, Backtotop2</p>
    <br/>
    <p>Hello, Backtotop3</p>
    <br/>
    <p>Hello, Backtotop4</p>
    <br/>
    <p id="bottom">Hello, Backtotop5</p>
    <br/>
  </div>
  <a onclick="up()" href="#">回到顶部按钮</a>
  <a onclick="down()" href="#">回到底部按钮</a>
function up() {
   const target = document.getElementById("top");
   target.scrollIntoView(false);
}
function down() {
   const target = document.getElementById("bottom");
   target.scrollIntoView(true);
}
设备支持情况
  • iOS 13.3 Safari 不支持smooth
  • iOS 11.4.1 Safari 不支持smooth
  • Galaxy S9 Android 9.0 自带浏览器 支持smooth
  • Chrome 79 支持smooth
四、多设备支持的滚动

以上的方法,安卓大部分都是可用的,IOS虽然也是可以滚动,但是却不支持options,所以无法缓慢滚动,都是一下子滚到底,所以为了让安卓和IOS都能够缓慢滚动,需要有一个兼容性的滚动方案

  function scrollTopSmooth(position, sumTime = 45, target) {
    // 不存在原生`requestAnimationFrame`,用`setTimeout`模拟替代
    if (!window.requestAnimationFrame) {
      window.requestAnimationFrame = function(cb) {
        return setTimeout(cb, 20)
      }
    }
    // 当前滚动高度
    let scrollTop = target
      ? target.scrollTop
      : document.documentElement.scrollTop || document.body.scrollTop
    // 当前滚动对象
    let scrollTarget = target || window
    // sumTime 控制滚动速率, scrollTime做判断
    let scrollTime = sumTime
    // step
    function step() {
      let distance = position - scrollTop
      scrollTime--
      scrollTop = scrollTop + distance / sumTime

      if (!scrollTime) {
        scrollTarget.scrollTo(0, position)
      } else {
        scrollTarget.scrollTo(0, scrollTop)
        requestAnimationFrame(step)
      }
    }
    step()
  }
补充
  1. document.documentElement.scrollTop与document.body.scrollTop

    document.documentElement表示获取到html,document.body表示获取到body。使用document.body.scrollTop获取不到页面滚动的距离,就必须使用document.documentElement.scrollTop来获取。所以一般我们获取滚动距离的兼容代码最好写成这样

    let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
    
  2. 关于绑定滚动事件scroll

    只有window和document两个能绑定scroll滚动事件,document.documentElement和document.body绑定不起,这个应该跟浏览器内核有关系。

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

参考链接
通过图片懒加载引出来的知识点
平滑滚动到顶部或底部的几种方案
完美实现一个“回到顶部”

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值