Vue视差标题背景

一、说明

这个我是为了放在博客的标题部分作为背景图,上下滚动的时候比较好看。

原理就是通过几张透明的png进行叠加,然后在上下滚动时,外层png移动的快,内层png移动得慢来实现视差效果。

  • 先放一张示意图:

这里实际的距离X和Y在观察者看来是一样的,原因是距离观察者的距离Z不一样导致的。

  • 再放一张视差标题背景的3d示意图:

二、Vue代码

这里为了代码高亮分三部分展示

html部分

html 复制代码
<template>
  <section>
    <img :src="p0Src" id="p0" :style="{ transform: `translateY(${p0Top}px)`, zIndex: `100` }" alt="p0">
    <img :src="p1Src" id="p1" :style="{ transform: `translateY(${p1Top}px)`, zIndex: `200` }" alt="p1">
    <img :src="p2Src" id="p2" :style="{ transform: `translateY(${p2Top}px)`, zIndex: `300` }" alt="p2">
    <img :src="p3Src" id="p3" :style="{ transform: `translateY(${p3Top}px)`, zIndex: `400` }" alt="p3">
    <img :src="p4Src" id="p4" :style="{ transform: `translateY(${p4Top}px)`, zIndex: `500` }" alt="p4">
    <img :src="p6Src" id="p6" :style="{ transform: `translateY(${p6Top}px)`, zIndex: `600` }" alt="p6">
    <div id="banner_title"
         class="container"
         :style="{ marginRight: `0px`, marginTop: `${bannerTitleMarginTop}px`, width: `75%`}">
        <h1>{{blogTitle}}</h1>
        <p class="description">{{blogDescription}}</p>
    </div>
  </section>
</template>

js部分

js 复制代码
<script>
const imgUrl = "https://xxxxxxxxxxxx/";
export default {
  name: "Banner",
  data() {
    return {
      p0Src: imgUrl + 'banner/ppp0.png',
      p1Src: imgUrl + 'banner/pp1.png',
      p2Src: imgUrl + 'banner/pp2.png',
      p3Src: imgUrl + 'banner/pp3.png',
      p4Src: imgUrl + 'banner/pp4.png',
      p6Src: imgUrl + 'banner/pp6.png',
      p0Top: 0,
      p1Top: 0,
      p2Top: 0,
      p3Top: 0,
      p4Top: 0,
      p6Top: 0,
      bannerTitleMarginTop: -100,
      requestId: undefined, // 用于跟踪 requestAnimationFrame 的标识
    };
  },
  props:{
    blogTitle:{
      type: String,
      require: true
    },
    blogDescription:{
      type: String,
      require: true
    },
  },
  mounted() {
    this.addScrollListener();
  },
  beforeDestroy() {
    this.removeScrollListener();
  },
  methods: {
    addScrollListener() {
      // 使用 passive 参数优化滚动性能
      window.addEventListener('scroll', this.handleScroll, {passive: true});
    },
    removeScrollListener() {
      window.removeEventListener('scroll', this.handleScroll);
    },
    handleScroll() {
      const value = window.scrollY;
      this.p0Top = value * 0.6;
      this.p1Top = value * 0.36;
      this.p2Top = value * 0.24;
      this.p3Top = value * 0.16;
      this.p4Top = value * 0.12;
      this.p6Top = 0;
      this.bannerTitleMarginTop = value * 1.1 - 100;
      // 使用 requestAnimationFrame 更新样式
      if (this.requestId === undefined) {
        this.requestId = requestAnimationFrame(this.updateStyles);
      }
    },
    updateStyles() {
      // 清除请求动画帧标识
      this.requestId = undefined;
    }
  }
}
</script>

style部分

css 复制代码
<style scoped lang="scss">
section {
  position: relative;
  width: 100%;
  height: 100vh;
  padding: 0px;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow: hidden;

  img {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    //height: 100%;
    object-fit: cover;
    pointer-events: none;
    will-change: transform; // 提前告知浏览器哪些属性可能会发生变化
  }

  #p4,#p3,#p2,#p1,#p0 {
    width: 100%;
    height: 100%;
  }

  #p6 {
    width: 100%;
    height: 150%;
  }

  section::before {
    content: '';
    position: absolute;
    bottom: 0;
    width: 100%;
    //height: 100px;
    background: linear-gradient(to top, #1c0522, transparent);
    //z-index: 1000;
  }
}
@-webkit-keyframes bounce {
  0%,10%,25%,40%,50% {
    -webkit-transform: translateY(0) rotate(0deg);
    transform: translateY(0) rotate(0deg)
  }

  20% {
    -webkit-transform: translateY(-10px) rotate(0deg);
    transform: translateY(-10px) rotate(0deg)
  }

  30% {
    -webkit-transform: translateY(-5px) rotate(0deg);
    transform: translateY(-5px) rotate(0deg)
  }
}

@keyframes bounce {
  0%,10%,25%,40%,50% {
    -webkit-transform: translateY(0) rotate(0deg);
    transform: translateY(0) rotate(0deg)
  }

  20% {
    -webkit-transform: translateY(-10px) rotate(0deg);
    transform: translateY(-10px) rotate(0deg)
  }

  30% {
    -webkit-transform: translateY(-5px) rotate(0deg);
    transform: translateY(-5px) rotate(0deg)
  }
}
</style>

三、效果

可以点击七仔的博客然后上下缓慢滚动来查看效果。

相关推荐
ttwuai19 小时前
XYGo Admin 菜单与路由:Vue3 动态路由 + GoFrame 权限菜单的完整实现方案
前端·vue·后台框架
Kurisu57521 小时前
探灵直播2026最新官方正版免费下载 一键转存 永久更新 (看到速转存 资源随时走丢)
游戏·游戏引擎·游戏程序·动画·关卡设计
ttwuai1 天前
XYGo Admin 国际化实战:Vue3 中后台多语言方案详解
前端·javascript·vue.js·vue
暗冰ཏོ2 天前
《前端动画超详细教程:CSS、JS 动画原理、实战与性能优化》
前端·javascript·css·动画
还得是你大哥2 天前
Java互联网医院管理系统源码SpringBoot
java·spring boot·vue
会周易的程序员3 天前
aiDgeScanner:工业设备扫描与管理的一体化利器——深度解析上位机与扫描端的无缝协作
c++·物联网·typescript·electron·vue·iot·aiot
阿部多瑞 ABU3 天前
运动会智能编排系统 - 完整详细需求规格说明书
python·贪心算法·vue·html
AIGC包拥它4 天前
RAG 项目实战进阶:基于 FastAPI + Vue3 前后端架构全面重构 LangChain 0.3 集成 Milvus 2.5 构建大模型智能应用
人工智能·python·重构·vue·fastapi·milvus·ai-native
次次皮6 天前
代理启动前端dist包
java·前端·vue
展示猪肝6 天前
Vue2 + FastAPI + Dify 实现 AI 医疗预检分诊助手:从问诊追问到医生审核闭环
人工智能·vue·fastapi·dify