本文是波兰语原版文章的 AI 生成翻译,可能包含细微错误。
在 Vue 3 和 WebGL 中构建交互式 3D 魔方

浏览器中的 3D 图形早已不仅是一种技术上的好奇,而是成为了构建高度交互式体验的强大工具。当我们想到网络上的 3D 时,通常首先想到的是 Three.js 库。然而,在本文中,我想介绍一种架构方法,即完全在 Vue 3 框架内构建一个交互式 3D 魔方,严重依赖于原生 WebGL 接口 API 和旋转分数的精确状态管理。
您可以在我的公共 Gitea 实例上完整地研究我最新的开源项目——rubic-cube。祝您阅读愉快!
架构与挑战
实现像魔方这样的逻辑游戏的主要问题不仅在于“绘制”空间中的立方体,还在于无冲突地管理它们在各个轴上的旋转。
为什么选择 Vue 3?
使用 Vue 3 的响应式状态(得益于 Composition API – ref、computed、watch),使我们能够优雅地将魔方本身的逻辑和数学(即27个较小立方体,或称 Cubies 的状态)与将帧投射到 <canvas> 上的渲染层分离开来。Vue 的响应式引擎在跟踪用户旋转特定面的“意图”(例如,手指划过屏幕)方面表现极其出色。
渲染循环与响应板
在一个典型的网络 3D 流程中,我们有一个 requestAnimationFrame 循环,每秒计算和重绘世界 60(或 120)次。将整个响应式的 Vue 状态投入其中将大幅扼杀较弱设备(移动端)上的性能。
我保持 60 FPS 的解决方案是限制响应性。魔方的排列表示(data model)仅在特定算法移动期间按需更新,而 WebGL 则简单地在一个纯粹的循环中将多边形投影到宇宙空间中,查询转换矩阵,并且在纯粹的绘制(渲染)期间几乎完全绕过 Vue 代理。
TIP
Vue 中对于繁重渲染投影操作的最佳优化策略是将转换矩阵作为纯 JS 对象分离,而没有 Reactivity 的开销。
数学模型 – 四元数和欧拉角
为防止著名的 Gimbal Lock(万向节死锁)问题,我们使用四元数(Quaternions)而不是欧拉角来实现各个平面的整个 3x3x3 矩阵的旋转。当我们“快速转动”右侧面时,CSS 动画实在太不可靠了。
旋转通过映射相对于中央迭代的位置而发生:
// Vue 中列旋转算法的概略片段
function rotateSlice(axis, index, direction) {
state.isAnimating = true;
const targetAngle = direction * (Math.PI / 2); // 90 度
animateValue(0, targetAngle, 300, (currentAngle) => {
// 更新活动方块的旋转矩阵
updateActiveCubiesMatrix(axis, currentAngle);
}).then(() => {
snapToGrid();
state.isAnimating = false;
});
}由于如此,我们获得了魔方刚好每 90 度“卡入”其坚固位置的效果,同时保持了完美流畅、等距投影的旋转。
响应式和移动触摸
魔方需要三维拖拽——这里我们没有平面滚动。这通过在 <canvas> 对象上注册原生的 touchstart、touchmove 事件得到解决,从而允许分析拖拽增量向量:
<template>
<div class="cube-container">
<canvas
ref="webglCanvas"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
></canvas>
</div>
</template>这套东西在触摸屏上是完全可玩的,而且延迟明显很低——几乎和原生应用程序一样好,这是现代网络标准的巨大成功。
亲自试一试!
建立在空间数学上的图形构建,会比标准地组装 REST 表单和查询,更多地锻炼工程师的思想。它开阔了针对硬件优化的眼界。
请前去查看我域上的公共仓库,以便自行下载代码并在本地运行: 👉 Gitea 7u.pl 上的 Rubic Cube 仓库
把它全部解开,并炫耀一下您的打乱算法 PR 时间吧!🚀