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;
-->
代码:
效果: