vue使用three.js实现粒子波浪效果

npm install --save three
<template>
  <div id="indexLizi" />
</template>
 
<script>
import * as THREE from "three";

export default {
  name: "Pointwave",
  props: {
    amountX: {
      type: Number,
      default: 50,
    },
    amountY: {
      type: Number,
      default: 50,
    },
    color: {
      type: Number,
      // default: 0xffffff,
      // default: 0x097bdb,
      default: 0x497fb7,
    },
    top: {
      type: Number,
      default: 150,
    },
  },
  data() {
    return {
      count: 0,
      // 用来跟踪鼠标水平位置
      mouseX: 0,
      windowHalfX: null,
      // 相机
      camera: null,
      // 场景
      scene: null,
      // 批量管理粒子
      particles: null,
      // 渲染器
      renderer: null,
    };
  },
  mounted() {
    this.init();
    this.animate();
    this.onWindowResize();
  },
  methods: {
    init: function () {
      const SEPARATION = 100;
      const SCREEN_WIDTH = window.innerWidth;
      const SCREEN_HEIGHT = window.innerHeight;
      const container = document.createElement("div");
      this.windowHalfX = window.innerWidth / 2;
      container.style.position = "relative";
      container.style.top = `${this.top}px`;
      container.style.height = `${SCREEN_HEIGHT - this.top}px`;
      document.getElementById("indexLizi").appendChild(container);

      this.camera = new THREE.PerspectiveCamera(
        75,
        SCREEN_WIDTH / SCREEN_HEIGHT,
        1,
        10000
      );
      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;
      let j = 0;
      for (let ix = 0; ix < this.amountX; ix++) {
        for (let iy = 0; iy < this.amountY; iy++) {
          positions[i] = ix * SEPARATION - (this.amountX * SEPARATION) / 2;
          positions[i + 1] = 0;
          positions[i + 2] = iy * SEPARATION - (this.amountY * SEPARATION) / 2;
          scales[j] = 1;
          i += 3;
          j++;
        }
      }

      const geometry = new THREE.BufferGeometry();
      geometry.setAttribute(
        "position",
        new THREE.BufferAttribute(positions, 3)
      );
      geometry.setAttribute("scale", new THREE.BufferAttribute(scales, 1));
      // 初始化粒子材质
      const material = new THREE.ShaderMaterial({
        uniforms: {
          color: { value: new THREE.Color(this.color) },
        },
        vertexShader: `
          attribute float scale;
          void main() {
            vec4 mvPosition = modelViewMatrix * vec4( position, 2.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);

      this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
      this.renderer.setSize(container.clientWidth, container.clientHeight);
      this.renderer.setPixelRatio(window.devicePixelRatio);
      this.renderer.setClearAlpha(0);
      container.appendChild(this.renderer.domElement);

      window.addEventListener("resize", this.onWindowResize, {
        passive: false,
      });
      document.addEventListener("mousemove", this.onDocumentMouseMove, {
        passive: false,
      });
      document.addEventListener("touchstart", this.onDocumentTouchStart, {
        passive: false,
      });
      document.addEventListener("touchmove", this.onDocumentTouchMove, {
        passive: false,
      });
    },
    render: function () {
      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;
      let 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) * 100 +
            Math.sin((iy + this.count) * 0.5) * 100;
          scales[j] =
            (Math.sin((ix + this.count) * 0.3) + 1) * 8 +
            (Math.sin((iy + this.count) * 0.5) + 1) * 8;
          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;
    },
    animate: function () {
      requestAnimationFrame(this.animate);
      this.render();
    },
    onDocumentMouseMove: function (event) {
      this.mouseX = event.clientX - this.windowHalfX;
    },
    onDocumentTouchStart: function (event) {
      if (event.touches.length === 1) {
        this.mouseX = event.touches[0].pageX - this.windowHalfX;
      }
    },
    onDocumentTouchMove: function (event) {
      if (event.touches.length === 1) {
        event.preventDefault();
        this.mouseX = event.touches[0].pageX - this.windowHalfX;
      }
    },
    onWindowResize: function () {
      console.log("onWindowResize");
      this.windowHalfX = window.innerWidth / 2;
      this.camera.aspect = window.innerWidth / window.innerHeight;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(window.innerWidth, window.innerHeight);
    },
  },
};
</script>
 
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Three.js实现星云效果,可以按照以下步骤进行: 1. 引入Three.js库文件和需要的插件 ``` <script src="https://threejs.org/build/three.min.js"></script> <script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script> ``` 2. 创建场景、相机和渲染器 ``` var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.z = 5; var renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); ``` 3. 创建星云材质 ``` var starMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 0.1, map: THREE.ImageUtils.loadTexture( "https://threejs.org/examples/textures/sprites/disc.png" ), blending: THREE.AdditiveBlending, transparent: true, depthWrite: false }); ``` 4. 创建星云模型 ``` var starGeometry = new THREE.Geometry(); for (var i = 0; i < 10000; i++) { var star = new THREE.Vector3(); star.x = THREE.Math.randFloatSpread(2000); star.y = THREE.Math.randFloatSpread(2000); star.z = THREE.Math.randFloatSpread(2000); starGeometry.vertices.push(star); } var stars = new THREE.Points(starGeometry, starMaterial); scene.add(stars); ``` 5. 创建控制器,实现交互操作 ``` var controls = new THREE.OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.25; controls.enableZoom = false; ``` 6. 渲染场景 ``` function animate() { requestAnimationFrame(animate); controls.update(); renderer.render(scene, camera); } animate(); ``` 7. 完整代码示例 ``` <!DOCTYPE html> <html> <head> <title>Starfield Simulation</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> body { margin: 0; padding: 0; overflow: hidden; } </style> </head> <body> <script src="https://threejs.org/build/three.min.js"></script> <script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script> <script> var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.z = 5; var renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); var starMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 0.1, map: THREE.ImageUtils.loadTexture( "https://threejs.org/examples/textures/sprites/disc.png" ), blending: THREE.AdditiveBlending, transparent: true, depthWrite: false }); var starGeometry = new THREE.Geometry(); for (var i = 0; i < 10000; i++) { var star = new THREE.Vector3(); star.x = THREE.Math.randFloatSpread(2000); star.y = THREE.Math.randFloatSpread(2000); star.z = THREE.Math.randFloatSpread(2000); starGeometry.vertices.push(star); } var stars = new THREE.Points(starGeometry, starMaterial); scene.add(stars); var controls = new THREE.OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.25; controls.enableZoom = false; function animate() { requestAnimationFrame(animate); controls.update(); renderer.render(scene, camera); } animate(); </script> </body> </html> ``` 这样就可以在Vue项目中使用Three.js实现星云效果了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值