Skip to content

本文是波兰语原版文章的 AI 生成翻译,可能包含细微错误。

在 Vue 3 和 WebGL 中构建交互式 3D 魔方

具有网络技术的赛博朋克 3D 魔方

浏览器中的 3D 图形早已不仅是一种技术上的好奇,而是成为了构建高度交互式体验的强大工具。当我们想到网络上的 3D 时,通常首先想到的是 Three.js 库。然而,在本文中,我想介绍一种架构方法,即完全在 Vue 3 框架内构建一个交互式 3D 魔方,严重依赖于原生 WebGL 接口 API 和旋转分数的精确状态管理。

您可以在我的公共 Gitea 实例上完整地研究我最新的开源项目——rubic-cube。祝您阅读愉快!

架构与挑战

实现像魔方这样的逻辑游戏的主要问题不仅在于“绘制”空间中的立方体,还在于无冲突地管理它们在各个轴上的旋转。

为什么选择 Vue 3?

使用 Vue 3 的响应式状态(得益于 Composition API – refcomputedwatch),使我们能够优雅地将魔方本身的逻辑和数学(即27个较小立方体,或称 Cubies 的状态)与将帧投射到 <canvas> 上的渲染层分离开来。Vue 的响应式引擎在跟踪用户旋转特定面的“意图”(例如,手指划过屏幕)方面表现极其出色。

渲染循环与响应板

在一个典型的网络 3D 流程中,我们有一个 requestAnimationFrame 循环,每秒计算和重绘世界 60(或 120)次。将整个响应式的 Vue 状态投入其中将大幅扼杀较弱设备(移动端)上的性能。

我保持 60 FPS 的解决方案是限制响应性。魔方的排列表示(data model)仅在特定算法移动期间按需更新,而 WebGL 则简单地在一个纯粹的循环中将多边形投影到宇宙空间中,查询转换矩阵,并且在纯粹的绘制(渲染)期间几乎完全绕过 Vue 代理。

TIP

Vue 中对于繁重渲染投影操作的最佳优化策略是将转换矩阵作为纯 JS 对象分离,而没有 Reactivity 的开销。

数学模型 – 四元数和欧拉角

为防止著名的 Gimbal Lock(万向节死锁)问题,我们使用四元数(Quaternions)而不是欧拉角来实现各个平面的整个 3x3x3 矩阵的旋转。当我们“快速转动”右侧面时,CSS 动画实在太不可靠了。

旋转通过映射相对于中央迭代的位置而发生:

javascript
// 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> 对象上注册原生的 touchstarttouchmove 事件得到解决,从而允许分析拖拽增量向量:

vue
<template>
  <div class="cube-container">
    <canvas 
      ref="webglCanvas" 
      @touchstart="handleTouchStart"
      @touchmove="handleTouchMove"
    ></canvas>
  </div>
</template>

这套东西在触摸屏上是完全可玩的,而且延迟明显很低——几乎和原生应用程序一样好,这是现代网络标准的巨大成功。

亲自试一试!

建立在空间数学上的图形构建,会比标准地组装 REST 表单和查询,更多地锻炼工程师的思想。它开阔了针对硬件优化的眼界。

请前去查看我域上的公共仓库,以便自行下载代码并在本地运行: 👉 Gitea 7u.pl 上的 Rubic Cube 仓库

把它全部解开,并炫耀一下您的打乱算法 PR 时间吧!🚀