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 地球应用。接下来,你可以尝试:
- 添加更多标记和信息窗口。
- 实现地球表面动态数据展示。
- 优化性能,支持移动设备。
快动手试试吧!
热门推荐
告别“星期鱼”烦恼!新手养鱼秘密大公开!
搞BIM建模有前途吗
乙庚合化金八字命理(乙庚合化金有什么好处什么意思)
项目立项管理中的技术可行性分析:关键评估指标
家庭对个人成长的影响:从原生家庭到新生家庭
乳制品替代品市场研究报告:2025-2032年全球市场趋势与预测
城里人和农村人的区别
白酒股,玩的就是心跳?
秒懂!100以内数字辨别法,轻松掌握数字规律!
现值概念在会计要素计量属性中的应用与实践
一个记忆思维模型助你成为背诵达人丨自我管理
什么是TIF格式?
石雕花窗的图案解析:背后的历史与文化故事(多图欣赏)
如来佛祖为何设下真假美猴王赌局?孙悟空如何战胜内心的二心魔障
2025年券商重组仍是重头戏,将沿着三条主线演进
复兴号技术提升型智能动车组
普朗克黑体辐射理论:量子论的起源
在家制作冷萃咖啡的详细指南:简单步骤和专家技巧解析
宿舍床尺寸的重要性与选择指南,提升生活与学习舒适度
爱快和OpenWrt在网络安全策略上的不同
梦泪在电竞领域的影响力有多大?他对lpl赛事经理角色有何贡献?
多维度数据分析:从数据视角到业务思维的转变
数治入门 | 数据资产化过程中的合规审查与登记实施
如何成功安装自流平砂浆?
婚前协议怎么避免婚姻风险
沉浸式RPG《天国:拯救2》体验:中世纪波西米亚的深度之旅
网络小说大神级的剧情设计方法:扩展与精简
新交房小区电梯频出故障 太原杏花岭区回应
新房装修开荒保洁多少钱每平方,如何找到合适的服务?
盘口分析:如何通过盘口信息做出明智的投资决策?