大家好,我是FogLetter,今天给大家带来一篇关于使用Three.js创建3D地球的完整教程。最近看了一下小米SU7官网用WebGL实现的酷炫3D交互效果,让我也想带大家探索一下3D网页开发的魅力!
一、为什么选择Three.js?
在开始代码之前,我们先聊聊为什么Three.js如此受欢迎。Three.js是一个基于WebGL的JavaScript 3D库,它让3D图形开发变得简单易用。就像小米SU7官网展示的那样,3D技术可以带来:
- 沉浸式体验:比传统2D更吸引眼球
- 跨平台兼容:无论是手机还是电脑都能流畅运行
- 病毒式传播潜力:酷炫的效果更容易被分享到朋友圈或短视频平台
二、基础准备:HTML5 Canvas
所有3D魔法都始于一个简单的HTML元素------<canvas>
标签。它就像一块数字画布,我们可以在上面绘制2D或3D图形。
html
<canvas id="webglcanvas"></canvas>
获取画布和上下文:
javascript
const canvas = document.getElementById('webglcanvas');
const ctx = canvas.getContext('2d');
虽然我们可以用原生Canvas API画一个简单的2D圆(就像下面这样),但今天我们追求的是更酷的3D效果!
javascript
ctx.beginPath();
ctx.arc(x, y, radius, startAngle, endAngle, counterClickwise);
ctx.fillStyle = 'green';
ctx.fill();
ctx.closePath();
三、Three.js核心概念
在Three.js的世界里,构建3D场景需要几个基本要素:
- 场景(Scene):所有物体的容器
- 相机(Camera):观察场景的视角
- 渲染器(Renderer):将3D场景渲染到2D屏幕
- 物体(Mesh):由几何体(Geometry)和材质(Material)组成
四、实战:创建3D地球

1. 初始化场景
首先引入Three.js库:
html
<script src="https://cdn.bootcss.com/three.js/r83/three.min.js"></script>
然后设置基础结构:
javascript
let canvas, camera, scene, renderer, group;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
function init() {
// 获取Canvas元素
canvas = document.getElementById('webglcanvas');
// 创建透视相机 (视野角度, 宽高比, 近裁剪面, 远裁剪面)
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 2000);
camera.position.z = 500; // 相机位置
// 创建场景
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff); // 白色背景
// 创建组
group = new THREE.Group();
scene.add(group);
}
2. 加载地球纹理
地球之所以看起来真实,关键在于纹理贴图。我们使用TextureLoader
加载一张地球表面图片:
javascript
let loader = new THREE.TextureLoader();
loader.load('land_ocean_ice_cloud.jpg', function(texture) {
// 创建球体几何 (半径, 宽度分段, 高度分段)
let geometry = new THREE.SphereGeometry(200, 20, 20);
// 创建基础材质并应用纹理
let material = new THREE.MeshBasicMaterial({
map: texture
});
// 创建网格对象
let mesh = new THREE.Mesh(geometry, material);
group.add(mesh);
// 初始化渲染器
renderer = new THREE.WebGLRenderer({
canvas: canvas,
antialias: true // 开启抗锯齿
});
renderer.setSize(window.innerWidth, window.innerHeight);
// 开始动画循环
animate();
});
3. 添加交互效果
为了让地球更生动,我们添加鼠标交互,让地球跟随鼠标移动:
javascript
// 鼠标移动事件监听
document.addEventListener('mousemove', onDocumentMouseMove, false);
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX);
mouseY = (event.clientY - windowHalfY);
}
4. 动画循环
Three.js使用requestAnimationFrame
实现平滑动画:
javascript
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
// 相机跟随鼠标移动(带缓动效果)
camera.position.x += (mouseX - camera.position.x) * 0.005;
camera.position.y += (mouseY - camera.position.y) * 0.005;
// 相机始终看向场景中心
camera.lookAt(scene.position);
// 地球自转
group.rotation.y -= 0.005;
// 渲染场景
renderer.render(scene, camera);
}
五、优化与进阶
1. 性能优化
- 减少几何体的分段数(在效果可接受范围内)
- 使用合适的材质类型(
MeshBasicMaterial
性能最好)
2. 视觉效果增强
- 添加云层(使用透明纹理叠加)
- 实现昼夜效果(通过灯光和材质调整)
- 添加星空背景
3. 响应式设计
别忘了处理窗口大小变化:
javascript
window.addEventListener('resize', function() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
六、完整代码回顾
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>
<script src="https://cdn.bootcss.com/three.js/r83/three.min.js"></script>
</head>
<body>
<canvas id="webglcanvas"></canvas>
<script>
let canvas, camera, scene, renderer, group;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
init();
function init() {
canvas = document.getElementById('webglcanvas');
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 2000);
camera.position.z = 500;
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
group = new THREE.Group();
scene.add(group);
let loader = new THREE.TextureLoader();
loader.load('land_ocean_ice_cloud.jpg', function(texture) {
let geometry = new THREE.SphereGeometry(200, 20, 20);
let material = new THREE.MeshBasicMaterial({ map: texture });
let mesh = new THREE.Mesh(geometry, material);
group.add(mesh);
renderer = new THREE.WebGLRenderer({
canvas: canvas,
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
animate();
document.addEventListener('mousemove', onDocumentMouseMove, false);
});
}
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX);
mouseY = (event.clientY - windowHalfY);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
camera.position.x += (mouseX - camera.position.x) * 0.005;
camera.position.y += (mouseY - camera.position.y) * 0.005;
camera.lookAt(scene.position);
group.rotation.y -= 0.005;
renderer.render(scene, camera);
}
</script>
</body>
</html>
七、总结与展望
通过这个简单的例子,我们实现了:
- 基本的Three.js场景搭建
- 地球纹理加载和显示
- 鼠标交互效果
- 平滑的动画渲染
未来可以进一步探索:
- 添加3D标记点显示城市位置
- 实现地球到具体国家的缩放过渡
- 集成VR支持,打造沉浸式体验
就像小米SU7官网展示的那样,WebGL和Three.js为我们打开了网页3D交互的大门。希望这篇教程能帮助你入门Three.js开发,期待在评论区看到大家的创意实现!