3D 地球仪
创作时间:
作者:
@小白创作中心
3D 地球仪
引用
CSDN
1.
https://blog.csdn.net/mmc123125/article/details/145206500
在网页上展示一个可以交互的 3D 地球,不仅酷炫,还能带来极佳的用户体验!Three.js 是一个强大的 WebGL 库,可以帮助我们轻松实现这一点。本教程将带你从零开始,构建一个交互式地球仪,并添加自定义的交互效果。
一、准备工作
在开始之前,确保你已具备以下条件:
- 安装了 Node.js 环境。
- 新建了一个项目文件夹并初始化 npm。
- 安装了 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 地球应用。接下来,你可以尝试:
- 添加更多标记和信息窗口。
- 实现地球表面动态数据展示。
- 优化性能,支持移动设备。
快动手试试吧!
热门推荐
天麻的生长环境及适宜种植地方(探究天麻生长的要求和种植技巧)
土壤盐分累积影响蔬菜生长!桃改场最新技术找回土地生命力、产量增45%!
世界之巅有多冷?——珠穆朗瑪峰頂的天氣與溫度
第一次攀登珠穆朗玛峰:挑战极限的壮丽征程
曼城4-1大胜西汉姆联:瓜迪奥拉战术布局下的完美演出
曼城遭遇伤病潮,瓜迪奥拉如何应对?
曼城冬窗豪掷2.18亿!马尔穆什领衔三大新援,瓜迪奥拉打造新王朝
世界第二难爬的山峰:乔戈里峰的致命诱惑
1986年巴基斯坦乔格里峰山难:登山探险的至暗时刻
ISO14001:打造高效环境管理体系的金钥匙
数字化转型助力制造业应对环境管理新挑战
西门子洗衣机突然不通电,具体原因和解决方法
2025年最火猪猪侠手游推荐:5款新作各具特色,总有一款点燃你的童年梦想
成都可可豆和光线传媒如何打造《哪吒2》特效?
猪猪侠大电影:哪一部让你笑到肚子疼?
鬼谷八荒剑修全攻略:功法技能身法神通与顶级武器
如何确保房产土地证件的办理?这些证件怎样保障业主的权益?
瓦良格号给了中国多大震撼?我国专家:苏联的钢材与技术太先进
听见涛声:青春记忆里的那片海
《枫桥夜泊》如何成就《涛声依旧》?
《涛声依旧》:一首歌见证中国流行音乐的黄金时代
《涛声依旧》:一首歌见证广东乐坛的黄金时代
盘山:天津的自然明珠
天津古文化街探秘:天后宫的历史回响
为什么中国四大高原里没有帕米尔高原?
社交媒体寻亲攻略:让科技助力团圆
仙剑98柔情版存档丢失?教你妙招恢复!
为啥北方吃的羊肉不膻,南方吃的却很膻?原因是啥?
羊肉清洗秘籍:一招洗净不膻不腥,美味又健康
成都首个轻资产大悦城延期一年未建成 未来品牌运营方向成谜