vue 实现钉钉官网的轮播图下面功能滚动排版CSS效果

前言

  • 最近在写PC端的业主端时候,发现传统的菜单栏比较丑,也不符合实际应用(功能页面并不多-展示为主)

  • 偶然发现钉钉官网的效果挺有意思的,想着把这个效果复原过来,然后夸夸搜索了一番。

  • 经过一顿的cv打法,加上修修补补把大概的效果整了出来,时间关系最基础的,剩下的可以自己补充

地址演示:演示效果地址

视频效果

官网效果

细节

1.代码中第二屏是300vh是3倍,试过很多遍,3倍滚动时效果最好不建议改,建议不显示滚动条(src/styles/index.scss)效果最好

::-webkit-scrollbar {
  // 隐藏滚动条
  display: none; /* Chrome Safari */
}

2.代码中第二屏的3个class类名最好不要改,因为是根据这几个类名在获取DOM操作

3.代码中第二屏中 list-itme中的data-order="0"等于几(从0开始)控制动画盒子顺序,可以自己调试看效果

完整代码-可复制

<template>
  <div class="conter">
    <!-- 第一屏 -->
    <div class="flatly-itemone">
    </div>
    <!-- 第二屏 -->
    <div class="playground">
      <div class="animation-container">
        <div class="titlemanifesto" v-if="titlemanifesto">
          生活意义-坦然面对生活并且接受她的事与愿违
        </div>
        <!-- data-order="0" 数字是控制每一项动画顺序 -->
        <div class="list">
          <div data-order="0" class="list-item"></div>
          <div data-order="1" class="list-item"></div>
          <div data-order="2" class="list-item"></div>
          <div data-order="2" class="list-item"></div>
          <div data-order="1" class="list-item"></div>
          <div data-order="0" class="list-item"></div>
          <div data-order="0" class="list-item"></div>
          <div data-order="1" class="list-item"></div>
          <div data-order="2" class="list-item"></div>
          <div data-order="2" class="list-item"></div>
          <div data-order="1" class="list-item"></div>
          <div data-order="0" class="list-item"></div>
        </div>
      </div>
    </div>
  </div>
</template>
​
<script>
export default {
  name: 'Dashboard',
  data() {
    return {
      animataionMap: new Map(),
      // 文字显示
      titlemanifesto: false
    }
  },
  created() {},
  mounted() {
    this.updateMap(),
      this.updateStyle(),
      window.addEventListener('scroll', this.updateStyle)
  },
  methods: {
    // 得出动画节点数值
    createAnimation(scrollStart, scrollEnd, valueStart, valueEnd) {
      return (scroll) => {
        if (scroll <= scrollStart) {
          return valueStart
        }
​
        if (scroll >= scrollEnd) {
          return valueEnd
        }
​
        return (
          valueStart +
          ((valueEnd - valueStart) * (scroll - scrollStart)) /
            (scrollEnd - scrollStart)
        )
      }
    },
​
    getDomAnimation(scrollStart, scrollEnd, dom) {
      const list = document.querySelector('.list')
      scrollStart = scrollStart + dom.dataset.order * 300
      const opacityAnimation = this.createAnimation(
        scrollStart,
        scrollEnd,
        0,
        1
      )
      // 基于当前滚动计算得出的透明度
      const opacity = function (scroll) {
        return opacityAnimation(scroll)
      }
​
      const scaleAnimation = this.createAnimation(
        scrollStart,
        scrollEnd,
        0.3,
        1
      )
​
      const xAnimation = this.createAnimation(
        scrollStart,
        scrollEnd,
        list.clientWidth / 2 - dom.offsetLeft - dom.clientWidth / 2,
        0
      )
      const yAnimation = this.createAnimation(
        scrollStart,
        scrollEnd,
        list.clientHeight / 2 - dom.offsetTop - dom.clientHeight / 2,
        0
      )
​
      const transform = function (scroll) {
        return `translate(${xAnimation(scroll)}px,${yAnimation(
          scroll
        )}px)  scale(${scaleAnimation(scroll)})`
      }
​
      return {
        opacity,
        transform
      }
    },
​
    updateMap() {
      const items = document.querySelectorAll('.list-item')
      const playGround = document.querySelector('.playground')
      this.animataionMap.clear()
      const playGroundRect = playGround.getBoundingClientRect()
      // 开始动画的距离
      const scrollStart = playGroundRect.top + window.scrollY
      // 结束动画的距离  相当于playground的高度
      const scrollEnd =
        playGroundRect.bottom + window.scrollY - window.innerHeight
      for (const item of items) {
        this.animataionMap.set(
          item,
          this.getDomAnimation(scrollStart, scrollEnd, item)
        )
      }
      // 打开遮罩层
      // this.listmsk = true
    },
​
    updateStyle() {
      const scroll = window.scrollY
      // 获取元素-改变背景颜色
      const list = document.querySelector('.list')
      if (scroll > 2200 && scroll < 2862) {
        console.log('打开遮罩层')
        list.style.backgroundColor = 'rgba(23, 26, 29, 0.9)'
        // 显示文字
        this.titlemanifesto = true;
      } else {
        console.log('关闭遮罩层')
        list.style.backgroundColor = '#063868'
        // 隐藏文字
        this.titlemanifesto = false
      }
      console.log('scroll', scroll)
      for (let [dom, value] of this.animataionMap) {
        for (const cssProp in value) {
          dom.style[cssProp] = value[cssProp](scroll)
        }
      }
    }
  }
}
</script>
<style lang="scss" scoped>
.conter {
  .flatly-itemone {
    height: 90vh;
    background-color: #fff;
  }
  .playground {
    height: 310vh;
    background-color: #063868;
    position: relative;
    .animation-container {
      display: flex;
      position: sticky;
      top: 0;
      height: 100vh;
      text {
        z-index: 999;
        color: red;
      }
      // 标题
      .titlemanifesto {
        height: 50px;
        width: 1000px;
        position: absolute;
        left: 50%;
        top: 23%;
        transform: translate(-50%);
        // background-color: skyblue;
        text-align: center;
        color: #fff;
        font-family: PingFangSC-Medium;
        font-weight: 500;
        font-size: 30px;
        line-height: 50px;
      }
      .list {
        height: 550px;
        width: 1000px;
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -28%);
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        border-radius: 10px;
        padding: 15px 20px;
        opacity: 0.8;
        .list-item {
          width: 100px;
          height: 155px;
          border-radius: 10px;
          background-color: #fff;
          margin: 50px 30px;
          &:nth-child(2n - 1) {
            background-color: skyblue;
          }
          &:nth-child(2n) {
            background-color: rgb(111, 245, 111);
          }
          &:nth-child(3n) {
            background-color: orange;
          }
        }
      }
    }
  }
}
</style>

总结:

经过这一趟流程下来相信你也对 vue 实现钉钉官网的轮播图下面功能滚动排版CSS效果 有了初步的深刻印象,但在实际开发中我 们遇到的情况肯定是不一样的,所以我们要理解它的原理,万变不离其宗。加油,打工人!

什么不足的地方请大家指出谢谢 -- 風过无痕

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-風过无痕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值