引言
看见大佬制作的 小米su7(点击欣赏)的3D效果,不得不佩服,我什么时候也能做一个这样的效果呢?还得从基础做起,这篇文章来看看如何使用Three.js在网页上实现一个逼真的 3D 地球并加入互动效果。
制作思路
- 初始化 Three.js 的基本组件(场景、相机、渲染器)。
- 创建地球的几何体,并加载纹理为其赋予真实外观。
- 实现地球的自转动画。
- 添加鼠标事件监听,实现交互。
- 处理窗口大小变化的逻辑,确保兼容不同设备的视口。
引入 Three.js
首先,在 HTML 文件中引入 Three.js 库:
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/build/three.min.js"></script>
实现步骤
1. 初始化场景、相机与渲染器
创建基础组件:
let canvas, // 3d 容器
camera, // 镜头
scene, // 场景
renderer, // 渲染器
group; // 组
// 物品
let mouseX = 0, mouseY = 0; // mousemove 坐标
let windowHalfX = window.innerWidth / 2; // 球心
let windowHalfY = window.innerHeight / 2;
使用 Three.js
创建一个基础 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);
renderer = new THREE.WebGLRenderer({
canvas: canvas,
antialias: true
});
}
2. 创建地球模型
加载地球纹理,并将其映射到球体几何体上:
// 纹理加载器 这段代码添加在init()方法中
let loader = new THREE.TextureLoader(); // 简单的加载器
loader.load('地球.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 );
地球图片(为上面代码第3行中的地球.jpg
):
3. 实现窗口大小自适应
处理窗口尺寸变化,确保画布自适应:
renderer.setSize(window.innerWidth, window.innerHeight); //添加到init()方法中
4. 添加鼠标交互
实现鼠标事件监听,通过鼠标移动调整相机位置:
document.addEventListener('mousemove', onDocumentMouseMove, false);// 这行代码添加到init()方法中
function onDocumentMouseMove(event) {
mouseX = event.clientX - windowHalfX;
mouseY = event.clientY - windowHalfY;
}
5. 实现地球自转动画
通过递归的 requestAnimationFrame
实现地球的旋转动画:
function animate() {
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);
group.rotation.y -= 0.005; // 控制地球自转速度
renderer.render(scene, camera);
}
6. 完整代码
将上述代码块整合:
<!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://unpkg.com/three@0.128.0/build/three.min.js"></script>
</head>
<body>
<canvas id="webglcanvas"></canvas>
<script>
// 3d 地球
// 3D 时间就是镜头拍出的世界,导演
let canvas, // 3d 容器
camera, // 镜头
scene, // 场景
renderer, // 渲染器
group; // 组
// 物品
let mouseX = 0, mouseY = 0; // mousemove 坐标
let windowHalfX = window.innerWidth / 2; // 球心
let windowHalfY = window.innerHeight / 2;
init();
animate();
// 准备
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('地球.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);
})
}
function onDocumentMouseMove(event) {
mouseX = event.clientX - windowHalfX;
mouseY = event.clientY - windowHalfY;
}
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);
}
</script>
</body>
</html>
结语
你已经掌握了使用 Three.js 构建一个 3D 地球的基础方法,让我们在以后的学习中向 小米su7进军。