元素周期表是化学的基石,118个元素蕴含着物质世界的奥秘。而在前端开发中,将这张表以动态、可交互的3D形式呈现出来,不仅是对数据可视化的挑战,更是一次技术与创意的碰撞。本文将带你逐步实现四种不同风格的元素周期表特效:2D网格表格、3D球体分布、螺旋弹簧结构、DNA双螺旋以及排队纵深矩阵。最终所有特效均使用 Three.js + CSS2DRenderer 实现,保证文字清晰且性能优良。
一、基础先行:标准2D周期表
在开始3D特效之前,一个可靠的数据源和规整的2D表格是基石。我们使用 grid 布局模拟传统周期表。
技术要点:
将118个元素按周期和族放置在7行18列的网格中(空缺位置用占位符填充)。
每个卡片包含:原子序数、符号、中文名、原子量、状态标识(气/液/固)、合成元素标记。
根据元素族类(碱金属、过渡金属等)应用不同的背景色。

核心代码示意:
// 数据存储
const elementsData = {};
function addElement(z, symbol, nameZh, mass, category, state, synthetic) { ... }
// 网格布局 (7x18)
const grid = Array(7).fill().map(() => Array(18).fill(null));
function placeElement(z, row, col) { grid[row-1][col-1] = elementsData[z]; }
// 渲染时动态创建卡片DOM
const card = createCardElement(elem);
periodicGrid.appendChild(card);这种方式生成的2D表格适配移动端和PC,是所有3D特效的数据基础。
二、3D球体:让元素环绕地球
将118个元素均匀分布在球面上,用户可通过鼠标拖拽旋转观察每个角落。

核心算法:斐波那契球体算法(Fibonacci Sphere),保证点分布均匀无极点聚集。
const radius = 5.0;
const phiGolden = Math.PI * (3 - Math.sqrt(5));
for (let i = 0; i < total; i++) {
const y = 1 - (i / (total - 1)) * 2;
const radiusAtY = Math.sqrt(1 - y*y);
const theta = i * phiGolden * 2;
const x = Math.cos(theta) * radiusAtY;
const z = Math.sin(theta) * radiusAtY;
positions.push(new THREE.Vector3(x * radius, y * radius, z * radius));
}将每个卡片包装为 CSS2DObject 并设置位置,添加 OrbitControls 后即可交互。若需要自转,只需每帧旋转包含所有卡片的 Group。
三、螺旋弹簧结构:像弹簧一样旋转
螺旋结构能清晰地展示元素的顺序(按原子序数递增),视觉上酷似弹簧或螺丝。

参数方程:
const radius = 2.2, startY = -3.5, endY = 3.5, turns = 2.2;
for (let i = 0; i < total; i++) {
const t = i / (total - 1);
const angle = t * Math.PI * 2 * turns;
const y = startY + t * (endY - startY);
const x = radius * Math.cos(angle);
const z = radius * Math.sin(angle);
positions.push(new THREE.Vector3(x, y, z));
}为了让螺旋更明显,可以添加一条半透明的 TubeGeometry 沿着路径,加强视觉引导。并且可以设置整个组绕 Y 轴自转,产生“弹簧旋转”的动感。
四、DNA双螺旋:科学感十足
DNA双螺旋结构是生命科学的象征,用来展示元素周期表别有一番风味。我们将118个元素分成两条链(各59个),相位差180度,中间用圆柱体或线条连接形成碱基对。

关键步骤:
定义螺旋线函数
getHelixPosition(t, phaseOffset)。将元素按索引交错分配到两条链上(或直接前后半切分)。
计算两条链上每个卡片的位置。
对于每一对对应高度的卡片,创建圆柱体或线条连接。
// 创建连接柱 const pA = posChainA[i]; const pB = posChainB[i]; const direction = new THREE.Vector3().subVectors(pB, pA); const length = direction.length(); const center = new THREE.Vector3().addVectors(pA, pB).multiplyScalar(0.5); const cylinder = new THREE.Mesh(new THREE.CylinderGeometry(0.08, 0.08, length, 6), material); cylinder.position.copy(center); cylinder.quaternion.setFromUnitVectors(new THREE.Vector3(0,1,0), direction.clone().normalize());
为了增强视觉效果,可以添加两条彩色光带(TubeGeometry)沿着两条螺旋线,并加入漂浮粒子。最终效果非常惊艳。
五、排队纵深矩阵:正面整齐,侧面有惊喜
这种特效模拟了“队列”的感觉:正面看去只有5行4列共20个元素,旋转到侧面才发现后面还有多层(共6层,118个元素)。适合演示“遮挡与纵深”概念。

布局计算:
设定每层5行 x 4列 = 20个元素。
层数 = ceil(118 / 20) = 6。
层间距
spacingZ设为 1.2,行间距 1.0,列间距 0.9。正面(Z轴负方向)看到的是第一层(layer=0),后面的层依次排列。
let idx = 0;
for (let layer = 0; layer < layers; layer++) {
for (let row = 0; row < rows; row++) {
for (let col = 0; col < cols; col++) {
if (idx >= total) break;
const x = (col - cols/2) * spacingX;
const y = (rows/2 - row) * spacingY;
const z = - layer * spacingZ;
targetPositions.push(new THREE.Vector3(x, y, z));
idx++;
}
}
}通用技术栈:
Three.js + CSS2DRenderer:确保文字清晰。
OrbitControls:提供拖拽、缩放交互。
Tween.js:平滑动画过渡。
通过这些实现,不仅可以做出炫酷的元素周期表,还能将任何数据集以同样的方式可视化。
本文最后更新时间 2026-05-27
文章链接地址:https://yrajsh.cn/index.php/archives/137/
本站文章除注明[转载|引用|原文]出处外,均为本站原生内容,转载前请注明出处