原生JavaScript和CSS3实现全屏滚动动画

1,303 阅读1分钟

实现思路

全屏滚动和轮播图原理相似,这里主要通过css3的transform 3d转换和transition过渡动画实现页面的滚动效果,通过鼠标滚轮事件监听页面滚动。知识点:transform:translate3d(),transition,transitionend事件,mousewheel鼠标滚轮事件。

效果图

slide.gif

html布局

    <div class="box">
        <div class="item">
          <h1>第一屏</h1>
        </div>
        <div class="item">
          <h1>第二屏</h1>
        </div>
        <div class="item">
          <h1>第三屏</h1>
        </div>
        <div class="item">
          <h1>第四屏</h1>
        </div>
    </div>

    <!-- 导航小圆点 -->
    <div class="pagination">
      <span class="active"></span>
      <span></span>
      <span></span>
      <span></span>
    </div>

    <!-- 下一页按钮 -->
    <div class="next-page">下一页>></div>

css样式

<style>
  * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }

  html,
  body {
    height: 100%;
    width: 100%;
    overflow: hidden;
  }

  .box {
    height: 100%;
    width: 100%;
    transition: all 800ms ease-in-out;
  }

  .box .item {
    height: 100%;
    width: 100%;
  }

  .box .item h1 {
    padding-top: 300px;
    text-align: center;
  }

  .box .item:first-child {
    background: #9966ff;
  }

  .box .item:nth-child(2) {
    background: skyblue;
  }

  .box .item:nth-child(3) {
    background: cyan;
  }

  .box .item:nth-child(4) {
    background: #ffff66;
  }

  .next-page {
    height: 50px;
    width: 120px;
    position: fixed;
    left: 50%;
    margin-left: -60px;
    bottom: 20px;
    font-weight: 700;
    color: #000;
    cursor: pointer;
    text-align: center;
    line-height: 50px;
    animation: bounce 2s linear infinite;
  }


  .pagination {
    position: fixed;
    right: 15px;
    top: 50%;
    transform: translateY(-50%)
  }

  .pagination span {
    width: 8px;
    height: 8px;
    display: block;
    margin-bottom: 15px;
    background: #000;
    border-radius: 50%;
    opacity: 0.8;
    transition: transform 500ms;
  }

  .pagination span.active {
    background: rgba(255, 255, 255, 0.8);
    transform: scale(1.5)
  }

  @keyframes bounce {
    from {
      opacity: 0.3;
      transform: scale(1);
      transform: translateX(0)
    }

    to {
      opacity: 1;
      transform: scale(1.1);
      transform: translateX(10px)
    }
  }
</style>

js代码

    var clientHeight = window.innerHeight // 浏览器全屏高度
    var index = 0 // 滚动索引位置
    var flag = true // 节流阀
    var box = document.querySelector('.box') // 需要滚动的父元素
    var paginations = document.querySelectorAll('.pagination span') // 右侧导航小圆点
    var nextPage = document.querySelector('.next-page') // 下一页按钮
    var itemsLen = document.querySelectorAll('.box .item').length // 滚动屏数

    // 处理滚动的函数
    function slide(index) {

      // 使用css3 transform和transition属性实现滚动和过度动画
      box.style.transform = 'translate3d(0,' + (- index * clientHeight) + 'px,0)'

      // 导航小圆点添加高亮
      paginations.forEach(function (ele) {
        ele.classList.remove('active')
      })
      paginations[index].classList.add('active')

    }

    // 添加鼠标滚轮事件
    window.addEventListener('mousewheel', function (e) {

      // flag节流阀结合transitionend事件监听当前正在执行的transition动画
      // 是否已完成从而进行下个transition动画
      // 解决频繁触发滚轮事件导致某一屏未滚动完成就执行下一屏滚动
      if (flag) {
        flag = false

        if (e.wheelDelta < 0) {
          // e.wheelEelta < 0表示向下滚动

          if (index === itemsLen - 1) {
            index -= 1 // 滚动到最后一屏时,index值始终保持在最后一屏
            
            //因滚动到最后一屏不再向下滚动,
            //无法触发transitionend事件所以手动开启节流阀
            flag = true 
          }
          index++

        } else {

          if (index === 0) {
            index = 1
            flag = true
          }
          index--

        }

        slide(index)
      }

    })

    // 点击下一页按钮
    nextPage.addEventListener('click', function () {
      if (flag) {
        flag = false
        if (index === itemsLen - 1) {
          index -= 1
          flag = true
        }
        index++
        slide(index)
      }

    })

    // 监听当前transition过度动画是否已执行完毕
    box.addEventListener('transitionend', function () {
      flag = true // 开启节流阀,执行下一步transition
    })