3D粒子波浪特效、动画结合vue+three.js

在这里插入图片描述
开箱即用
在components下创建组件loginBgk/index

<template>
  <div id="iviewBg">
    <slot></slot>
  </div>
</template>

<script>
import * as THREE from "three";
// import Stats from "./stats.module";
import { onMounted } from "vue";
export default {
  props: {
    //控制x轴波浪的长度
    amountX: {
      type: Number,
      default: 50,
    },
    //控制y轴波浪的长度
    amountY: {
      type: Number,
      default: 50,
    },
    //控制点颜色
    color: {
      type: String,
      default: "#097bdb",
    },
    //控制波浪的位置
    top: {
      type: Number,
      default: 350,
    },
  },
  data() {
    return {
      SEPARATION: 100,
      container: "",
      camera: "",
      scene: "",
      renderer: "",
      particles: "",
      count: 0,
      mouseX: 0,
      windowHalfX: "",
    };
  },
  mounted() {
    this.windowHalfX = window.innerWidth / 2;
    this.init();
    this.animate();
  },
  methods: {
    init() {
      this.container = document.createElement("div");
      document.getElementById("iviewBg").appendChild(this.container);

      //创建透视相机
      this.camera = new THREE.PerspectiveCamera(
        75, //摄像机视锥体垂直视野角度
        window.innerWidth / window.innerHeight, //摄像机视锥体长宽比
        1, //摄像机视锥体近端面
        10000 //摄像机视锥体远端面
      );

      //设置相机z轴视野
      this.camera.position.z = 1000;

      //创建场景
      this.scene = new THREE.Scene();

      const numParticles = this.amountX * this.amountY;

      const positions = new Float32Array(numParticles * 3);
      const scales = new Float32Array(numParticles);

      let i = 0,
        j = 0;

      // 初始化粒子位置和大小
      for (let ix = 0; ix < this.amountX; ix++) {
        for (let iy = 0; iy < this.amountY; iy++) {
          positions[i] =
            ix * this.SEPARATION - (this.amountX * this.SEPARATION) / 2; // x
          positions[i + 1] = 0; // y
          positions[i + 2] =
            iy * this.SEPARATION - (this.amountY * this.SEPARATION) / 2; // z
          scales[j] = 1;
          i += 3;
          j++;
        }
      }

      //是面片、线或点几何体的有效表述。包括顶点位置,面片索引、法相量、颜色值、UV 坐标和自定义缓存属性值。使用 BufferGeometry 可以有效减少向 GPU 传输上述数据所需的开销
      const geometry = new THREE.BufferGeometry();
      geometry.setAttribute(
        "position",
        new THREE.BufferAttribute(positions, 3)
      );
      geometry.setAttribute("scale", new THREE.BufferAttribute(scales, 1));

      //着色器材质(ShaderMaterial),设置球的大小,颜色,等
      const material = new THREE.ShaderMaterial({
        uniforms: {
          //设置球的颜色
          color: { value: new THREE.Color(this.color) },
        },
        //控制球的大小
        vertexShader:
          "attribute float scale; void main() {vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );gl_PointSize = scale * ( 300.0 / - mvPosition.z );gl_Position = projectionMatrix * mvPosition;}",
        fragmentShader:
          "uniform vec3 color;void main() {if ( length( gl_PointCoord - vec2( 0.5, 0.5 ) ) > 0.475 ) discard;gl_FragColor = vec4( color, 1.0 );}",
      });

      //一个用于显示点的类。
      this.particles = new THREE.Points(geometry, material);
      //往场景中添加点
      this.scene.add(this.particles);

      //alpha - canvas是否包含alpha (透明度)。默认为 false。
      //渲染器的背景色默认为黑色,设置渲染器的背景色为透明
      this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
      this.renderer.setPixelRatio(window.devicePixelRatio);
      this.renderer.setClearAlpha(0);
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.container.appendChild(this.renderer.domElement);

      //显示右上角fps框
      // stats = new Stats();
      //   container.appendChild(stats.dom);

      this.container.style.touchAction = "none";
      //监听鼠标移动事件
      this.container.addEventListener("pointermove", this.onPointerMove);

      //调整波浪的位置
      this.container.style.position = "relative";
      this.container.style.top = `${this.top}px`;

      window.addEventListener("resize", this.onWindowResize);
    },
    render() {
      this.camera.position.x += (this.mouseX - this.camera.position.x) * 0.05;
      this.camera.position.y = 400;
      this.camera.lookAt(this.scene.position);

      const positions = this.particles.geometry.attributes.position.array;
      const scales = this.particles.geometry.attributes.scale.array;

      // 设置粒子位置和大小
      let i = 0,
        j = 0;
      for (let ix = 0; ix < this.amountX; ix++) {
        for (let iy = 0; iy < this.amountY; iy++) {
          positions[i + 1] =
            Math.sin((ix + this.count) * 0.3) * 50 +
            Math.sin((iy + this.count) * 0.5) * 50;

          scales[j] =
            (Math.sin((ix + this.count) * 0.3) + 1) * 10 +
            (Math.sin((iy + this.count) * 0.5) + 1) * 10;

          i += 3;
          j++;
        }
      }

      this.particles.geometry.attributes.position.needsUpdate = true;
      this.particles.geometry.attributes.scale.needsUpdate = true;

      this.renderer.render(this.scene, this.camera);

      this.count += 0.1;
    },
    onWindowResize() {
      this.windowHalfX = window.innerWidth / 2;
      this.camera.aspect = window.innerWidth / window.innerHeight;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(window.innerWidth, window.innerHeight);
    },
    onPointerMove(event) {
      if (event.isPrimary === false) return;
      this.mouseX = event.clientX - this.windowHalfX;
    },
    animate() {
      requestAnimationFrame(this.animate);
      this.render();
      //fps 实时更新
      // stats.update();
    },
  },
};
</script>

<style lang="scss" scoped>
#iviewBg {
  background: url("../../assets/imgs/wavesBg.png") no-repeat;
  overflow: hidden;
  justify-content: center;
  align-items: center;
  height: 100%;
  position: relative;
  display: flex;
}

</style>

在页面中引入

<wavesBg :top="250">
	在这个背景你所要画的页面
</wavesBg>

import wavesBg from "../components/loginBgk/index.vue";
 components: {
    wavesBg,
  },
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Vue和Three.js是两个不同的技术,Vue是一个前端框架,而Three.js是一个基于WebGL的JavaScript库,用于创建3D图形。使用Vue和Three.js可以很方便地实现3D地图场景的展示。 在使用Vue和Three.js创建3D地图时,首先需要设置场景(Scene)、相机(Camera)、光源(Lighting)、对象(Object)等元素,并将它们组合在一起。可以使用Vue的组件化方式来构建这些元素,然后将它们添加到场景中。在设置相机时,需要考虑到相机的位置、方向、FoV等参数,以便实现视角的变换和缩放等操作。 当创建好场景、相机、光源和对象后,可以使用Three.js提供的材质(Material)、纹理(Texture)、几何体(Geometry)等API,来实现对象的样式和效果。例如,可以使用纹理图片来为建筑物、地面等对象添加贴图效果,也可以使用材质来控制对象的表面和反射等特性。 除了基础的场景元素和对象设置外,还可以使用Three.js提供的控制器(Controller)来实现用户交互。例如,可以使用鼠标控制器(OrbitControls)来实现用户通过鼠标操作旋转和缩放场景,或使用触摸控制器(TouchControls)来实现在移动设备上的交互。 最后需要注意的是,3D地图的数据源通常比较大,需要进行优化和压缩。可以使用Vue和Three.js提供的工具和插件,来实现数据的处理和性能的优化。例如,可以使用Vue的懒加载和异步组件,来减少初始化时间和提高页面加载速度;也可以使用Three.js的GeometryUtils和TextureLoader等API,来优化数据加载和渲染性能。 总之,使用Vue和Three.js可以很方便地实现3D地图场景的展示,并且可以通过组件化与API的方式实现更加灵活和丰富的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值