原生JS监听楼层,封装动画等

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    div:nth-child(1) {
      background-color: #ccc;
    }
    div:nth-child(6) {
      background-color: blue;
    }
    div:nth-child(3) {
      background-color: pink;
    }
    div:nth-child(4) {
      background-color: yellow;
    }
    div:nth-child(5) {
      background-color: #58d7ed;
    }
    #wrap {
      width: 100%;
      height: 60px;
      list-style: none;
      background-color: orange;
      position: relative;
      z-index: 999;
    }
    #wrap li:first-child {
      margin-left: 120px;
    }
    #wrap li {
      float: left;
      width: 40px;
      height: 100%;
      line-height: 60px;
      margin: 0 20px;
      text-align: center;
    }
    #wrap a {
      text-decoration: none;
      color: #111;
    }
    #line {
      width: 40px;
      background-color: green;
      height: 3px;
      position: absolute;
      left: 120px;
      bottom: 0px;
      display: none;
    }
  </style>
</head>
<body>
  <div>index</div>
    <ul id="wrap">
      <li><a href="javascript:void(0)">1</a></li>
      <li><a href="javascript:void(0)">2</a></li>
      <li><a href="javascript:void(0)">3</a></li>
      <li><a href="javascript:void(0)">4</a></li>
      <span id="line"></span>
    </ul>
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>

  <script>
    var divs = document.body.getElementsByTagName('div');
    var wrap = document.getElementById('wrap');
    var lists = wrap.children;
    var line = document.getElementById('line');
    var divY = {};
    // 设置div宽高与屏幕一致
    divs[0].style.width = innerWidth + 'px';
    divs[0].style.height = innerHeight + 'px';
    for (var i = 1; i < divs.length; i++) {
      divs[i].style.width = innerWidth  + 'px';
      divs[i].style.height = innerHeight - wrap.offsetHeight + 'px';
      divs[i].style.position = 'relative';
    }

    // 悬浮导航栏
    // 滚动监听
    for (i = 0; i < divs.length;i++) {
      divY[i] = divs[i].offsetTop;
    }

    document.onscroll = function () {
      var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
      if (scrollTop > divs[0].offsetHeight) {
        wrap.style.position = 'fixed';
        wrap.style.left = 0 + 'px';
        wrap.style.top = 0 + 'px';
        line.style.display = 'block';
      }
      if (scrollTop < divs[0].offsetHeight) {
        wrap.style.position = 'relative';
      }

      // 滚动监听
      for (var key in divs) {
        if (document.documentElement.scrollTop >= divY[key] - 120) {
          key = parseInt(key) - 1;
          key = key === -1 ? 0: key;
          animate(line,lists[key].offsetLeft);
          console.log(document.documentElement.scrollTop);
          console.log(key);
        }
      }
    };
    //
    /*
    因为悬浮栏滚动出去大于或等于732的时候脱离文档流,然而当我点击第一个div时刚好滚动条滚动出入732,这时导航栏脱离文档流,所以div就凑上主页,导致bug
    */

    // 导航栏的线条动画

    for (i = 0;i < lists.length; i++) {
      var list = lists[i];
      list.index = i+1;
      list.addEventListener('mouseover',function () {
        line.style.display = 'block';
        animate(line,this.offsetLeft);
      },false);

      // 点击导航栏跳到该跳的页面
      list.addEventListener('click',function () {
        var that = this;
        if (that.timerId) {// 如果点击的时候有计时器在执行,没有就清除掉它
          clearTimeout(that.timerId);
        }
        // 获取页面当前滚动出去的位置
        var current = document.documentElement.scrollTop || document.body.scrollTop;
        // 设置定时器做动画
        that.timerId = setInterval(function () {
          // 获取当前点击的那个div的坐标
          var target = divs[that.index].offsetTop;
          var stop = 30;
          // 如果当前位置大于目标位置,就让stop变成负数
          if (current > target) {
            stop = -Math.abs(stop);
          }
          // 如果目标位置离当前位置很近,那就让目标位置变成当前位置
          if (Math.abs(target - current)<= Math.abs(stop)) {
            // 当前位置 = 目标位置减去导航栏的高度
            document.documentElement.scrollTop = target - wrap.offsetHeight;
            document.body.scrollTop = target - wrap.offsetHeight;
            console.log(document.documentElement.scrollTop);
            clearInterval(that.timerId);
            return;
          }
          current += stop;
          document.documentElement.scrollTop = current - wrap.offsetHeight;
          document.body.scrollTop = current - wrap.offsetHeight;
        },5)
      },false);
    }





    // 封装动画
    function animate (element,target,callback) {
      // 解决多次点击动画变快的bug
      if (element.timerId) {// 如果点击的时候有计时器在执行,没有就清除掉它
        clearTimeout(element.timerId);
      }
      element.timerId = setInterval(function () {

        // 当前div的位置
        var current= element.offsetLeft;
        // 步进
        // 如果current > target ,就让count变成负数(向反方向移动)
        var count = 10;
        if (current > target) {
          count = -Math.abs(count);
        }
        //将current >= target换成current绝对值 - target绝对值的差小于一个数
        if (Math.abs(current - target) <= Math.abs(count)) {
          element.style.left = target + 'px';
          // 回调函数
          // 判断是否传入了这个函数,有就执行
          if (callback) {
            callback();
          }
          //清除定时器
          clearTimeout(element.timerId);
          return;
        }
        // 执行一次当前的等于当前的加步进的
        current += count;
        element.style.left = current + 'px';
      },20);
    }
  </script>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值