tresjs 集成
tres.js是一个基于vue3和three.js的封装库,它让你可以使用vue组件的方式来构建 3D 场景,降低了使用three.js的门槛,并且更适合 Vue 生态的开发者。
注意
当前版本的 tresjs 有许多需要注意的问题,详见这里。
从模板开始
建议直接使用集成好的项目模板,它包含了完整的分包优化/代码兼容性配置。
如遇下载失败,你也可以手动到 github 代码仓库根据对应分支下载模板。
npx degit minisheeep/threejs-miniprogram-template#uni-ts-tresjs my-projectnpx 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>:::