看了小米su7的3D互动体验网页我直接一整个亚麻呆住了,那是相当的酷炫啊,激动的心颤抖的手我也来写个3D地球来练练手。
小米su7: gamemcu.com/su7/
1. Three.js
Three.js 是一个基于 WebGL 的 JavaScript 库,它简化了在网页上创建和展示 3D 图形的过程。WebGL(Web Graphics Library)是一个JavaScript API,用于在任何兼容的网络浏览器中渲染交互式2D和3D图形,而无需使用插件。
2. 3D地球制作
2.1 初始化设置 (init
函数)
- 创建画布:获取页面中的
<canvas>
元素作为 Three.js 渲染的目标。 - 配置相机:设置了视角、宽高比、近裁剪面和远裁剪面。
- 设定场景背景色:将场景的背景颜色设置为白色。
- 创建组:为了方便管理多个对象,可以将它们添加到一个组里,然后一起操作。
- 加载纹理并创建地球:通过
TextureLoader
加载地球的纹理图片,创建球体几何体,并用带有纹理映射的材质包裹这个几何体,形成地球模型。 - 初始化渲染器:设置抗锯齿,并根据窗口大小调整渲染器尺寸。
- 监听鼠标事件:添加了一个监听器来捕捉鼠标的移动,以实现视角随鼠标移动的功能。
function init(){
canvas = document.getElementById('webglcanvas');
camera = new THREE.PerspectiveCamera(60, // fov 视角
window.innerWidth / window.innerHeight, // aspect 宽高比
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(100,32,32); // 球的半径 宽 高
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);
document.addEventListener('mousemove',onDocumentMouseMove,false);
});
}
2.2 动画循环 (animate
函数)
动画函数是 Three.js 应用程序的核心部分,它通常包含一个递归调用的 requestAnimationFrame
,确保每帧都会更新和重新渲染场景。在这个例子中,我们让地球持续自转,并且根据鼠标的位置调整相机的角度,从而让用户感觉像是在围绕地球旋转。
function animate(){
// 屏幕的刷新 60帧/秒
group.rotation.y += 0.01; // 旋转 0.01 弧度 360度 / 60 帧
requestAnimationFrame(animate); // 递归
render();
}
2.3 渲染 (render
函数)
每次动画帧时,都会调用 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);
renderer.render(scene,camera);
}
2.4 交互(onDocumentMouseMove
函数)
onDocumentMouseMove
函数用于处理鼠标移动事件,并更新全局变量 mouseX
和 mouseY
,以便在 Three.js 场景中实现基于鼠标的交互
function onDocumentMouseMove(event){
mouseX = (event.clientX - windowHalfX);
mouseY = (event.clientY - windowHalfY);
}
3. 关键组件
- 场景 (Scene) :
scene = new THREE.Scene();
在 Three.js 中,所有的物体都必须放在一个场景内。 - 相机 (Camera) :
camera = new THREE.PerspectiveCamera(...)
定义了从哪个角度查看场景。透视相机模拟了人眼的视觉效果。 - 渲染器 (Renderer) :
renderer = new THREE.WebGLRenderer({...})
将场景与相机组合起来,在画布上显示最终图像。 - 几何体 (Geometry) 和 材质 (Material) :
geometry = new THREE.SphereGeometry(...)
和material = new THREE.MeshBasicMaterial({...})
分别定义了地球的形状和表面属性。 - 加载器 (Loader) :
loader = new THREE.TextureLoader()
用于加载外部资源,如图片或模型文件。 - 监听器 (Event Listener) :
document.addEventListener('mousemove', onDocumentMouseMove, false)
监听鼠标的移动事件,使得用户可以通过鼠标控制视角。
4. 效果展示
5. 源码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D-Earth</title>
<!-- 画地球 选择框架 加速 -->
<script src="https://cdn.bootcss.com/three.js/r83/three.min.js"></script>
</head>
<body>
<canvas id="webglcanvas"></canvas>
<script>
// 3D 地球
let canvas, // 3D 容器
camera,// 3D 相机
scene, // 3D 场景
renderer, // 3D 渲染器
group; // 组合
var mouseX=0,mouseY=0; // mousemove 坐标
let windowHalfX = window.innerWidth / 2; // 球心
let windowHalfY = window.innerHeight / 2;
init();
animate();
// 准备
function init(){
canvas = document.getElementById('webglcanvas');
camera = new THREE.PerspectiveCamera(60, // fov 视角
window.innerWidth / window.innerHeight, // aspect 宽高比
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(100,32,32); // 球的半径 宽 高
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);
document.addEventListener('mousemove',onDocumentMouseMove,false);
});
}
function onDocumentMouseMove(event){
mouseX = (event.clientX - windowHalfX);
mouseY = (event.clientY - windowHalfY);
}
function animate(){
// 屏幕的刷新 60帧/秒
group.rotation.y += 0.01; // 旋转 0.01 弧度 360度 / 60 帧
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);
renderer.render(scene,camera);
}
</script>
</body>
</html>
6. 总结
这个示例展示了如何利用 Three.js 构建一个基本但完整的 3D 场景,并通过简单的交互方式增强了用户体验。喜欢的就点个赞再走吧!