随着小米 SU7 的发布,不少网友发现了一个小米su7的展示网页,那是相当的酷炫:
当你体验一遍后,会看到各种炫酷的效果
包括隧道穿梭、波浪动画等,并且还有些细节也值得注意,如地面的反射效果。
原网页:gamemcu.com/su7/
那么这个网页是用哪个技术实现的呢?答案是three.js
,不论是从控制台,还是一些技术解析插件都能得知。
现在,前端开发不再局限于2D图形和静态页面。随着WebGL和JavaScript库如Three.js的发展,创建复杂且互动性高的3D内容变得更加简单。今天,我们将一起探索如何使用Three.js创建一个交互式的3D地球,并了解这个过程中涉及到的关键概念和技术。
要创建3D地球就要用下面到2D的地球图片
准备工作环境
首先,我们需要确保我们的HTML文档已经正确设置了<canvas>
标签,它将作为Three.js渲染3D内容的目标。同时,我们引入了Three.js库,这是实现3D效果的核心:
html
深色版本
<script src="https://unpkg.com/three@0.128.0/build/three.min.js"></script>
<canvas id="webglcanvas"></canvas>
创建场景、相机和渲染器
接下来,我们要初始化场景(Scene)、相机(Camera)以及渲染器(Renderer)。这些元素共同构成了3D空间的基础框架,允许我们在网页上展示3D物体。
javascript
深色版本
function init() {
canvas = document.getElementById('webglcanvas'); // 获取Canvas DOM元素
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); // 设置背景颜色为白色
renderer = new THREE.WebGLRenderer({canvas: canvas, antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight); // 设置渲染尺寸
}
init函数:初始化 3D 场景
function init() {
canvas = document.getElementById('webglcanvas'); // DOM
camera = new THREE.PerspectiveCamera(60,
window.innerWidth / window.innerHeight, 1, 2000); // 实例化 相机
// 相机离scene场景
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_2048.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 );
// 渲染器 目标是canvas
renderer = new THREE.WebGLRenderer({
canvas: canvas,
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
// renderer.render(scene, camera);
document.addEventListener('mousemove', onDocumentMouseMove, false);
})
}
- 首先,通过document.getElementById获取到页面中的元素并赋值给canvas变量,建立起 JavaScript 与 HTML 页面元素的连接,后续操作才有了具体的 “画板”。
- 接着创建PerspectiveCamera实例,参数60是视野角度,类似人眼视角范围,window.innerWidth / window.innerHeight是相机的宽高比,保证画面不变形,1和2000分别是近裁剪面和远裁剪面距离,划定可见范围。将camera.position.z = 500,把相机拉远到合适距离,能完整呈现 3D 地球全貌。
- 创建Scene实例,设置白色背景,为后续添加的 3D 对象提供干净整洁的展示环境。
- 实例化Group并添加到scene,为组织 3D 元素做准备。
- 关键的纹理加载环节,使用TextureLoader加载地球纹理图片,当图片加载成功回调函数内:
-
- 用SphereGeometry构建球体几何形状,半径200,20和20分别是经度和纬度方向的分段数,分段越多球体越圆润。
-
- 结合加载的纹理创建MeshBasicMaterial材质,将纹理映射到球体表面。
-
- 最后通过Mesh把几何形状与材质组合成 3D 地球模型,并添加到group中。
-
- 同时创建WebGLRenderer实例,关联canvas,开启抗锯齿让画面更平滑,设置渲染尺寸与窗口一致,并添加鼠标移动事件监听器,为交互埋下伏笔。
onDocumentMouseMove函数:捕捉鼠标移动
function onDocumentMouseMove(event) {
mouseX = event.clientX - windowHalfX;
mouseY = event.clientY - windowHalfY;
}
这个函数简洁明了,每次鼠标在页面移动时,它获取鼠标当前位置clientX和clientY,减去窗口中心坐标windowHalfX和windowHalfY,得到鼠标相对窗口中心的偏移量,实时更新mouseX和mouseY变量,后续用于控制相机移动实现交互。
animate和render函数:让 3D 地球动起来
function animate() {
// 递归 屏幕的刷帧率 60帧/s
requestAnimationFrame(animate)
render()
}
function render() {
camera.position.x += (mouseX - camera.position.x) * 0.05;
camera.position.y += (mouseY - camera.position.y) * 0.05;
camera.lookAt(scene.position);
// camera.lookAt(scene.position)
group.rotation.y -= 0.005;
renderer.render(scene, camera);
}
animate函数利用requestAnimationFrame以每秒 60 帧的频率递归调用自身,形成流畅的动画循环。每次循环调用render函数:
- 在render函数里,根据鼠标偏移量,以一定系数0.05缓慢调整相机位置,让相机跟随鼠标移动,仿佛我们转动头部观察地球;
- 同时让group(包含地球模型)绕 y 轴以-0.005的速度缓慢旋转,模拟地球自转;
-
最后通过renderer.render将实时更新的 3D 场景绘制到canvas上,呈现出动态逼真的 3D 地球效果。
最终效果如下
总之,WebGL和Three.js 的结合为前端开发注入了强大动力,赋予了我们创造神奇 3D 世界的能力,开启了无限可能的创意空间。无论是构建沉浸式的游戏场景、逼真的数字孪生模型,还是打造令人惊叹的可视化数据展示,它们都能胜任。希望大家都能深入探索。
看到这就点个赞吧