慢慢的滑着,前往指定节点

3,782 阅读3分钟

滑动难点

其实滑动本身不难,难在不知道元素DOM上挂载的对象的属性是什么意思:

刨析难点

慢慢解开、滑动的密码

DOM对象

  • scrollTop:滑动条滑动的高度
  • clientHeight :可视窗口的高度
  • scrollHeight:文档的高度 说起来很抽象,那我就简单作画理解一下,请见谅 ZUFCI9NTD6D.png

获取需要的DOM对象

下面介绍一下获取的方法,心里想怎么会那么多?因为需要兼容与容错。😊

scrollTop

获取滑动栏的高度

  let scrollTop =
      window.pageYOffset ||
      document.body.scrollTop ||
      document.documentElement.scrollTop;

clientHeight

获取可视窗口的高度

let clientHeight = 
    document.body.clientHeight || 
    document.documentElement.clientHeight;

scrollHeight

获取文档的高度

let scrollHeight = 
    document.body.scrollHeight || 
    document.documentElement.scrollHeight;

获取节点信息

选种节点就能获取到节点的相关对象信息,我们取一些有用的信息

  • offsetTop | offset().top:获取节点到文档顶部的距离,不论你套多少层。
  • getBoundingClientRect().top:动态的获取节点到视窗顶端的距离。 还是很抽象,那我再开一副画

节点信息

开始分析问题

第一种:可以滑动指定地点 zhujiao.offsetTop = scrollTop,也就是getBoundingClientRect().top为零的时候。

第二种:页面高度不足,滑不到指定地点已经触底了 scrollHeight = clientHeight + scrollTop ;

不论以上两种,哪一种不符合,都需要清理收尾,结束迭代调用函数。

当然不可能使其两边完全的相等,因为动态的滑动,是需要计算的,下面就明白为什么了。

滑动JS代码

简单的滑动JS代码,只能从上到下使用

var stopTimerId = null;
function scrollToNode(speed){
  //获取猪脚的DOM元素
  let zhujiao = document.querySelector(".YBlockPink");
  // 获取滑动栏的高度
  let scrollTop =
      window.pageYOffset ||
      document.body.scrollTop ||
      document.documentElement.scrollTop;
  //获取可视窗口的高度
  let clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
  //获取文档的高度
  let scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight; 
  //获取猪脚的到视窗顶部的距离
  let surplus = zhujiao.offsetTop - scrollTop;
  if(  surplus > 0 && scrollHeight > clientHeight + scrollTop){
    if(surplus > 100){
      window.scrollBy(0,speed);
    }else{
      window.scrollBy(0,speed/5); //减速5倍,speed就慢了下了,也就越精确
    }
    // 符合条件运行函数
    this.stopTimerId = setTimeout(()=>{
      this.scrollToNode(speed);
    },16)
  }else{
    window.alert("停止迭代");
    clearTimeout(stopTimerId);
  }
}

![滑动动画.gif](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2b6679cf7af34d6d98436a5b055b6ae8~tplv-k3u1fbpfcp-watermark.image?)
scrollToNode(50);

使用函数式的只能从上到下使用

var stopTimerId = null;
var preSurplus = 0 ;
function funScrollToNode(speed){
   //获取猪脚的到文档顶部的高度
   let zhujiao = document.querySelector(".YBlockPink");
   let surplus = zhujiao.getBoundingClientRect().top;
   //上次的距离与这次的相同就清除时间ID,结束循环 也可以把上面那个写的触底拿来使用
    if(surplus > 0 && preSurplus !== surplus){
       // 符合条件运行函数
       if(surplus > 100){
        window.scrollBy(0,speed);
      }else{
        window.scrollBy(0,speed/2); //减速2倍,自定义你最近的想法
      }
      this.stopTimerId = setTimeout(()=>{
        this.funScrollToNode(speed)
      },16)
      preSurplus = surplus;
    }else{
      window.alert("停止迭代");
      clearTimeout(stopTimerId);
    }
}

总结:speed的处理上,自己看着使用,surplus > 100也是本人随意写的。迭代的减速也是自己瞎写的,总体逻辑就这么多了

任何位置点击即到

滑动动画.gif 关键代码如下

var stopTimerId = null;
var preSurplus = 0 ;
function funScrollToNode(speed,zhujiao){
   //获取猪脚的到文档顶部的高度
   let surplus = zhujiao.getBoundingClientRect().top;
   let signSpeed = surplus > 0 ? speed : -speed ;
   // 再 5 的区间内 停止
    if(Math.abs(surplus) > 0.05 && preSurplus !== surplus){
       // 符合条件运行函数
       if(Math.abs(surplus) > 30){
        signSpeed = signSpeed;
      }else{
        signSpeed = signSpeed/2; //速度迭代式一直除2
      }
      window.scrollBy(0,signSpeed);
      speed = Math.abs(signSpeed);
      this.stopTimerId = setTimeout(()=>{
        this.funScrollToNode(speed,zhujiao)
      },16)
      preSurplus = surplus;
    }else{
      window.alert("停止迭代")
      clearTimeout(stopTimerId)
    }
}

点击使用预览

总结

里面的常量可以自己测试,修改认为合适,再进行使用