Skip to content

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 { 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

属性类型
currentAdapterPlatformAdapter?返回当前注册的平台适配器实例
useAdapter(platformAdapter: PlatformAdapter) => this注册平台适配器
patch(target: string) => this将适配器补充的 Web API 添加到 globalThis[target]
getExistAdapter() => PlatformAdapter 返回现有的平台适配器,如果你未调用 useAdapter,它会在浏览器环境下返回适配浏览器的版本
getWindowInfo()=>PlatformWindowInfoPlatformWindowInfo
useCanvas(selector: string, selectorCtx?: any)=> Promise<UseCanvasResult<EventType>>;UseCanvasResultselectorCtx 为小程序内可执行 createQuerySelector 的对象
useElement(selector: string, selectorCtx?: any)=> Promise<UseElementResult<EventType>>;UseElementResult
其他属性GlobalPatchedGlobalPatched

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

执行依赖收集/替换全局对象前缀/拷贝资源等工作。

用法

在你的 viterollup 配置文件中添加以下插件:

js
import threePlatformAdapter from '@minisheep/three-platform-adapter/plugin';

export default {
  plugins: [
    //...
    threePlatformAdapter()
    //...
  ]
}

详细配置

ts
export interface ThreePlatformAdapterPluginOptions {
  /**
   * 代理全局对象的名称前缀 如代码中使用的 URL.createObjectURL 会被编译成 THREEGlobals['URL'].createObjectURL, 以便于非全局 polyfill 工作
   * 仅会影响 node_module 内 three 相关代码,不会影响用户代码
   * @default THREEGlobals
   * */
  prefixName?: string;
  mergePrefixGlobalOptions?: Partial<PrefixGlobalPluginOptions>;
  /**
   * 是否使用被 Brotli 压缩过的 wasm 文件, 显著减少文件大小,需要平台支持
   * @default true
   * */
  useBrotli?: boolean;
  /**
   * 指定 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 'wasm'
       * */
      dracoVersion?: 'gltf' | 'standard' | 'both';
    };
    meshOptDecoder?: {
      /**
       * 是否使用 simd 版本的 meshopt_decoder, 可能有部分设备不支持
       * 微信从 8.0.25 版本支持 SIMD 特性
       * @defualt true
       * */
      useSIMD?: boolean;
    };
  };

  features?: {
    /**
     * 当创建 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 的环境变量判断
       * */
      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';

搭配 rollup-plugin-to-custom-chunk 插件使用

@minisheep/three-platform-adapter/dist/three-override/jsm/** 添加到对应匹配目录中。