用Three.js打造炫酷3D地球:从入门到实现交互式体验

大家好,我是FogLetter,今天给大家带来一篇关于使用Three.js创建3D地球的完整教程。最近看了一下小米SU7官网用WebGL实现的酷炫3D交互效果,让我也想带大家探索一下3D网页开发的魅力!

一、为什么选择Three.js?

在开始代码之前,我们先聊聊为什么Three.js如此受欢迎。Three.js是一个基于WebGL的JavaScript 3D库,它让3D图形开发变得简单易用。就像小米SU7官网展示的那样,3D技术可以带来:

  1. 沉浸式体验:比传统2D更吸引眼球
  2. 跨平台兼容:无论是手机还是电脑都能流畅运行
  3. 病毒式传播潜力:酷炫的效果更容易被分享到朋友圈或短视频平台

二、基础准备: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场景需要几个基本要素:

  1. 场景(Scene):所有物体的容器
  2. 相机(Camera):观察场景的视角
  3. 渲染器(Renderer):将3D场景渲染到2D屏幕
  4. 物体(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场景搭建
  • 地球纹理加载和显示
  • 鼠标交互效果
  • 平滑的动画渲染

未来可以进一步探索:

  1. 添加3D标记点显示城市位置
  2. 实现地球到具体国家的缩放过渡
  3. 集成VR支持,打造沉浸式体验

就像小米SU7官网展示的那样,WebGL和Three.js为我们打开了网页3D交互的大门。希望这篇教程能帮助你入门Three.js开发,期待在评论区看到大家的创意实现!

相关推荐
sin°θ_陈2 天前
前馈式3D Gaussian Splatting 研究地图(路线二):几何优先的前馈式 3DGS——前馈式 3DGS 如何重新拥抱多视图几何
深度学习·3d·webgl·三维重建·空间计算·3dgs·空间智能
星河耀银海3 天前
3D效果:HTML5 WebGL结合AI实现智能3D场景渲染
前端·人工智能·深度学习·3d·html5·webgl
点量云实时渲染-小芹3 天前
Unity模型数字孪生虚拟仿真webgl推流卡实时云渲染推流
unity·webgl·数字孪生·实时云渲染·虚拟仿真·云推流
WebGISer_白茶乌龙桃5 天前
基于 Cesium 的 GLB 建筑模型分层分房间点击拾取技术实现
前端·javascript·vue.js·webgl·cesium
sin°θ_陈5 天前
前馈式3D Gaussian Splatting 研究地图(路线一):像素对齐高斯的起点——pixelSplat 与 latentSplat 在解决什么
python·深度学习·3d·aigc·webgl·3dgs·空间智能
就是个名称5 天前
Chrome使用cesium.js或者three.js报错不支持webGL
javascript·chrome·webgl
烛阴5 天前
Three.js 场景完全入门指南:让你的 3D 场景不在乱成一团
webgl·three.js
EliseL6 天前
SuperMap iClient3D for WebGL 如何实时汇报相机位置天气情况
javascript·3d·html·webgl
ct9786 天前
Cesium的时间与时钟系统
gis·webgl·cesium
Jay-r6 天前
樱花雨特效 WebGL实现 短视频同款浪漫视觉效果(附源码下载)
开发语言·javascript·ecmascript·编程·webgl·代码·樱花雨