Babylon.js 从零开始
什么是 Babylon.js?
Babylon.js 是由微软开发并维护的一款高性能、开源的 3D 引擎,专为 Web 打造。它基于 WebGL 技术,允许开发者在浏览器中创建丰富的 3D 游戏、可视化效果和交互式体验,而无需用户安装任何插件。
其主要优势包括:
强大的渲染能力,支持复杂材质和光影效果
丰富的几何体和粒子系统
完善的物理引擎集成
良好的跨浏览器兼容性
活跃的社区和详尽的文档
与主流前端框架(React、Vue 等)良好兼容
实战
在 React 项目中使用 Babylon.js 创建一个包含基础几何体、动画和交互的 3D 场景。
环境准备
安装必要的依赖:
npm install @babylonjs/core @babylonjs/react-native核心代码解析
下面是一个完整的 React 组件,它创建了一个包含多种几何体、动画和交互的 3D 场景:
1. 基础设置与组件状态
import React, { useEffect, useRef, useState } from 'react';
import {
Engine,
Scene,
Vector3,
HemisphericLight,
MeshBuilder,
StandardMaterial,
Color3,
ArcRotateCamera,
PointLight,
SpotLight,
Animation
} from '@babylonjs/core';
function App() {
const canvasRef = useRef<HTMLCanvasElement>(null);
//Todo
}
使用
useRef获取 canvas 元素的引用,这是 Babylon.js 渲染 3D 场景的基础。
2. 初始化 Babylon 核心组件
Babylon.js 的核心是
Engine(引擎)和Scene(场景),让我们看看如何初始化它们:
useEffect(() => {
if ( !canvasRef.current) return;
// 创建引擎和场景
const engine = new Engine(canvasRef.current, true);
const scene = new Scene(engine);
// 后续代码将在这里添加
}, []);
Engine是连接 canvas 和场景的桥梁,负责处理渲染循环和低级 WebGL 操作。Scene则是所有 3D 元素的容器。
3. 添加相机
没有相机,就无法 "看到"3D 场景。这里我们使用
ArcRotateCamera,围绕目标旋转观察:
// 创建相机
const camera = new ArcRotateCamera(
"camera", // 名称
0, // 初始方位角(弧度)
Math.PI / 3, // 初始仰角(弧度)
10, // 与目标的距离
Vector3.Zero(), // 目标点坐标
scene // 所属场景
);
camera.attachControl(canvasRef.current, true);
camera.lowerRadiusLimit = 5; // 最小缩放限制
camera.upperRadiusLimit = 20; // 最大缩放限制attachControl方法让相机响应鼠标 / 触摸输入,实现旋转和缩放功能。
4. 添加光源
3D 场景中的光照至关重要,它决定了物体的视觉表现。我们添加了三种不同类型的光源:
// 环境光 - 均匀照亮所有物体
const hemisphericLight = new HemisphericLight(
"hemisphericLight",
new Vector3(0, 1, 0), // 光源方向
scene
);
hemisphericLight.intensity = 0.3;
// 点光源 - 从一点向各个方向发射光线
const pointLight = new PointLight(
"pointLight",
new Vector3(0, 5, 0), // 光源位置
scene
);
pointLight.intensity = 0.8;
pointLight.diffuse = new Color3(1, 0.8, 0.6); // 暖黄色
// 聚光灯 - 类似手电筒,有方向和锥形范围
const spotLight = new SpotLight(
"spotLight",
new Vector3(0, 10, 0), // 光源位置
new Vector3(0, -1, 0), // 光照方向
Math.PI / 3, // 锥角
2, // 衰减指数
scene
);
spotLight.intensity = 0.5;
spotLight.diffuse = new Color3(0.6, 0.8, 1); // 冷蓝色
不同类型的光源可以创造出丰富的光影效果,组合使用能让场景更有层次感。
5. 创建几何体与材质
创建基础几何体,应用材质:
// 创建地面
const ground = MeshBuilder.CreateGround("ground", {
width: 20,
height: 20
}, scene);
const groundMaterial = new StandardMaterial("groundMaterial", scene);
groundMaterial.diffuseColor = new Color3(0.2, 0.2, 0.2); // 深灰色
groundMaterial.specularColor = new Color3(0.1, 0.1, 0.1); // 弱高光
ground.material = groundMaterial;
// 创建立方体
const box = MeshBuilder.CreateBox("box", { size: 2 }, scene);
box.position = new Vector3(-3, 1, 0); // 设置位置
const boxMaterial = new StandardMaterial("boxMaterial", scene);
boxMaterial.diffuseColor = new Color3(0.8, 0.3, 0.3); // 红色
box.material = boxMaterial;
// 创建球体、圆柱体和圆环(代码类似,略)
MeshBuilder提供了多种创建基础几何体的方法,如CreateBox、CreateSphere等。StandardMaterial则用于定义物体的外观属性。
6. 添加动画
为物体添加一些动画:
// 立方体旋转动画
const boxAnimation = new Animation(
"boxAnimation",
"rotation.y", // 要动画的属性
30, // 帧率
Animation.ANIMATIONTYPE_FLOAT,
Animation.ANIMATIONLOOPMODE_CYCLE // 循环模式
);
// 定义关键帧
const keyFrames = [];
keyFrames.push({ frame: 0, value: 0 });
keyFrames.push({ frame: 120, value: 2 * Math.PI }); // 2π即360度
boxAnimation.setKeys(keyFrames);
box.animations = [boxAnimation];
// 播放动画
scene.beginAnimation(box, 0, 120, true);
// 球体弹跳动画(类似,略)
通过定义关键帧,我们可以控制物体在不同时间点的状态,Babylon.js 会自动计算中间状态,实现平滑过渡。
7. 交互功能
让我们添加点击交互,让用户可以与 3D 物体互动:
// 添加鼠标点击事件
scene.onPointerDown = function (evt) {
const pickResult = scene.pick(scene.pointerX, scene.pointerY);
if (pickResult.hit) {
const hitMesh = pickResult.pickedMesh;
if (hitMesh) {
// 随机改变颜色
const material = hitMesh.material as StandardMaterial;
if (material) {
material.diffuseColor = new Color3(
Math.random(),
Math.random(),
Math.random()
);
}
}
}
};
scene.pick方法通过射线检测,判断鼠标点击位置是否有物体。
8. 渲染循环与清理
启动渲染循环,并在组件卸载时进行清理:
// 渲染循环
engine.runRenderLoop(() => {
scene.render();
});
// 处理窗口大小变化
window.addEventListener('resize', () => {
engine.resize();
});
// 清理函数
return () => {
engine.dispose();
window.removeEventListener('resize', () => {});
};engine.runRenderLoop会不断渲染场景,确保动画和交互的流畅性。组件卸载时,engine.dispose会释放资源,避免内存泄漏。
9. 组件渲染
最后,我们需要在 JSX 中渲染 canvas 元素:
return (
<div className="App" style={{ width: '100vw', height: '100vh', overflow: 'hidden' }}>
{showAdvanced ? (
<AdvancedBabylonExample onSwitchExample={() => setShowAdvanced(false)} />
) : (
<div style={{ position: 'relative', width: '100%', height: '100%' }}>
<canvas
ref={canvasRef}
style={{
width: '100%',
height: '100%',
outline: 'none',
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'
}}
/>
{/* 悬浮切换按钮 */}
<div className="floating-switch-btn" onClick={() => setShowAdvanced(true)}>
<span>高级示例</span>
</div>
</div>
)}
</div>
);
运行效果

一个 3D 场景,包含地面和四种不同的几何体
一个可以用鼠标控制的相机(拖动旋转,滚轮缩放)
自动旋转的立方体和上下弹跳的球体
点击任何物体时,它会随机改变颜色
右上角有一个按钮,可以切换到更高级的示例