🌍 前言:前端的尽头是图形学?
你是否厌倦了每天写<div>、<span>和 CRUD?
在 2025 年,普通的 React/Vue 开发者已成红海,但掌握 3D 可视化的前端工程师依然稀缺,薪资通常高出 30%~50%。
今天,我们不讲复杂的数学公式,直接动手。用Three.js配合几张贴图,在浏览器里复刻一个**“流浪地球”风格的科幻地球仪**。
它包含:真实地形凹凸、海洋高光、大气层光晕、以及星空背景。
先看原理,再撸代码。
🧠 核心原理:地球不是一个“球”
在 3D 渲染中,想要逼真,不能只放一张照片。我们需要把地球拆解成**“图层”**。
这就像 PS 的图层叠加,我们需要由内而外构建 4 层结构:
graph TD Core[核心:球体 Geometry] --> Material[材质 Material] subgraph 纹理贴图层 Material -- 1. 基础颜色 --> Map[Diffuse Map: 决定陆地海洋颜色] Material -- 2. 地形凹凸 --> BumpMap[Bump Map: 决定山脉高度] Material -- 3. 海洋反光 --> SpecularMap[Specular Map: 让海洋反光 陆地不反光] end subgraph 大气层特效 Core -- 叠加 --> Cloud[云层: 独立的透明球体] Cloud -- 叠加 --> Glow[光晕: Shader 或 精灵图] end style Map fill:#e1f5fe,stroke:#01579b style Glow fill:#fff9c4,stroke:#fbc02d🛠️ 实战代码:100 行的奇迹
为了方便大家直接运行,我使用了 CDN 引入 Three.js,你可以直接创建一个index.html并在浏览器打开。
准备工作:
我们需要 3 张核心贴图(文末有获取方式):
earth.jpg(地球卫星图)bump.jpg(灰度图,越白的地方越高)specular.jpg(黑白图,海洋是白色的,陆地是黑色的)
完整源码:
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Three.js Wandering Earth</title><style>body{margin:0;overflow:hidden;background-color:#000;}</style><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script></head><body><divid="canvas-container"></div><script>// 1. 初始化场景、相机、渲染器constscene=newTHREE.Scene();// 雾化效果,模拟宇宙深处的幽暗scene.fog=newTHREE.FogExp2(0x000000,0.0008);constcamera=newTHREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);camera.position.z=15;// 相机距离constrenderer=newTHREE.WebGLRenderer({antialias:true});// 抗锯齿renderer.setSize(window.innerWidth,window.innerHeight);document.body.appendChild(renderer.domElement);// 2. 创建地球材质 (核心!)consttextureLoader=newTHREE.TextureLoader();constearthGeometry=newTHREE.SphereGeometry(5,64,64);// 半径5,高精度网格constearthMaterial=newTHREE.MeshPhongMaterial({map:textureLoader.load('https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/planets/earth_atmos_2048.jpg'),// 基础图bumpMap:textureLoader.load('https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/planets/earth_normal_2048.jpg'),// 凹凸图bumpScale:0.15,// 凹凸程度specularMap:textureLoader.load('https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/planets/earth_specular_2048.jpg'),// 高光图specular:newTHREE.Color('grey'),// 高光颜色shininess:10// 光泽度});constearth=newTHREE.Mesh(earthGeometry,earthMaterial);scene.add(earth);// 3. 创建大气层光晕 (简单的 Shader 模拟)constatmosphereGeo=newTHREE.SphereGeometry(5.3,64,64);constatmosphereMat=newTHREE.MeshPhongMaterial({color:0x00aaff,// 科幻蓝transparent:true,opacity:0.2,side:THREE.BackSide,// 渲染背面,制造边缘发光感blending:THREE.AdditiveBlending// 叠加混合模式});constatmosphere=newTHREE.Mesh(atmosphereGeo,atmosphereMat);scene.add(atmosphere);// 4. 打光 (科幻感的关键)constambientLight=newTHREE.AmbientLight(0x333333);// 环境微光scene.add(ambientLight);constsunLight=newTHREE.DirectionalLight(0xffffff,1);// 模拟太阳光sunLight.position.set(5,3,5);scene.add(sunLight);// 5. 满天星斗 (粒子系统)conststarGeo=newTHREE.BufferGeometry();conststarCount=2000;constposArray=newFloat32Array(starCount*3);for(leti=0;i<starCount*3;i++){posArray[i]=(Math.random()-0.5)*100;// 随机分布}starGeo.setAttribute('position',newTHREE.BufferAttribute(posArray,3));conststarMat=newTHREE.PointsMaterial({color:0xffffff,size:0.05});conststarMesh=newTHREE.Points(starGeo,starMat);scene.add(starMesh);// 6. 动画循环functionanimate(){requestAnimationFrame(animate);// 地球自转earth.rotation.y+=0.002;atmosphere.rotation.y+=0.002;// 星空缓慢旋转starMesh.rotation.y-=0.0005;renderer.render(scene,camera);}animate();// 窗口自适应window.addEventListener('resize',()=>{camera.aspect=window.innerWidth/window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth,window.innerHeight);});</script></body></html>运行图如下
🎨 代码解析:为什么这么写才“炫”?
- MeshPhongMaterial:
这是 Three.js 中用于模拟有光泽表面的材质。
如果不加specularMap(高光贴图),整个地球会像一个塑料球一样反光。加了之后,你会发现只有海洋在反光,陆地是哑光的,真实感瞬间提升 10 倍。 - AdditiveBlending (叠加混合):
在做大气层(atmosphere)时,我们用了一个比地球稍大的球体,并开启了AdditiveBlending。这意味着它的颜色会和背景叠加变亮,从而模拟出发光、通透的空气感,这是科幻风格的精髓。 - 粒子星空:
不要用一张星空图片做背景,那样太死板。用THREE.Points生成 2000 个随机点,让它们缓慢反向旋转,整个场景就**“活”**过来了。
🚀 进阶:如何做得更像电影级?
上面的代码只是基础版。如果你想达到大屏可视化交付的标准,还需要加入:
- 后期处理 (Post-Processing):
使用UnrealBloomPass(辉光通道),让地球边缘的蓝色光晕产生“溢出”的效果,就像电影镜头拍摄的那样。 - 着色器 (Shaders):
用 GLSL 手写 Shader,实现大气散射 (Rayleigh Scattering),这样日出日落的边缘会有真实的橙红色渐变。 - 交互控制:
引入OrbitControls,允许用户缩放、旋转查看细节。
📝 总结
Web 3D 技术并没有想象中那么难,它更多的是对**“图层、光影、材质”**的理解。
当你能用 100 行代码手搓出一个地球时,你在面试官眼里的等级,已经从“切图仔”升级到了“图形工程师”。
不要停留在 2D 的舒适区,升维打击才是王道。