美文网首页
threejs-3D酷炫地球

threejs-3D酷炫地球

作者: Y_Jaaao | 来源:发表于2023-09-03 15:15 被阅读0次
    <template>
      <div class="home">
        <div class="canvas-container" ref="screenDom" />
      </div>
    </template>
    
    <script setup>
    import * as THREE from 'three';
    import { onMounted, reactive, ref } from "vue";
    import { gsap } from 'gsap';
    import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
    let screenDom = ref(null)
    let progress = ref(0)
    
    const lon2xyz = (R, longitude, latitude) => {
      let lon = (longitude * Math.PI) / 180; // 转弧度值
      const lat = (latitude * Math.PI) / 180; // 转弧度值
      lon = -lon; // js坐标系z坐标轴对应经度-90度,而不是90度
    
      // 经纬度坐标转球面坐标计算公式
      const x = R * Math.cos(lat) * Math.cos(lon);
      const y = R * Math.sin(lat);
      const z = R * Math.cos(lat) * Math.sin(lon);
      // 返回球面坐标
      return new THREE.Vector3(x, y, z);
    };
    
    onMounted(() => {
      //创建场景
      let scene = new THREE.Scene();
      // 创建相机
      let camera = new THREE.PerspectiveCamera(
        45,
        window.innerWidth / window.innerHeight,
        0.1,
        100000
      );
      camera.position.set(0, 50, 300)
      //创建渲染器
      let renderer = new THREE.WebGLRenderer({ antialias: true })
      renderer.setSize(window.innerWidth, window.innerHeight)
      //将画布添加到页面中
      screenDom.value.appendChild(renderer.domElement)
    
      //创建控制器
      let controls = new OrbitControls(camera, renderer.domElement)
      controls.autoRotate = true; //自动旋转
    
      //创建星空背景
      scene.background = new THREE.Color(0x030311);
      //使用点材质创建星空效果
      const vertices = [];
      for (let i = 0; i < 500; i++) {
        const vertex = new THREE.Vector3();
        vertex.x = Math.random() * 800 - 400;
        vertex.y = Math.random() * 800 - 400;
        vertex.z = Math.random() * 800 - 400;
        vertices.push(vertex.x, vertex.y, vertex.z);
      }
    
      //星空效果
      let starsGeometry = new THREE.BufferGeometry();
      starsGeometry.setAttribute(
        "position",
        new THREE.BufferAttribute(new Float32Array(vertices), 3)
      );
    
      //加载点材质纹理
      const starsTexture = new THREE.TextureLoader().load('./images/stars.png')
      const starsMaterial = new THREE.PointsMaterial({
        map:starsTexture,
        size: 2,
        sizeAttenuation: true, //尺寸衰减
        color: 0x44d76cf,
        transparent: true, //透明度
        opacity: 1
      })
      let stars = new THREE.Points(starsGeometry, starsMaterial);
      scene.add(stars);
      
      // 创建地球
      let earthTexture = new THREE.TextureLoader().load('./images/map.jpg');
      let earthGeometry = new THREE.SphereGeometry(50,32,32)
      
      let earthMaterial = new THREE.MeshBasicMaterial({
        map:earthTexture
      })
      let earth = new THREE.Mesh(earthGeometry,earthMaterial)
      scene.add(earth)
      // 创建发光的地球
      let lightEarthGeometry = new THREE.SphereGeometry(53,32,32)
      let lightTexture = new THREE.TextureLoader().load('./images/earth.jpg');
      
      let lightEarthMaterial = new THREE.MeshBasicMaterial({
        map: lightTexture,
        alphaMap: lightTexture,
        blending: THREE.AdditiveBlending,
        transparent: true,
      })
      let lightEarth = new THREE.Mesh(lightEarthGeometry, lightEarthMaterial)
      scene.add(lightEarth)
    
      // 添加地球外发光精灵
      let spriteTexture = new THREE.TextureLoader().load('./images/glow.png');
      let spriteMaterial = new THREE.SpriteMaterial({
        map: spriteTexture,
        transparent: true,
        color:0x4d76cf,
        depthWrite:false,
        depthTest:false,
        blending: THREE.AdditiveBlending
      })
      let sprite = new THREE.Sprite(spriteMaterial);
      sprite.scale.set(155, 155, 0);
      scene.add(sprite);
      //内发光
      let spriteTexture1 = new THREE.TextureLoader().load('./images/innerGlow.png');
      let spriteMaterial1 = new THREE.SpriteMaterial({
        map: spriteTexture1,
        transparent: true,
        color:0x4d76cf,
        depthWrite:false,
        depthTest:false,
        blending: THREE.AdditiveBlending
      })
      let sprite1 = new THREE.Sprite(spriteMaterial1);
      sprite1.scale.set(128, 128, 0);
      scene.add(sprite1);
      // let scale = new THREE.Vector3(1, 1, 1);
    
      for (let i = 0; i < 30; i++) {
         // 实现光柱
         let lightPillarTexture = new THREE.TextureLoader().load(
          "./images/light_column.png"
         );
         let lightPillarGeometry = new THREE.PlaneGeometry(3, 20);
         let lightPillarMaterial = new THREE.MeshBasicMaterial({
          color:0xffffff,
          map:lightPillarTexture,
          alphaMap:lightPillarTexture,
          transparent: true,
          blending: THREE.AdditiveBlending,
          side:THREE.DoubleSide,
          depthWrite:false
         })
         let lightPillar = new THREE.Mesh(lightPillarGeometry, lightPillarMaterial);
         lightPillar.add(lightPillar.clone().rotateY(Math.PI / 2));
    
         //创建波纹扩散效果
         let circlePlane = new THREE.PlaneGeometry(6,6); 
         let circleTexture = new THREE.TextureLoader().load("./images/label.png");
         let circleMaterial = new THREE.MeshBasicMaterial({
          color:0xffffff,
          map:circleTexture,
          transparent: true,
          blending: THREE.AdditiveBlending,
          depthWrite:false,
          side:THREE.DoubleSide,
         })
         let circleMesh = new THREE.Mesh(circlePlane,circleMaterial);
         circleMesh.rotation.x = -Math.PI /2;
         circleMesh.position.set(0,-7,0);
         lightPillar.add(circleMesh);
    
         gsap.to(circleMesh.scale, {
          duration: 1 + Math.random() * 0.5,
          x: 2,
          y: 2,
          z: 2,
          repeat: -1,
          delay: Math.random() * 0.5,
          yoyo: true,
          ease: "power2.inOut",
        });
        // 设置光柱的位置
        let lat = Math.random() * 180 - 90;
        let lon = Math.random() * 360 - 180;
        let position = lon2xyz(60, lon, lat);
        lightPillar.position.set(position.x, position.y, position.z);
    
        lightPillar.quaternion.setFromUnitVectors(
          new THREE.Vector3(0, 1, 0),
          position.clone().normalize()
        )
        scene.add(lightPillar)
      }
      
      // 绕地球运行的月球
      let moonTexture = new THREE.TextureLoader().load("./images/moon.jpg");
      let moonGeometry = new THREE.SphereGeometry(5,32,32)
      let moonMaterial = new THREE.MeshBasicMaterial({
        map:moonTexture,
        emissive:0xffffff,
        emissiveMap :moonTexture
      })
      let moon = new THREE.Mesh(moonGeometry,moonMaterial)
      moon.position.set(150,0,0)
      scene.add(moon)
      // 创建月球环
        let moonRingTexture = new THREE.TextureLoader().load(
        "./images/moon_ring.png"
      );
      let moonRingMaterial = new THREE.MeshBasicMaterial({
        map: moonRingTexture,
        transparent: true,
        blending: THREE.AdditiveBlending,
        side: THREE.DoubleSide,
        depthWrite: false,
        opacity: 0.5,
      });
      let moonRingGeometry = new THREE.RingGeometry(145, 155, 64);
      let moonRing = new THREE.Mesh(moonRingGeometry, moonRingMaterial);
      moonRing.rotation.x = -Math.PI / 2;
      scene.add(moonRing);
    
      let time = {
        value: 0
      };
      gsap.to(time, {
        value: 1,
        duration: 10,
        repeat: -1,
        ease: "linear",
        //月球每次旋转位置更新位置
        onUpdate: () => {
          moon.position.x = 150 * Math.cos(time.value * Math.PI * 2);
          moon.position.z = 150 * Math.sin(time.value * Math.PI * 2);
          moon.rotation.y = time.value * Math.PI * 8;
        },
      });
    
      function render() {
        controls.update();
        requestAnimationFrame(render);
        renderer.render(scene, camera);
      }
      render();
    
      THREE.DefaultLoadingManager.onProgress = function (item, loaded, total) {
        console.log(item, loaded, total);
        progress.value = new Number((loaded / total) * 100).toFixed(2)
      }
    })
    </script>
    <style>
    * {
      margin: 0;
      padding: 0;
    }
    body {
      background-color: #000;
    }
    .canvas-container {
      width: 100vw;
      height: 100vh;
    }
    </style>
    
    image.png

    相关文章

      网友评论

          本文标题:threejs-3D酷炫地球

          本文链接:https://www.haomeiwen.com/subject/akpfvdtx.html