七、全屏粒子特效

简介

给页面添加粒子光影特效。欢迎访问个人的简历网站预览效果

本章涉及修改与新增的文件:main.tsApp.vueutils
七、全屏粒子特效_第1张图片

一、安装插件

  1. 安装 vue3-particles tsparticles插件 详细文档查看 tsParticles 官网
npm i vue3-particles

npm i tsparticles
  1. 创建配置文件 options.ts
// 在 utils 文件夹中 创建options.ts
export const options = {
  "fullScreen": {
    "zIndex": 1
  },
  "particles": {
    "bounce": {
      "horizontal": {
        "random": {
          "enable": false,
          "minimumValue": 0.1
        },
        "value": 1
      },
      "vertical": {
        "random": {
          "enable": false,
          "minimumValue": 0.1
        },
        "value": 1
      }
    },
    "collisions": {
      "absorb": {
        "speed": 2
      },
      "bounce": {
        "horizontal": {
          "random": {
            "enable": false,
            "minimumValue": 0.1
          },
          "value": 1
        },
        "vertical": {
          "random": {
            "enable": false,
            "minimumValue": 0.1
          },
          "value": 1
        }
      },
      "enable": false,
      "maxSpeed": 50,
      "mode": "bounce",
      "overlap": {
        "enable": false,
        "retries": 0
      }
    },
    "color": {
      "value": "#F29927",
    },
    "groups": {},
    "move": {
      "angle": {
        "offset": 0,
        "value": 50
      },
      "attract": {
        "distance": 200,
        "enable": false,
        "rotate": {
          "x": 3000,
          "y": 3000
        }
      },
      "center": {
        "x": 50,
        "y": 50,
        "mode": "percent",
        "radius": 0
      },
      "decay": 0,
      "distance": {},
      "direction": "none",
      "drift": 0,
      "enable": true,
      "gravity": {
        "acceleration": 9.81,
        "enable": false,
        "inverse": false,
        "maxSpeed": 50
      },
      "path": {
        "clamp": true,
        "delay": {
          "random": {
            "enable": false,
            "minimumValue": 0
          },
          "value": 0
        },
        "enable": false,
        "options": {}
      },
      "outModes": {
        "default": "out",
        "bottom": "out",
        "left": "out",
        "right": "out",
        "top": "out"
      },
      "random": false,
      "size": false,
      "speed": 2,
      "spin": {
        "acceleration": 0,
        "enable": false
      },
      "straight": false,
      "trail": {
        "enable": false,
        "length": 10,
        "fill": {}
      },
      "vibrate": false,
      "warp": false
    },
    "number": {
      "density": {
        "enable": true,
        "width": 1920,
        "height": 1080
      },
      "limit": 0,
      "value": 50
    },
    "opacity": {
      "random": {
        "enable": true,
        "minimumValue": 0.5
      },
      "value": {
        "min": 0.3,
        "max": 1
      },
      "animation": {
        "count": 0,
        "enable": true,
        "speed": 0.5,
        "decay": 0,
        "delay": 0,
        "sync": false,
        "mode": "auto",
        "startValue": "random",
        "destroy": "none",
        "minimumValue": 0.3
      }
    },
    "shape": {
      "close": true,
      "fill": true,
      "options": {},
      "type": "circle"
    },
    "size": {
      "random": {
        "enable": true,
        "minimumValue": 1
      },
      "value": {
        "min": 1,
        "max": 3
      },
      "animation": {
        "count": 0,
        "enable": true,
        "speed": 3,
        "decay": 0,
        "delay": 0,
        "sync": false,
        "mode": "auto",
        "startValue": "random",
        "destroy": "none",
        "minimumValue": 1
      }
    },
    "stroke": {
      "width": 0
    },
    "zIndex": {
      "random": {
        "enable": false,
        "minimumValue": 0
      },
      "value": 0,
      "opacityRate": 1,
      "sizeRate": 1,
      "velocityRate": 1
    },
    "destroy": {
      "bounds": {},
      "mode": "none",
      "split": {
        "count": 1,
        "factor": {
          "random": {
            "enable": false,
            "minimumValue": 0
          },
          "value": 3
        },
        "rate": {
          "random": {
            "enable": false,
            "minimumValue": 0
          },
          "value": {
            "min": 4,
            "max": 9
          }
        },
        "sizeOffset": true,
        "particles": {}
      }
    },
    "roll": {
      "darken": {
        "enable": false,
        "value": 0
      },
      "enable": false,
      "enlighten": {
        "enable": false,
        "value": 0
      },
      "mode": "vertical",
      "speed": 25
    },
    "tilt": {
      "random": {
        "enable": false,
        "minimumValue": 0
      },
      "value": 0,
      "animation": {
        "enable": false,
        "speed": 0,
        "decay": 0,
        "sync": false
      },
      "direction": "clockwise",
      "enable": false
    },
    "twinkle": {
      "lines": {
        "enable": false,
        "frequency": 0.05,
        "opacity": 1
      },
      "particles": {
        "enable": false,
        "frequency": 0.05,
        "opacity": 1
      }
    },
    "wobble": {
      "distance": 5,
      "enable": false,
      "speed": {
        "angle": 50,
        "move": 10
      }
    },
    "life": {
      "count": 0,
      "delay": {
        "random": {
          "enable": false,
          "minimumValue": 0
        },
        "value": 0,
        "sync": false
      },
      "duration": {
        "random": {
          "enable": false,
          "minimumValue": 0.0001
        },
        "value": 0,
        "sync": false
      }
    },
    "rotate": {
      "random": {
        "enable": false,
        "minimumValue": 0
      },
      "value": 0,
      "animation": {
        "enable": false,
        "speed": 0,
        "decay": 0,
        "sync": false
      },
      "direction": "clockwise",
      "path": false
    },
    "orbit": {
      "animation": {
        "count": 0,
        "enable": false,
        "speed": 1,
        "decay": 0,
        "delay": 0,
        "sync": false
      },
      "enable": false,
      "opacity": 1,
      "rotation": {
        "random": {
          "enable": false,
          "minimumValue": 0
        },
        "value": 45
      },
      "width": 1
    },
    "links": {
      "blink": false,
      "color": {
        "value": "random"
      },
      "consent": false,
      "distance": 100,
      "enable": false,
      "frequency": 1,
      "opacity": 1,
      "shadow": {
        "blur": 5,
        "color": {
          "value": "#000"
        },
        "enable": false
      },
      "triangles": {
        "enable": false,
        "frequency": 1
      },
      "width": 1,
      "warp": false
    },
    "repulse": {
      "random": {
        "enable": false,
        "minimumValue": 0
      },
      "value": 0,
      "enabled": false,
      "distance": 1,
      "duration": 1,
      "factor": 1,
      "speed": 1
    }
  },
}

二、修改文件中代码

  1. main.ts 中引入插件
import { createApp } from 'vue'
import './style.css'
import 'animate.css';
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import Particles from "vue3-particles";// 引入插件
import App from './App.vue'
const app = createApp(App)

app.use(Particles)
app.use(ElementPlus, { size: 'small', zIndex: 3000 })
app.mount('#app')
  1. App.vue 中使用插件
<template>
  <div class="app-background" @wheel="handleWheel">
    <!-- 上一页信息 -->
    <div class="absolute" @click="prev" style="top: 50px;">
      <img src="/up.svg" class="logo" alt="Email" />
    </div>

    <el-carousel ref="carousel" height="100vh" trigger="click" direction="vertical" :autoplay="false"
      @change="changeCarousel">
      <el-carousel-item>
        <first :count="count" ref="firstPage" />
      </el-carousel-item>
      <el-carousel-item>
        <second :count="count" />
      </el-carousel-item>
      <el-carousel-item>
        <third :count="count" ref="thirdPage" />
      </el-carousel-item>
      <el-carousel-item>
        <fourth :count="count" ref="fourthPage" />
      </el-carousel-item>
      <el-carousel-item>
        <fifth :count="count" ref="fifthPage" @showProject="showProject" />
      </el-carousel-item>
    </el-carousel>
    <!-- 下一页信息 -->
    <div class="absolute" @click="next" style="bottom: 50px;">
      <img src="/down.svg" class="logo" alt="Email" />
    </div>
    <!-- 项目经验详情 -->
    <el-dialog v-model="showDialog" center>
      <div class="family">
        <div class="text18" style="text-align: center;font-weight: bold;">{{ projectInfo.projectName }}</div>
        <div class="margin-top" style="text-align: center;">
          {{ projectInfo.projectStartTime }} - {{ projectInfo.projectEndTime }}
        </div>
        <div class="flex margin-top">
          <div style="min-width: 100px;">项目描述:</div>
          <div>{{ projectInfo.projectDescription }}</div>
        </div>
        <div class="flex margin-top">
          <div style="min-width: 100px;">项目职责:</div>
          <div>{{ projectInfo.projectDuty }}</div>
        </div>
        <div class="flex margin-top">
          <div style="min-width: 100px;">技术栈:</div>
          <div>{{ projectInfo.projectStack }}</div>
        </div>
        <div class="flex margin-top" v-if="projectInfo.projectOnline">
          <div style="min-width: 100px;">线上地址:</div>
          <el-link :href="projectInfo.projectOnline" target="_blank">
            {{ projectInfo.projectOnline }}
          </el-link>
        </div>
      </div>
    </el-dialog>
	// 使用粒子特效组件
    <vue-particles id="tsparticles" :particlesInit="particlesInit" :clickEffect="true" :options="options" />
  </div>
</template>

<script setup lang="ts">
import first from './components/First.vue'
import second from './components/Second.vue'
import third from './components/Third.vue'
import fourth from './components/Fourth.vue'
import fifth from './components/Fifth.vue'
import project from './utils/Project.ts'
import { options } from "./utils/options";
import { loadFull } from 'tsparticles'
import { ref } from 'vue'
const showDialog = ref(false)
const projectInfo = ref(project['center'])
const count = ref(0)
const firstPage = ref()
const thirdPage = ref()
const fourthPage = ref()
const fifthPage = ref()
const carousel = ref()
// 获取默认项目经验数据
const showProject = (value: any) => {
  if (project[value]) {
    projectInfo.value = project[value]
    showDialog.value = true
  }
}

// 上一页
const prev = () => {
  carousel.value.prev()
}

// 下一页
const next = () => {
  carousel.value.next()
}

let timer: any = null
const handleWheel = (e: any) => {
  if (showDialog.value) return
  let lock: Boolean = !timer;
  if (lock) {
    if (e.deltaY > 0) {
      next()
    } else if (e.deltaY < 0) {
      prev()
    }
    timer = setTimeout(() => {
      timer = null;
    }, 500);
  }
}

const handleKeyDown = (event: any) => {
  if (showDialog.value) return
  let lock: Boolean = !timer;
  if (lock) {
    if (event.key === 'ArrowUp') { prev() }
    else if (event.key === 'ArrowDown') { next() }
    timer = setTimeout(() => {
      timer = null;
    }, 500);
  }
}
// 监听键盘触发事件
document.addEventListener('keydown', handleKeyDown);

// 监听切换事件,重置和触发动态效果
const changeCarousel = (value: any) => {
  count.value = value
  if (value === 0) {
    firstPage.value.resetArr()
  } else if (value === 2) {
    thirdPage.value.resetArr()
  } else if (value === 3) {
    fourthPage.value.resetArr()
  } else if (value === 4) {
    fifthPage.value.resetArr()
  }
}

const particlesInit = async (engine: any) => {
  await loadFull(engine)
}
</script>

<style scoped>
.app-background {
  position: relative;
  width: 100%;
  height: 100vh;
  background-image: url('./assets/bgBig.png');
  background-repeat: no-repeat;
  background-position: center 0;
  background-size: cover;
}

.el-carousel__item {
  min-height: 100vh;
  background-color: rgba(10, 10, 10, 0.3);
}

::v-deep(.el-dialog) {
  background-color: rgb(250, 235, 215);
  animation: jackInTheBox;
  animation-duration: 1.5s;
}

.absolute {
  position: absolute;
  z-index: 10;
  left: calc(50% - 14px);
  opacity: .25;
  transition: all .4s linear 0s;
}

.absolute:hover {
  transform: scale(1.18);
  opacity: .85;
}

.logo {
  width: 28px;
  height: 28px;
}
</style> 

效果如下:

=> To Be Continued

点赞 评论 收藏 ~~ 留言讨论,如有错误,也希望大家不吝指出。 ~~ 点赞 评论 收藏

你可能感兴趣的:(互联网个人简历,typescript,node.js,前端)