Three.js是轻量级的JavaScript 3D库,基于WebGL封装了常用的3D功能,开发者无需深入掌握WebGL底层原理就能快速搭建3D场景。实现3D图表的核心思路是将数据值映射为3D物体的尺寸、位置等属性,再结合场景、相机、渲染器完成最终展示。

基础环境准备
首先需要在项目中引入Three.js库,可以通过CDN引入:
<script src="https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.min.js"></script>
实现3D柱状图的核心步骤
1. 初始化基础场景
3D场景需要包含场景、透视相机、WebGL渲染器三个核心部分,同时添加环境光让物体可见:
// 创建场景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xf0f0f0);
// 创建透视相机 参数依次为:视角、宽高比、近裁剪面、远裁剪面
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(10, 10, 10);
camera.lookAt(0, 0, 0);
// 创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 添加环境光
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
// 添加平行光增强立体感
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight.position.set(10, 20, 10);
scene.add(directionalLight);2. 数据映射为3D柱体
假设我们有以下销售数据,需要将每个数据项映射为一个3D柱体,柱体的高度对应数据值:
// 示例数据 格式为{名称: 数值}
const chartData = [
{ name: '一月', value: 5 },
{ name: '二月', value: 8 },
{ name: '三月', value: 3 },
{ name: '四月', value: 10 },
{ name: '五月', value: 7 }
];
// 柱体参数配置
const barWidth = 1; // 柱体宽度
const barDepth = 1; // 柱体深度
const barGap = 1.5; // 柱体之间的间距
const heightScale = 1; // 高度缩放系数接下来遍历数据创建柱体并添加到场景中:
// 创建柱体材质
const barMaterial = new THREE.MeshPhongMaterial({ color: 0x4a90e2 });
chartData.forEach((item, index) => {
// 计算柱体高度
const barHeight = item.value * heightScale;
// 创建长方体几何体 参数:宽度、高度、深度
const geometry = new THREE.BoxGeometry(barWidth, barHeight, barDepth);
const bar = new THREE.Mesh(geometry, barMaterial);
// 设置柱体位置 x轴按索引和间距排列 y轴让柱体底部贴地 z轴设为0
bar.position.x = index * (barWidth + barGap) - (chartData.length - 1) * (barWidth + barGap) / 2;
bar.position.y = barHeight / 2;
bar.position.z = 0;
// 给柱体添加自定义属性 方便后续交互
bar.userData = { name: item.name, value: item.value };
scene.add(bar);
});3. 添加坐标轴辅助
为了让图表更易读,可以添加坐标轴标记:
// 创建坐标轴辅助 参数为坐标轴长度 const axesHelper = new THREE.AxesHelper(6); scene.add(axesHelper);
4. 渲染循环与交互
启动渲染循环,同时可以添加鼠标交互查看柱体信息:
// 渲染循环
function animate() {
requestAnimationFrame(animate);
// 缓慢旋转场景 增强3D观感
scene.rotation.y += 0.002;
renderer.render(scene, camera);
}
animate();
// 添加鼠标点击事件 获取点击的柱体信息
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
window.addEventListener('click', (event) => {
// 计算鼠标在归一化设备坐标中的位置
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
// 更新射线
raycaster.setFromCamera(mouse, camera);
// 检测与柱体的交叉
const intersects = raycaster.intersectObjects(scene.children);
if (intersects.length > 0) {
const target = intersects[0].object;
if (target.userData.name) {
alert(`当前选中:${target.userData.name},数值:${target.userData.value}`);
}
}
});
// 窗口大小变化时调整渲染尺寸
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});效果优化建议
- 可以给不同柱体设置不同颜色,通过数据值映射颜色深浅
- 添加柱体的悬浮高亮效果,提升交互体验
- 若数据量较大,可以使用实例化网格
THREE.InstancedMesh提升渲染性能 - 可以添加图表标题、数据标签等文字元素,使用
THREE.CSS2DRenderer实现文字的3D排版
Three.jsJavaScript3D图表WebGL修改时间:2026-06-06 07:37:28