问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

3D 地球仪

创作时间:
作者:
@小白创作中心

3D 地球仪

引用
CSDN
1.
https://blog.csdn.net/mmc123125/article/details/145206500

在网页上展示一个可以交互的 3D 地球,不仅酷炫,还能带来极佳的用户体验!Three.js 是一个强大的 WebGL 库,可以帮助我们轻松实现这一点。本教程将带你从零开始,构建一个交互式地球仪,并添加自定义的交互效果。

一、准备工作

在开始之前,确保你已具备以下条件:

  1. 安装了 Node.js 环境。
  2. 新建了一个项目文件夹并初始化 npm。
  3. 安装了 Three.js。

1. 安装 Three.js

使用 npm 安装 Three.js:

npm install three

二、构建基础场景

我们首先创建一个包含地球模型的简单 Three.js 场景。

1. 初始化场景

创建一个 HTML 文件作为入口:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>3D 地球仪</title>
  <style>
    body { margin: 0; overflow: hidden; }
    canvas { display: block; }
  </style>
</head>
<body>
  <script type="module" src="app.js"></script>
</body>
</html>

在 app.js 中编写基础场景代码:

import * as THREE from 'three';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 5);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}
animate();

现在我们已经有了一个基础的 Three.js 场景。

三、绘制地球

1. 创建地球的球体

使用 THREE.SphereGeometry 创建一个球体,并加载地球纹理贴图。

const geometry = new THREE.SphereGeometry(1, 32, 32);
const textureLoader = new THREE.TextureLoader();
const earthTexture = textureLoader.load('https://example.com/earth_texture.jpg');
const material = new THREE.MeshStandardMaterial({ map: earthTexture });
const earth = new THREE.Mesh(geometry, material);
scene.add(earth);

2. 添加光源

为地球添加光照以突出细节。

const ambientLight = new THREE.AmbientLight(0x404040); // 环境光
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 1);
pointLight.position.set(5, 5, 5);
scene.add(pointLight);

3. 让地球自转

在动画循环中更新地球的旋转:

function animate() {
  requestAnimationFrame(animate);
  earth.rotation.y += 0.01; // 让地球缓慢自转
  renderer.render(scene, camera);
}

四、交互功能:拖拽与缩放

1. 引入 OrbitControls

使用 OrbitControls 实现场景的旋转、缩放和拖拽交互:

npm install three-orbitcontrols

然后在代码中引入:

import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true; // 启用阻尼效果(模拟惯性)
controls.dampingFactor = 0.05;

在 animate 函数中调用更新方法:

function animate() {
  requestAnimationFrame(animate);
  controls.update(); // 更新交互
  renderer.render(scene, camera);
}

现在,你可以拖动地球和滚动鼠标进行缩放了!

五、添加点标记与点击事件

1. 创建点标记

使用 THREE.Mesh 添加一些标记点来表示地球上的位置。

function createMarker(lat, lon) {
  const markerGeometry = new THREE.SphereGeometry(0.02, 16, 16);
  const markerMaterial = new THREE.MeshStandardMaterial({ color: 0xff0000 });
  const marker = new THREE.Mesh(markerGeometry, markerMaterial);
  // 将经纬度转换为 3D 坐标
  const phi = (90 - lat) * (Math.PI / 180);
  const theta = (lon + 180) * (Math.PI / 180);
  const radius = 1.01; // 稍微高出地球表面
  marker.position.set(
    radius * Math.sin(phi) * Math.cos(theta),
    radius * Math.cos(phi),
    radius * Math.sin(phi) * Math.sin(theta)
  );
  scene.add(marker);
}
createMarker(37.7749, -122.4194); // 例如,标记旧金山的位置

2. 实现点击事件

使用 Raycaster 检测鼠标点击的地球表面坐标。

const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
window.addEventListener('click', (event) => {
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
  raycaster.setFromCamera(mouse, camera);
  const intersects = raycaster.intersectObject(earth);
  if (intersects.length > 0) {
    console.log('点击了地球的坐标:', intersects[0].point);
  }
});

六、性能优化与附加功能

1. 使用高清纹理

你可以使用 NASA 提供的高清地球纹理,例如:

  • 地球表面纹理
  • 云层纹理

2. 添加星空背景

使用一个大球体作为背景,加载星空纹理:

const starsGeometry = new THREE.SphereGeometry(50, 64, 64);
const starsMaterial = new THREE.MeshBasicMaterial({
  map: textureLoader.load('https://example.com/stars_texture.jpg'),
  side: THREE.BackSide,
});
const stars = new THREE.Mesh(starsGeometry, starsMaterial);
scene.add(stars);

七、完整代码

import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 5);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
// 地球
const textureLoader = new THREE.TextureLoader();
const earthTexture = textureLoader.load('https://example.com/earth_texture.jpg');
const earthGeometry = new THREE.SphereGeometry(1, 32, 32);
const earthMaterial = new THREE.MeshStandardMaterial({ map: earthTexture });
const earth = new THREE.Mesh(earthGeometry, earthMaterial);
scene.add(earth);
// 光源
const ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 1);
pointLight.position.set(5, 5, 5);
scene.add(pointLight);
// 星空
const starsGeometry = new THREE.SphereGeometry(50, 64, 64);
const starsMaterial = new THREE.MeshBasicMaterial({
  map: textureLoader.load('https://example.com/stars_texture.jpg'),
  side: THREE.BackSide,
});
const stars = new THREE.Mesh(starsGeometry, starsMaterial);
scene.add(stars);
// 动画
function animate() {
  requestAnimationFrame(animate);
  earth.rotation.y += 0.005;
  controls.update();
  renderer.render(scene, camera);
}
animate();

八、总结

通过本文,你学会了如何使用 Three.js 绘制一个交互式地球仪。我们从基本的场景搭建,到实现交互和性能优化,一步步构建出一个完整的 3D 地球应用。接下来,你可以尝试:

  1. 添加更多标记和信息窗口。
  2. 实现地球表面动态数据展示。
  3. 优化性能,支持移动设备。

快动手试试吧!

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号