首页 前端知识 Vue 实现全屏滚动效果

Vue 实现全屏滚动效果

2024-08-27 09:08:57 前端知识 前端哥 307 165 我要收藏

Vue实现全屏滚动效果

结构部分

<template>
  <div class="full-page" ref="page">
    <div
      class="list"
      ref="container"
      @mousewheel="mouseWheel"
      @DOMMouseScroll="mouseWheel"
    >
      <div class="item red">
        <h1>Page 1.</h1>
        <div class="content">
          <div class="info">
            <div
              class="avatar"
              :class="itemIndex === 1 ? 'avatar-act' : 'item-blur'"
            >
              K
            </div>
            <div
              class="name"
              :class="itemIndex === 1 ? 'name-act' : 'item-blur'"
            >
              Kay
            </div>
          </div>
          <div class="desc" :class="itemIndex === 1 ? 'desc-act' : 'item-blur'">
            <i>This is description.</i>
          </div>
        </div>
      </div>
      <div class="item blue">
        <h1>Page 2.</h1>
        <div class="content">
          <div
            class="logo"
            :class="itemIndex === 2 ? 'logo-act' : 'item-blur'"
          ></div>
          <div
            class="slogan"
            :class="itemIndex === 2 ? 'slogan-act' : 'item-blur'"
          >
            <i>This is slogan.</i>
          </div>
        </div>
      </div>
      <div class="item green">
        <h1>Page 3.</h1>
        <div class="content">
          <div
            class="title"
            :class="itemIndex === 3 ? 'title-act' : 'item-blur'"
          >
            This is the title for post.
          </div>
          <div class="post" :class="itemIndex === 3 ? 'post-act' : 'item-blur'">
            <i>
              In the flood of darkness, hope is the light. It brings comfort,
              faith, and confidence. It gives us guidance when we are lost, and
              gives support when we are afraid. And the moment we give up hope,
              we give up our lives. The world we live in is disintegrating into
              a place of malice and hatred, where we need hope and find it
              harder. In this world of fear, hope to find better, but easier
              said than done, the more meaningful life of faith will make life
              meaningful.
            </i>
          </div>
        </div>
      </div>
      <div class="item gray">
        <h1>Page 4.</h1>
        <div
          class="content"
          :class="itemIndex === 4 ? 'content-act' : 'item-blur'"
        >
          The end.
        </div>
      </div>
    </div>
    <div class="points">
      <div
        v-for="(e, i) in 4"
        class="item"
        :key="e"
        :class="itemIndex === i + 1 ? 'item-act' : ''"
      ></div>
    </div>
  </div>
</template>

JS部分

export default {
  name: "FullPageScroll",
  data() {
    return {
      isScroll: false, // 是否能滚动
      itemIndex: 0, // 当前下标
      len: 4, // 总个数
    };
  },
  methods: {
    handleMove() {
      this.isScroll = true;
      const scrollHeight = this.$refs.page.clientHeight;
      this.$refs.container.style.transform = `translateY(-${
        (this.itemIndex - 1) * scrollHeight
      }px)`;
      setTimeout(() => (this.isScroll = false), 1300); // 防止连续滚动,加延时
    },
    mouseWheel(event) {
      if (this.isScroll) { // 防止连续滚动
        return false;
      }
      if (event.deltaY > 0) {
        if (this.itemIndex === this.len) return; // 最后一个禁止向下滚动
        this.itemIndex += 1;
      } else {
        if (this.itemIndex === 1) return; // 第一个禁止向上滚动
        this.itemIndex -= 1;
      }
      this.handleMove();
    },
  },
  mounted() {
    setTimeout(() => (this.itemIndex += 1), 10); // 初始加一,为了加载第一页动画
  },
};

CSS

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(100px);
  }
  to {
    opacity: 1;
    transform: translateY(0px);
  }
}
@keyframes slideLeft {
  from {
    opacity: 0;
    transform: translateX(-100%);
  }
  to {
    opacity: 1;
    transform: translateX(0px);
  }
}
@keyframes slideRight {
  from {
    opacity: 0;
    transform: translateX(100%);
  }
  to {
    opacity: 1;
    transform: translateX(0px);
  }
}
@keyframes slideUp {
  from {
    opacity: 0;
    transform: translateY(-100%);
  }
  to {
    opacity: 1;
    transform: translateX(0px);
  }
}
@keyframes slideDown {
  from {
    opacity: 0;
    transform: translateY(100%);
  }
  to {
    opacity: 1;
    transform: translateX(0px);
  }
}
.full-page {
  width: 100vw;
  height: 100vh;
  position: relative;
  overflow: hidden;
  .list {
    width: 100vw;
    transition: 1s;
    .item {
      height: 100vh;
      transition: 1s all;
      .item-blur {
        opacity: 1 !important;
      }
      h1 {
        padding: 20px;
        font-size: 24px;
        margin: 0px;
      }
      &.red {
        h1 {
          color: red;
        }
        background-color: rgba($color: red, $alpha: 0.1);
        .content {
          width: 600px;
          margin: auto;
          padding-top: 200px;
          .info {
            display: flex;
            align-items: center;
            .avatar {
              width: 80px;
              height: 80px;
              margin-right: 20px;
              background-color: rgba($color: #fff, $alpha: 0.6);
              border-radius: 80px;
              overflow: hidden;
              text-align: center;
              line-height: 80px;
              font-size: 24px;
              color: #999;
              opacity: 0;
              &.avatar-act {
                animation: fadeIn 1s 0s forwards;
              }
            }
            .name {
              font-size: 24px;
              opacity: 0;
              &.name-act {
                animation: fadeIn 1s 0.5s forwards;
              }
            }
          }
          .desc {
            margin-left: 100px;
            font-size: 36px;
            font-weight: bold;
            opacity: 0;
            &.desc-act {
              animation: fadeIn 1s 1s forwards;
            }
          }
        }
      }
      &.blue {
        h1 {
          color: blue;
        }
        background-color: rgba($color: blue, $alpha: 0.1);
        .content {
          width: 400px;
          margin: 300px auto;
          position: relative;
          .logo {
            width: 100%;
            height: 80px;
            border-radius: 10px;
            position: absolute;
            border: 4px solid rgba($color: blue, $alpha: 0.3);
            opacity: 0;
            &.logo-act {
              animation: slideLeft 0.8s 0.2s forwards;
            }
          }
          .slogan {
            height: 80px;
            line-height: 80px;
            text-align: center;
            color: rgba($color: blue, $alpha: 0.5);
            font-size: 38px;
            font-weight: bold;
            opacity: 0;
            &.slogan-act {
              animation: slideRight 0.8s 0.2s forwards;
            }
          }
        }
      }
      &.green {
        h1 {
          color: green;
        }
        background-color: rgba($color: green, $alpha: 0.1);
        .content {
          width: 500px;
          margin: 200px auto;
          color: green;
          .title {
            margin-bottom: 10px;
            text-align: center;
            font-size: 24px;
            opacity: 0;
            &.title-act {
              animation: slideUp 0.8s 0.5s forwards;
            }
          }
          .post {
            font-size: 16px;
            text-indent: 2rem;
            opacity: 0;
            &.post-act {
              animation: slideDown 0.6s 0.7s forwards;
            }
          }
        }
      }
      &.gray {
        h1 {
          color: gray;
        }
        background-color: rgba($color: gray, $alpha: 0.4);
        .content {
          margin-top: 200px;
          font-size: 42px;
          text-align: center;
          font-weight: bold;
          color: gray;
          opacity: 0;
          &.content-act {
            animation: slideUp 1s 0.5s forwards;
          }
        }
      }
    }
  }
  .points {
    position: fixed;
    top: 50%;
    transform: translateY(-50%);
    right: 10px;
    .item {
      width: 4px;
      height: 20px;
      margin-bottom: 25px;
      background-color: rgba($color: gray, $alpha: 0.5);
      transition: 1s;
      &.item-act {
        height: 50px;
        background-color: #fff;
      }
    }
  }
}

效果图(静态)
在这里插入图片描述

转载请注明出处或者链接地址:https://www.qianduange.cn//article/16958.html
标签
评论
会员中心 联系我 留言建议 回顶部
复制成功!