还在用DOM叠加做3D交互?这个工具让你直接在Three.js里写UI
想做一个酷炫的3D产品展示页,或者给游戏加个交互界面,结果发现在Three.js场景里加个按钮都要算半天坐标?
传统方案要么用DOM叠加在Canvas上——性能差还无法真正融入3D空间;要么纯Three.js硬写——手动创建mesh、处理点击检测、计算每个元素的位置,改个间距就得重新算一遍坐标。
今天给大家介绍一个工具——UIKit,让你用Flexbox布局3D界面,用React组件写UI交互,就像开发普通网页一样自然。
UIKit是什么?一句话说清楚
简单来说,UIKit是一个让你在Three.js里用Flexbox和React组件开发3D UI的库。
它基于三个核心技术:
- Three.js:业界标准的3D渲染引擎
- React Three Fiber:Three.js的React声明式封装
- Yoga引擎:Facebook开源的跨平台Flexbox布局引擎
由Poimandres团队维护(就是React Three Fiber生态的核心开发团队),代码质量和持续性都有保障。
传统方案 vs UIKit
| 传统方案的痛点 | UIKit的解决方式 |
|---|---|
| ❌ 手动计算坐标位置 | ✅ Flexbox自动布局 |
| ❌ DOM叠加性能差 | ✅ 真3D渲染,性能原生 |
| ❌ 事件处理复杂 | ✅ React式事件系统 |
| ❌ 响应式布局困难 | ✅ 内置断点系统(sm/md/lg) |
UIKit解决的核心问题是:把前端开发者熟悉的UI开发方式,带入3D空间。
为什么推荐给前端开发者?
Flexbox布局:用CSS思维组织3D空间
以前在Three.js里布局UI元素,要手动设置每个对象的position、rotation、scale,一堆数字很难维护。改个间距或对齐方式,就得重新计算所有坐标。
现在用UIKit,直接写:
<Container
flexDirection="row"
gap={20}
justifyContent="center"
>就像写CSS Flexbox一样,gap控制间距,justifyContent控制对齐,所有布局引擎自动计算。你的React布局经验可以直接迁移到3D场景,零学习成本。
组件化开发:预设UI库开箱即用
从零实现一个3D按钮需要什么?创建mesh、添加材质、处理点击检测、实现hover状态、加上文字渲染...至少几十行代码。
UIKit提供了预设组件:
<Button onClick={handleClick}>点击我</Button>
<Input value={text} onChange={setText} />
<Container> {/* 类似div */}开箱即用,还支持两套设计系统:
- default-kit:基于Shadcn的现代风格
- horizon-kit:Meta Horizon的VR风格
想自定义样式?所有组件都支持主题定制和材质替换。
响应式设计:3D界面也能适配屏幕
做跨平台3D应用最头疼的是什么?VR头显、PC显示器、手机屏幕尺寸差距巨大,传统方案要写三套UI逻辑。
UIKit内置断点系统:
<Container
sm={{ width: 100, flexDirection: 'column' }}
lg={{ width: 200, flexDirection: 'row' }}
>和CSS媒体查询一样的思路,一套代码多端适配。sm、md、lg、xl、2xl五个断点,覆盖从手机到大屏的所有场景。
交互状态:hover/active就像写CSS伪类
以前实现hover效果要监听射线检测事件,手动管理悬停状态,更新材质颜色...光是一个按钮的hover就要写几十行代码。
现在只需要:
<Button
backgroundColor="blue"
hover={{ backgroundColor: 'lightblue', scale: 1.1 }}
active={{ scale: 0.95 }}
>就像CSS的:hover和:active伪类,所有交互逻辑UIKit自动处理。还支持focus状态和暗色模式适配。
性能更好:UI再多也不掉帧
传统React Three Fiber应用,状态更新会触发组件重渲染,复杂UI容易掉帧。
UIKit用了一套更聪明的更新机制,属性变化时直接改Three.js对象,不走React的渲染流程。实际效果是:即使有上百个UI元素同时更新动画,也能稳定保持60fps。
5分钟上手:一个3D空间里的卡片布局
安装依赖
npm install three @react-three/fiber @react-three/uikit写一个简单的3D卡片
import { Canvas } from '@react-three/fiber'
import { Container, Text } from '@react-three/uikit'
function Card() {
return (
<Container
flexDirection="column"
padding={20}
gap={10}
backgroundColor="white"
borderRadius={8}
hover={{ scale: 1.05 }}
>
<Text fontSize={24}>Hello 3D UI</Text>
<Text fontSize={16} opacity={0.7}>
这是用Flexbox布局的3D卡片
</Text>
</Container>
)
}
export default function App() {
return (
<Canvas>
<Card />
</Canvas>
)
}代码解读
- Container:类似HTML的
div,支持Flexbox所有属性 - flexDirection/gap/padding:和CSS完全一致的API,不用记新的
- backgroundColor/borderRadius:直接用熟悉的样式属性,自动转换成3D材质
- hover={{ scale: 1.05 }}:鼠标悬停时放大5%,交互效果一行搞定
运行后你会看到一张浮动在3D空间中的卡片,可以用鼠标拖拽旋转场景查看不同角度。支持所有React Three Fiber的事件:onClick、onPointerEnter、onPointerLeave等,就像写普通React组件一样。
哪些场景适合用?
游戏UI
背包系统、技能树、血条,这些游戏UI传统方案是DOM叠加,但容易闪烁、不同步。纯Three.js手写的话,一个可拖拽的背包面板就要几百行代码。
UIKit让UI真正融入3D场景,事件系统原生支持手柄和触摸。性能上,复杂UI的帧率比DOM方案高一个数量级。
VR/AR应用
VR环境里传统DOM完全没法用。手写Three.js实现设置面板,要处理射线检测、手柄交互、凝视触发,工作量巨大。
UIKit内置了WebXR支持和交互逻辑,响应式系统能适配不同头显分辨率,一套代码多端通用。
3D产品展示
电商看货、汽车配置器需要在模型旁边放参数面板。DOM叠加的方案,UI和模型分离,很难让按钮跟随模型旋转。
UIKit的UI在Three.js场景里,可以锚定到模型任何部位。比如在车门上放个按钮,无论怎么旋转视角都能精确跟随。
写在最后
UIKit让3D UI开发回归到前端熟悉的领域。Flexbox、React组件、响应式断点,这些平时写Web用的技能,直接拿来写3D场景里的界面。
不用重新学3D坐标系和矩阵运算,用现有技能就能做出真正融入场景的3D UI。对想尝试3D开发的前端来说,这可能是最顺滑的起点。
相关链接: