用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开发,期待在评论区看到大家的创意实现!

相关推荐
用户2519162427113 小时前
Canvas之图形变换
前端·javascript·canvas
康康的幸福生活4 小时前
webgl2 方法解析: layout - glsl 300 es版本
前端·javascript·webgl
寅时码10 小时前
我开源了一款 Canvas “瑞士军刀”,十几种“特效与工具”开箱即用
前端·开源·canvas
德育处主任1 天前
p5.js 用 beginGeometry () 和 endGeometry () 打造自定义 3D 模型
前端·前端框架·canvas
庖丁解牛2 天前
WebGL第四十五课:研究一下shader中的随机数
webgl·游戏开发·计算机图形学
德育处主任3 天前
p5.js 3D模型(model)入门指南
前端·前端框架·canvas
烛阴4 天前
ABS - Rhomb
前端·webgl
VincentFHR4 天前
Three.js 利用 shader 实现 3D 热力图
前端·three.js·canvas
德育处主任5 天前
p5.js 加载 3D 模型(loadModel)
前端·数据可视化·canvas