@minisheep/three-platform-adapter
TIP
主要包含以下三部分子包:
- 通用核心和对应平台适配包:
- @minisheep/three-platform-adapter:提供统一 API 封装
- @minisheep/three-platform-adapter/**:API 底层在不同平台的具体实现
- 插件包:
- @minisheep/three-platform-adapter/plugin: 执行依赖收集/替换全局对象前缀/拷贝资源等工作。
- 资源包:
- @minisheep/three-platform-adapter/override/jsm/**/*: 在构建时经过插件自动收集依赖,替换和输出资源到产物目录,无需手动使用。
安装
shell
pnpm i @minisheep/three-platform-adapter
shell
npm i @minisheep/three-platform-adapter
shell
yarn add @minisheep/three-platform-adapter
通用核心和对应平台适配
通用核心包对 API 做了统一封装,开发者仅需切换不同的平台适配包即可适配不同平台。
- 微信小程序: @minisheep/three-platform-adapter/wechat
- 微信小游戏: @minisheep/three-platform-adapter/wechat-game
- 更多平台后续支持。
用法
仅需在项目入口导入一次对应平台的适配器,以微信小程序为例。
js
import '@minisheep/mini-program-polyfill-core/wechat-polyfill';
import '@minisheep/three-platform-adapter/wechat';
//过时的用法⬇️
// import { adapter } from '@minisheep/three-platform-adapter';
// import { wechat } from '@minisheep/three-platform-adapter/wechat';
// 现在会在导入时 ⬆️ 时 自动帮你执行 ⬇️,以支持一些极端场景
// adapter.useAdapter(wechat).patch('THREEGlobals');
然后在后续需要画布的地方调用:
ts
import { adapter } from '@minisheep/three-platform-adapter';
await adapter.useCanvas(`#xxxx`).then(({ canvas }) => {
//....
})
在小游戏中使用你可以参照文档。
Typescript
adapter
属性 | 类型 | |
---|---|---|
getWindowInfo | ()=>PlatformWindowInfo | PlatformWindowInfo |
useCanvas | (selector: string, selectorCtx?: any)=> Promise<UseCanvasResult<EventType>>; | UseCanvasResult,selectorCtx 为小程序内可执行 createQuerySelector 的对象 |
useElement | (selector: string, selectorCtx?: any)=> Promise<UseElementResult<EventType>>; | UseElementResult |
其他属性 | GlobalPatched | 见 GlobalPatched |
⬇️ 面向开发者使用,可忽略 | ||
currentAdapter | PlatformAdapter? | 返回当前注册的平台适配器实例 |
useAdapter | (platformAdapter: PlatformAdapter) => this | 注册平台适配器 |
patch | (target: string) => this | 将适配器补充的 Web API 添加到 globalThis[target] 上 |
getExistAdapter | () => PlatformAdapter | 返回现有的平台适配器,如果你未调用 useAdapter ,它会在浏览器环境下返回适配浏览器的版本 |
PlatformWindowInfo
ts
type PlatformWindowInfo = {
innerWidth: number;
innerHeight: number;
devicePixelRatio: number;
}
UseCanvasResult
ts
export type UseCanvasResult<EventType extends TouchEventLike = TouchEventLike> = {
/** 功能不完整但可用的 HTMLCanvasElement*/
canvas: HTMLCanvasElement;
/** 与 canvas 匹配 requestAnimationFrame*/
requestAnimationFrame: typeof requestAnimationFrame;
/** 与 canvas 匹配 cancelAnimationFrame*/
cancelAnimationFrame: typeof cancelAnimationFrame;
/** 更便捷的 raq */
useFrame(animateFunc: (delta: number) => void): { cancel: () => void };
/** 通过调用此方法向元素传递事件*/
eventHandler: (event: EventType, propagation?: boolean, computeSize?: boolean) => void;
/** 根据 createQuerySelector 更新元素大小*/
recomputeSize(): Promise<void>;
};
UseElementResult
ts
export type UseElementResult<EventType extends TouchEventLike = TouchEventLike> = {
/** 功能不完整但可用的 HTMLElement*/
element: PatchedElement<{}>;
/** 通过调用此方法向元素传递事件*/
eventHandler: (event: EventType, propagation?: boolean, computeSize?: boolean) => void;
/** 根据 createQuerySelector 更新元素大小*/
recomputeSize(): Promise<void>;
};
Rollup 插件
@minisheep/three-platform-adapter/plugin
执行依赖收集/替换全局对象前缀/拷贝资源等工作。
用法
在你的 vite
或 rollup
配置文件中添加以下插件:
js
import threePlatformAdapter from '@minisheep/three-platform-adapter/plugin';
export default {
plugins: [
//...
threePlatformAdapter()
//...
]
}
详细配置
ts
export interface ThreePlatformAdapterPluginOptions {
prefixGlobal?: {
/**
* 代理全局对象的名称前缀 如代码中使用的 URL.createObjectURL 会被编译成 THREEGlobals['URL'].createObjectURL, 以便于非全局 polyfill 工作
* 仅会影响 node_module 内相关代码,不会影响用户代码
* @default `THREEGlobals`
* */
prefixName?: string;
/**
* 强制使某些全局对象的访问为 undefined
* pc小程序提供 createImageBitmap 却没有原始 Blob, 会导致 three 中使用到 createImageBitmap 的地方报错, 默认忽略
* @default ['createImageBitmap']
* */
forceUndef?: string[];
} & Omit<PrefixGlobalPluginOptions, 'prefixName' | 'forceUndef'>;
/**
* 是否解构 three-stdlib 的入口以便于代码分割
* 默认会自动根据使用情况分割,如遇失效,你也可以手动传递 three-stdlib 模块的 esm 入口地址
* @default true
* */
splitThreeStdlib?: boolean | string;
/**
* 指定 worker 和 wasm 产物输出的目录
* 注: 微信小程序如使用 worker 分包功能,需输出到同一目录, 因为 worker 分包只支持一个目录,
* */
assetsOutput?: {
/** @default workers*/
worker?: string | ((fileName: string) => string);
/** @default wasms */
wasm?: string | ((fileName: string) => string);
};
/** 部分 loader/decoder 的特殊配置*/
loaderOptions?: {
DRACOLoader?: {
/**
* 使用 DRACOLoader 时默认需要复制的 decoder 类型
* @default 'wasm'
* */
supportDecoder?: 'js' | 'wasm' | 'both';
/**
* 使用 DRACOLoader 时默认拷贝到产物的 draco 版本
* @default 'gltf'
* */
dracoVersion?: 'gltf' | 'standard' | 'both';
};
meshOptDecoder?: {
/**
* 是否使用 simd 版本的 meshopt_decoder, 可能有部分设备不支持
* 微信从 8.0.25 版本支持 SIMD 特性
* @defualt true
* */
useSIMD?: boolean;
};
};
/**
* 是否使用被 Brotli 压缩过的 wasm 文件, 显著减少文件大小,需要平台支持
* */
useBrotli?: boolean;
/** 对 three 模块进行预处理, 以改变一些行为 */
features?: {
/**
* 是否使用 three 提供的压缩版本 , 显著减少包大小占用
* @default true
* */
useMinVer?: boolean;
/**
* 当创建 WebglRenderer 的 canvas 参数为空时,指定创建的离屏画布的类型
* 在一些三方库使用了 new WebGlRenderer() 而不希望创建的画布 type 为 2d 时非常有用
* @default webgl2
* */
silentCreateCanvasType?: 'webgl2' | 'webgl' | '2d' | false;
bugPatch?: {
/**
* 是否集成微信 webgl 深度缓冲 bug 的修复补丁
* 不清除深度缓冲会导致各种各样的bug。例如 pmremGenerator 的 fromScene 黑屏截至到 2025-01-04 依然存在
* 启用后会在每次调用 WebglRenderer.render 时清除深度缓冲
* 会自动根据根据 uni-cli 的环境判断 或 platform 为 wechat | wechat-game 时启用
* */
wechatDepthBuffer?: boolean;
};
};
}
静态资源
@minisheep/three-platform-adapter/override/jsm/*
这个包包含了一些 three/examples/jsm
的小程序适配版本,以及对应的 worker
/ wasm
资源,会在编译时经过插件自动收集依赖,替换和输出资源到产物目录,无需手动使用。
例如当你使用了:
js
import { Rhino3dmLoader } from 'three/examples/jsm/loaders/3DMLoader.js';
或
js
import { Rhino3dmLoader } from 'three-stdlib';
实际上在编译时会被替换为:
js
import { Rhino3dmLoader } from '@minisheep/three-platform-adapter/override/jsm/loaders/3DMLoader.js';