平滑滚动的3种实现方式

引言:锚点跳转或者返回页面顶部的时候通常是“嗖”的一下直接滚动到目标位置,缺少动画效果,感觉有点奇怪。这里提供3种滚动实现方式

示例都在vue当中实现

<template>
  <div class="scroll">
    <a href="#bottom"> <div class="tag">这里是a标签</div> </a>
    <div class="placeholder">这里是中间占位元素</div>
    <a name="bottom"> <div class="tag">这里是目标点</div> </a>    
  </div>
</template>
<style >
.scroll .tag {
  height: 100px;
  border: 1px solid #000;
}
.placeholder {
  height: 1000px;
  background: rgb(255, 244, 213);
}
</style>

视图长这样: 

点击a标签会瞬间滚动到底部锚点,于是加几行css代码

1、通过css实现平滑滚动:scroll-behavior: smooth;

<template>
  <div class="scroll">
    <a href="#bottom"> <div class="tag">这里是a标签</div> </a>
    <div class="placeholder">这里是中间占位元素</div>
    <a name="bottom"> <div class="tag">这里是目标点</div> </a>    
  </div>
</template>
<style >
.scroll .tag {
  height: 100px;
  border: 1px solid #000;
}
.placeholder {
  height: 1000px;
  background: rgb(255, 244, 213);
}

/* 加入css代码 */
html,
body {
  scroll-behavior: smooth;
}
</style>

这时候点击a标签就能够平滑滚动了 

2、通过element.scrollIntoView()方法实现

<template>
  <div class="scroll">
    <a href="#bottom"> <div class="tag">这里是a标签</div> </a>
    <!-- 这里绑定点击事件toBottom -->
    <div class="placeholder" @click="toBottom">这里是中间占位元素</div>
    <!-- ref获取元素 -->
    <a name="bottom"> <div class="tag" ref="tagA">这里是目标点</div> </a>
  </div>
</template>

<script>
export default {
  methods: {
    toBottom() {
      this.$refs.tagA.scrollIntoView({ behavior: 'smooth' });// 利用scrollIntoView方法来平滑滚动
    }
  }
};
</script>

<style >
.scroll .tag {
  height: 100px;
  border: 1px solid #000;
}
.placeholder {
  height: 1000px;
  background: rgb(255, 244, 213);
}
</style>

点击中间占位元素就会平滑滚动 

3、原生js 实现

<template>
  <div class="scroll">
    <a href="#bottom"> <div class="tag">这里是a标签</div> </a>
    <!-- 这里绑定点击事件animate-->
    <div class="placeholder" @click="animate">这里是中间占位元素</div>
    <a name="bottom"> <div class="tag">这里是目标点</div> </a>
  </div>
</template>

<script>
export default {
  methods: {
    animate() {
      /**
       * requestAnimationFrame的兼容处理
       * requestAnimationFrame(fn)在每一帧会执行一次fn,类似setTimeout(fn,16.7)
       */
      const requestAnimationFrame =
        window.requestAnimationFrame ||
        function (fn) {
          window.setTimeout(fn, 17); // 浏览器频率是60帧,即1000/60 约等于 17
        };

      const ele = document.body.scrollTop ? document.body : document.documentElement; // 滚动条有可能在body上也有可能在html上
      var scrollTop = ele.scrollTop; // 获取滚动条的位置

      /**
       * 滚动速率
       * rate 越小滚动越快
       */
      const rate = 5;
      const top = function () {
        scrollTop = scrollTop + (0 - scrollTop) / rate; // 缓入动画

        // 临界判断,终止动画
        if (scrollTop <= 1) {
          ele.scrollTop = 0;
          return;
        }
        ele.scrollTop = scrollTop;
        // 递归调用动画
        requestAnimationFrame(top);
      };
      top();
    }
  }
};
</script>

<style >
.scroll .tag {
  height: 100px;
  border: 1px solid #000;
}
.placeholder {
  height: 1000px;
  background: rgb(255, 244, 213);
}
</style>

点击中间元素就会平滑滚动到顶部

requestAnimationFrame是浏览器自带方法,它会在页面刷新下一帧的一瞬间调用,相当于一个定时器settimeout

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值