three.js三维地球

1、在vue项目中安装依赖: npm i three

2、案例一代码如下:

<template>  
  <div ref="earthContainer" class="earth-container"></div>  
</template>  
  
<script>  
import * as THREE from 'three';  
import { ref,onMounted } from 'vue'
  import { gsap } from 'gsap'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; 
import earth from "../../../assets/images/earth.jpg";
import xingqiu from "../../../assets/images/xingqiu.png";
import yueqiu from "../../../assets/images/yueqiu.png";
import guanghuan from "../../../assets/images/guanghuan.png";
import wl from "../../../assets/images/wl.png";
import guangzhu from "../../../assets/images/guangzhu.png";
import bg13 from "../../../assets/images/bgImg/bg13.png";
  
export default {  
  name: 'Earth3D',  
  mounted() {  
    this.initThree();  
    window.addEventListener('resize', this.onWindowResize, false);  
  },  
  beforeDestroy() {  
    window.removeEventListener('resize', this.onWindowResize, false);  
  },  
  methods: {
    initThree() {
      const width = this.$refs.earthContainer.clientWidth;  
      const height = this.$refs.earthContainer.clientHeight;  
  
      // 创建场景  
      const scene = new THREE.Scene();  
  
      // 创建相机  
      const camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);  
      // camera.position.z = 1;  
      camera.position.set(0,50,100)

      // 创建渲染器  
      const renderer = new THREE.WebGLRenderer();  
      renderer.setSize(width, height);  
      this.$refs.earthContainer.appendChild(renderer.domElement);  

      // 设置背景色
      renderer.setClearColor(0x000520, 1); // 使用十六进制颜色代码设置红色调,第二个参数是透明度(1表示不透明) 
  
      // 创建地球纹理  
      const loader = new THREE.TextureLoader();  
      const earthTexture = loader.load(earth);  
      earthTexture.wrapS = THREE.RepeatWrapping;  
      earthTexture.wrapT = THREE.RepeatWrapping;  
      earthTexture.repeat.set(1, 1);  
  
      // 创建地球几何体和材质  
      const geometry = new THREE.SphereGeometry(50, 128, 128);  
      const material = new THREE.MeshBasicMaterial({ map: earthTexture });  
  
      // 创建地球网格  
      const earthMesh = new THREE.Mesh(geometry, material);  
      scene.add(earthMesh);  

      //【星空背景图开始------------------------------------------------------------------------------------------------------------------】
      // 创建材质并设置属性  
      const xingqiuTexture = loader.load(xingqiu);  
      const starsMaterial = new THREE.PointsMaterial({  
      map:xingqiuTexture,
      size: 1,  
      transparent: true,  
      opacity: 1,  
      vertexColors: true, // 启用顶点颜色  
      blending: THREE.AdditiveBlending,  
      sizeAttenuation: true // 根据摄像机距离调整粒子大小,通常设置为false  
      });  
      
      // 使用BufferGeometry创建星星的几何体  
      const starsGeometry = new THREE.BufferGeometry();  
      
      // 设置顶点位置数据  
      const positions = [];  
      const sizes = []; // 用于存储随机大小的数组  
      for (var i = 0; i < 10000; i++) {  
      var vertex = new THREE.Vector3();  
      vertex.x = Math.random() * 2 - 1;  
      vertex.y = Math.random() * 2 - 1;  
      vertex.z = Math.random() * 2 - 1;  
      positions.push(vertex.x, vertex.y, vertex.z); 
      
      // 随机生成星星的大小,例如介于0.5和3之间  
      const randomSize = Math.random() * 2.5 + 0.5;  
      sizes.push(randomSize);  
      }  
      
      // 设置顶点颜色数据  
      const colors = [];  
      for (var i = 0; i < 10000; i++) {  
      var color = new THREE.Color();  
      color.setHSL(Math.random() * 0.2 + 0.5, 0.55, Math.random() * 0.25 + 0.55);  
      colors.push(color.r, color.g, color.b);  
      }  
      
      // 将位置数据设置为几何体的属性  
      starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));  
      // 将颜色数据设置为几何体的属性  
      starsGeometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));  
      // 设置顶点大小数据为属性  
      starsGeometry.setAttribute('size', new THREE.Float32BufferAttribute(sizes, 1));  
      
      // 使用Points创建粒子系统  
      const stars = new THREE.Points(starsGeometry, starsMaterial);  
      stars.scale.set(500, 500, 500);  
      
      // 将星星添加到场景中  
      scene.add(stars); 
      // 【星空背景图结束 ------------------------------------------------------------------------------------------------------------------ 】

      // 【月球环形开始 ------------------------------------------------------------------------------------------------------------------ 】
      // 创建月球环
      // 设置环形运动的半径和速度  
      const radius = 65;  
      let moonRingTexture = new THREE.TextureLoader().load(guanghuan);
      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(radius-2, radius+2, 64);
      let moonRing = new THREE.Mesh(moonRingGeometry, moonRingMaterial);
      moonRing.rotation.x = -Math.PI / 2;
      scene.add(moonRing);
      // 【月球环形结束 ------------------------------------------------------------------------------------------------------------------ 】

      // 【绕地球运行的月球开始------------------------------------------------------------------------------------------------------------------】
      let moonTexture = new THREE.TextureLoader().load(yueqiu);
      let moonMaterial = new THREE.MeshStandardMaterial({
      map: moonTexture,
      emissive: 0xffffff,
      emissiveMap: moonTexture,
      });
      let moonGeometry = new THREE.SphereGeometry(2, 32, 32);
      let moon = new THREE.Mesh(moonGeometry, moonMaterial);
      scene.add(moon);
      const speed = 0.1;  
      // 初始化月球的起始位置  
      moon.position.set(radius, 0, 0);  
      // 声明一个全局的 clock 变量  
      let clock = 0;  
      // 【绕地球运行的月球结束 ------------------------------------------------------------------------------------------------------------------】

      // 【光柱开始------------------------------------------------------------------------------------------------------------------】
      for (let i = 0; i < 30; i++) {
          // 实现光柱
          let lightPillarTexture = new THREE.TextureLoader().load(yueqiu);
          let lightPillarGeometry = new THREE.PlaneGeometry(1, 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 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 circlePlane = new THREE.PlaneGeometry(6, 6);
          let circleTexture = new THREE.TextureLoader().load(wl);
          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",
          });
      }
          // 【光柱结束------------------------------------------------------------------------------------------------------------------】

      // 【添加鼠标拖拽控制开始------------------------------------------------------------------------------------------------------------------】
      const controls = new OrbitControls(camera, renderer.domElement); 
      // 【鼠标拖拽控制结束------------------------------------------------------------------------------------------------------------------】
  
      // 【创建地球自转动画、星空背景动画开始-----------------------------------------------------------------------】
      const animate = () => {
           // 【地球自转速度】
          requestAnimationFrame(animate);  
          earthMesh.rotation.y += 0.002;  

          // 【更新星星位置,以创建移动的星空背景效果】
          const positions = starsGeometry.attributes.position.array;  
          for (let i = 0; i < positions.length; i += 3) {  
              // 缓慢移动星星  
              positions[i] +=  0.00003;  
              positions[i + 1] +=  0.00003;  
              positions[i + 2] +=  0.00003;  
          }  
          starsGeometry.attributes.position.needsUpdate = true; // 标记属性已更新 

          // 【更新月球的位置,使月球绕地球运动】
          // 更新月球的位置  
          moon.position.x = Math.cos(clock) * radius;  
          moon.position.z = Math.sin(clock) * radius;  
          // 更新时钟以控制速度  
          clock += speed;  

          renderer.render(scene, camera);  
      };  
      animate();
      // 【创建地球自转动画、星空背景动画结束-----------------------------------------------------------------------】
  
      // 窗口大小变化时的处理函数  
      this.onWindowResize = () => {  
        const width = this.$refs.earthContainer.clientWidth;  
        const height = this.$refs.earthContainer.clientHeight;  
        renderer.setSize(width, height);  
        camera.aspect = width / height;  
        camera.updateProjectionMatrix();  
      };  
    },  
  },  
};  

  // 经纬度转换函数
  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)
  }
</script>  
  
<style scoped>  
.earth-container {  
  width: 100vw;  
  height: 100vh; /* 或者你想要的任何高度 */  
  position: relative;
}  
</style>

 案例二:

设置透明背景:

<!-- 
	将背景改为透明:
	步骤一:给body设置背景色
		<style>
			html, body {height: 100%;width: 100%;background-color: transparent;}
		</style>
	步骤二:在function initRenderer()方法中设置
		renderer = new THREE.WebGLRenderer({ alpha: true});  
		renderer.setClearColor(0x000520, 0); // 使用十六进制颜色代码设置红色调,第二个参数是透明度(1表示不透明) 
	步骤三:function initScene()方法中去掉scene.background = new THREE.Color( bgcolor );,即不设置背景色,去掉后如下
		scene = new THREE.Scene();
		scene.fog = new THREE.Fog( 0x020924, 200, 1000 );
		window.scene = scene;
 -->

代码:

效果:

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值