react-three-fiber 集成
react-three-fiber(简称 R3F)是一个基于 React 封装 Three.js 的库,它将 Three.js 转换为 React 组件,使开发者可以用 JSX 直接声明 3D 场景,并利用 React 的状态管理、hooks 和组件系统构建复杂的 3D 应用。
从模板开始
建议直接使用集成好的项目模板,它包含了完整的分包优化/代码兼容性配置。
如遇下载失败,你也可以手动到 github 代码仓库根据对应分支下载模板。
shell
npx degit minisheeep/threejs-miniprogram-template#uni-ts-r3f my-project
shell
npx degit minisheeep/threejs-miniprogram-template#weapp-vite-r3f my-project
手动集成
安装
shell
pnpm i @minisheep/platform-adapter-integration
使用
然后在 vite
和 ts
的配置文件中添加以下内容:
ts
import { defineConfig } from 'vite';
import threePlatformAdapter from '@minisheep/three-platform-adapter/plugin';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [
//...
threePlatformAdapter(),
react(),
],
})
json5
{
"compilerOptions": {
//...
"jsx": "react"
}
}
然后使用包导出的 createRoot
方法将你使用 tresjs
编写的场景组件挂载到画布上。
jsx
import { createRoot } from "@minisheep/platform-adapter-integration/r3f";
import { YourScene } from 'path/to/YourScene.tsx'
// ...
await adapter.useCanvas(`#canvas-id`).then(result => {
createRoot(result.canvas).render(<YourScene/>);
// ...
});
相关函数声明如下。
ts
import type { ReactNode } from 'react';
export declare function createRoot(canvas: HTMLCanvasElement): {
render(reactElement: ReactNode, callback?: (() => void) | null): any;
unmount(callback?: () => void): void;
};
需要注意的是,挂载的场景组件需要满足如下要求:
- 只有一个 R3F 的
Canvas
根节点 - 禁止包含其他小程序元素
例如:
jsx
import { Canvas } from '@react-three/fiber'
export function YourFirstScene() {
return (
<Canvas>
<mesh>
<torusGeometry args={[1, 0.5, 16, 32]}/>
<meshBasicMaterial color="orange"/>
</mesh>
<ambientLight intensity={1}/>
</>
);
}
完整的代码你可以参考此模板。
在 uni-app
中使用
在 uni-app
中集成 tresjs
显得有些特别,因为 uni-app
基于 vue
生态,而 R3F
(React Three Fiber)属于 react
体系, 尽管如此,R3F
所具备的一些优势依然值得关注:
- 相较于
tres.js
,R3F
更加成熟稳定。 - 拥有更活跃的社区和丰富的使用场景示例。
但这也带来了一些挑战:
- 你需要额外引入
react
的核心依赖,这将显著增加包体积。
配置以支持 react-jsx
你仅需在 vite.config.ts
中添加以下配置,否则 uni
会拦截 jsx
的相关处理
ts
import { defineConfig } from 'vite';
import threePlatformAdapter from '@minisheep/three-platform-adapter/plugin';
import react from '@vitejs/plugin-react';
import { supportR3fInUni } from '@minisheep/platform-adapter-integration/r3f/plugin';
export default defineConfig({
plugins: [
//...
threePlatformAdapter(),
react(),
supportR3fInUni(),
],
})
⚠️注意
这个插件可能会破坏 uni
处理 jsx
的能力(仅构建小程序目标的用户不影响)。
额外处理
如果你需要使用 @react-three/drei
提供的 Text
组件,还需通过 @minisheep/troika-three-text
来强制覆盖默认的 troika-three-text
包。 该版本修复了一些兼容性问题,使其在特定环境中能够正常运行。
在 package.json
中添加如下配置:
json
{
"pnpm": {
"overrides": {
"troika-three-text": "npm:@minisheep/troika-three-text@^0.52.4"
}
}
}
json
{
"overrides": {
"troika-three-text": "npm:@minisheep/troika-three-text@^0.52.4"
}
}
json
{
"resolutions": {
"troika-three-text": "npm:@minisheep/troika-three-text@^0.52.4"
}
}
同时,还需要手动禁用该库的 worker
功能:
js
import { configureTextBuilder } from 'troika-three-text';
configureTextBuilder({
useWorker: false, // 必须禁用 worker,否则会导致运行异常
});