tresjs 集成
tres.js
是一个基于vue3
和three.js
的封装库,它让你可以使用vue
组件的方式来构建 3D 场景,降低了使用three.js
的门槛,并且更适合 Vue 生态的开发者。
注意
当前版本的 tresjs
有许多需要注意的问题,详见这里。
从模板开始
建议直接使用集成好的项目模板,它包含了完整的分包优化/代码兼容性配置。
如遇下载失败,你也可以手动到 github 代码仓库根据对应分支下载模板。
npx degit minisheeep/threejs-miniprogram-template#uni-ts-tresjs my-project
npx degit minisheeep/threejs-miniprogram-template#weapp-vite-tresjs my-project
手动集成
首先安装依赖包:
pnpm i @minisheep/platform-adapter-integration/tresjs
它只导出了一个函数,用于将画布和 trejs
组件关联起来。
import type { App, RendererElement } from 'vue';
export function mountTresApp(
canvas: HTMLCanvasElement,
rootComponent: Component,
rootProps?: Record<string, unknown> | null
): App<RendererElement>
然后在 @minisheep/three-platform-adapter/plugin
的配置中添加以下内容:
import { defineConfig } from 'vite';
import threePlatformAdapter from '@minisheep/three-platform-adapter/plugin';
import vue from '@vitejs/plugin-vue';
import { templateCompilerOptions } from '@tresjs/core';
export default defineConfig({
plugins: [
//...
threePlatformAdapter({
mergePrefixGlobalOptions: {
include: [
/\/@vueuse\/(core|shared)\//,
/\/@tresjs\/(core|cientos)\//,
],
}
}),
vue({
...templateCompilerOptions,
}),
],
})
最后使用包导出的 mountTresApp
方法将你使用 tresjs
编写的场景组件挂载到画布上。
import { mountTresApp } from "@minisheep/platform-adapter-integration/tresjs";
import YourScene from 'path/to/YourScene.vue'
// ...
await adapter.useCanvas(`#canvas-id`).then(result=>{
const app = mountTresApp(result.canvas, YourScene)
// ...
});
完整的代码你可以参考此模板。
在 uni-app
中集成
因为 uni-app
构建小程序使用的 vue
是特殊处理过的版本(见 @dcloudio/uni-mp-vue),剔除了许多 @vue/runtime-core
导出的内容。
而 tresjs
是基于 createRenderer
工作的,所以在之前的配置上还需要额外的处理才能让其正常工作。
tresjs
组件存放目录
首先你需要定义一个目录,专门用于存放使用 tresjs
编写的组件。 然后将它在 uni
插件的处理中排除,使其能够访问标准的 vue
而不是 uni
处理过的版本。
需要在 vite.config.ts
中添加如下配置。
import { defineConfig } from 'vite';
import uni from '@dcloudio/vite-plugin-uni';
import threePlatformAdapter from '@minisheep/three-platform-adapter/plugin';
import vue from '@vitejs/plugin-vue';
import { templateCompilerOptions } from '@tresjs/core';
import { useStandardVuePlugin } from "@minisheep/platform-adapter-integration/tresjs/plugin";
const tresjsComponentPattern = /\/path_to_your_tresjs_component_folder\/.*.vue///
export default defineConfig({
plugins: [
//@ts-expect-error uni-plugin在 当前版本在以 esm 形式导出格式异常
uni.default({
vueOptions: {
exclude: [tresjsComponentPattern]
}
}),
vue({
include: [tresjsComponentPattern],
...templateCompilerOptions
}),
useStandardVuePlugin({
include: [
tresjsComponentPattern
]
})
],
})
模板中的配置还处理了一些兼容和分包问题,详细配置你可以参考此这里。
强制覆盖依赖版本
由于 uni-app
相关插件固定依赖了 @vue/shared
某个版本, 可能会与 @tresjs/core
依赖的 @vue/shared
版本出现不一致的情况,为避免重复导入以及出现非预期问题, 可以通过配置强制统一版本。
你需要在 package.json
增加以下内容, 具体版本号可以根据你安装的 @tresjs/core
所依赖的 vue
版本决定
{
"pnpm": {
"overrides": {
"@vue/shared": "^x.x.xx"
}
}
}
{
"overrides": {
"@vue/shared": "^3.5.13"
}
}
{
"resolutions": {
"@vue/shared": "^3.5.13"
}
}
额外处理
由于 trejs
目前的 Event System
在触摸设备上运行是有缺陷的,需要等待后续的 pull 被合并才可能会解决。
具体表现是光线投射的目标元素只会根据 pointermove
事件进行更新,所以在单一点击相关事件(click,pointer-down,pointer-up等)不能在正确的元素上触发。
你需要手动进行如下处理:
- 每次在传递
touchstart
事件之前需要手动复制并修改type
为touchmove
,然后传递一次。参考如下代码:
import { adapter } from "@minisheep/three-platform-adapter";
Page({
tresApp: null,
defaultHandler: ()=>{},
async onReady() {
const result = await adapter.useCanvas(`#tresjs_demo`, this);
this.defaultHandler = (e) => {
if (e.type === 'touchstart') {
result.eventHandler({
...e,
type: 'touchmove',
}, true, true) // 这里第三个参数需要为 true
}
result.eventHandler(e, true)
};
},
})
<view class="page-container">
<canvas
type="webgl2"
id="tresjs_demo"
bindtouchstart="defaultHandler"
bindtouchmove="defaultHandler"
bindtouchcancel="defaultHandler"
bindtouchend="defaultHandler"
bindtap="defaultHandler"
>
</canvas>
</view>
:::