<Model>
本页记录的 API 需要 @webspatial/react-sdk 1.7.0 或更高版本。
<Model> 组件实现了 WebSpatial API 中的静态 3D 内容容器元素,这种元素兼容 Web 标准中的 <model> 元素的 API,同时对 web 标准中的能力做了增强,不仅让元素对应的 2D 面片具备了空间化 HTML 元素的能力,也让 3D 模型能在这个 2D 面片前方的空间中渲染出有真实体积的 3D 内容。
Web 标准中的 model element 原本只能让 3D 模型在这个元素的「画布」上渲染,这个画布看上去像一个洞口,3D 内容在洞口的「内部」或「后方」显示。可参考 WebKit 的文档 和 demo。
要启用这种增强,需要在 <Model> 上添加空间化 HTML 元素的标记(enable-xr):
import { Model } from "@webspatial/react-sdk";
function Example() {
return (
<Model
enable-xr
autoplay
loop
style={{ height: "200px", "--xr-depth": "100px" }}
>
<source src="/modelasset/robot.glb" type="model/gltf-binary" />
<source src="/modelasset/robot.usdz" type="model/vnd.usdz+zip" />
</Model>
);
}
回退行为
如果没有添加 enable-xr 标记,或当前运行环境中没有 WebSpatial Runtime, <Model> 组件会自动降级成 web 标准中的 <model> 元素,由浏览器引擎负责渲染(当前平台上的浏览器引擎可能还不支持这个新标准,可以用 typeof HTMLModelElement !== "undefined" 做特性检测)。
为了让回退状态下的标准 <model> 代码在暂未原生支持 model element 标准的浏览器中也能显示,可以在页面中添加 model element polyfill。
WebSpatial SDK 当前版本中,<Model> 支持以下 model element 的 API:
属性
src
要嵌入的 3D 模型的 URL。
import { Model } from "@webspatial/react-sdk";
function MyScene() {
return <Model src="/modelasset/Duck.glb" enable-xr />;
}
使用 src 时只能指定一种格式的模型文件。要为不同平台提供不同格式的模型文件,请使用子元素 <source>。如果同时使用 src 和 <source> 子元素,src 的优先级最高:运行时会先尝试加载和使用 src 提供的模型文件,只有这个资源不可用时才会继续尝试 <source> 子元素。
poster
poster 用于在 3D 模型尚不可用时提供一张占位图片。当 <Model> 作为有真实体积的 3D 内容容器渲染时,WebSpatial SDK 会在模型文件加载期间把这张图片显示在 3D 容器的 2D 背板上。在此模式下,如果不提供 poster,SDK 会显示内部默认的 loading spinner。
当 <Model> 在 2D 网页中回退为标准 <model> 元素时,WebSpatial 只会把 poster 传递给浏览器,具体的展示时机和方式由浏览器而非 SDK 决定。当前的 model element 规范草案 说明,浏览器可以在 3D 内容不可用时显示这张图片,并建议在保持宽高比的前提下将其完整放入元素内并居中显示。暂时显示成类似静态 <img> 的占位图只是可能的效果之一,不是 WebSpatial SDK 保证的行为;不同原生浏览器的实现可能不同。
import { Model } from "@webspatial/react-sdk";
function MyScene() {
return (
<Model
src="/MaterialsVariantsShoe.glb"
poster="/shoe-poster.png"
enable-xr
/>
);
}
autoplay
autoplay 会在模型文件加载完成并可渲染后,立刻自动播放模型文件内建的动画。
loop
loop 会让模型文件内建的动画在播放到结尾后自动重新开始。
loading
loading 控制模型文件什么时候开始下载。
eager是默认值,表示<Model>组件挂载后立刻开始下载模型文件。lazy表示等到<Model>进入网页视区、真正需要渲染时再开始下载。
import { Model } from "@webspatial/react-sdk";
function LongScrollPage() {
return (
<>
{/* ... a lot of content ... */}
<Model loading="lazy" src="/modelasset/cone.glb" enable-xr />
</>
);
}
子元素
<source>
<source> 元素用于为 <Model> 指定一个或多个模型资源。它是一个 void element:没有内容,也不需要结束标签。在 JSX 中请使用自闭合形式。
不同平台支持的 3D 模型格式并不完全相同,因此你可以提供多个 source,由运行时使用第一个能理解的资源。source 会按顺序尝试加载。只要有一个 source 加载成功,就会在 <Model> 上触发 onLoad 事件,并且不会继续尝试后续 source。如果所有 source 都失败,会在 <Model> 上触发 onError 事件。不会在每个单独的 <source> 元素上触发 error 事件。
<source> 支持以下属性:
src
3D 模型资源的 URL。
type
模型的 MIME media type。当前支持的类型包括 model/vnd.usdz+zip (USDZ) 和 model/gltf-binary (GLB)。
生命周期事件
onLoad
当 3D 模型成功加载,并且已经可用于显示和交互时触发。如果提供了多个 source,这个事件只会针对第一个成功加载的 source 触发。
onError
当模型加载失败时触发。如果提供了多个 source,这个事件只会在所有 source 都已尝试且全部失败后触发,不会针对每一次单独的 source 加载失败触发。
JavaScript API
下面这些 JavaScript API 可以通过指向 <Model> 元素的 React ref 访问。
currentSrc
只读字符串,返回当前已加载资源的 URL。
ready
当模型的源文件已完成加载和处理时,这个 Promise 会 resolve。 如果源文件无法被获取,或者文件无法被解析为有效的 3D 模型资源,这个 Promise 会 reject。
entityTransform
一个可读可写的 DOMMatrixReadOnly,可以表示 3D 模型和 3D 内容容器内部空间之间的关系。
在默认状态下,3D 模型会在保持原有比例的前提下,尽可能撑满 <Model> 的宽或高,因此可以通过控制 <Model> 对应的 2D 面片的尺寸来控制 3D 模型的大小。
Animation Playback API
duration
只读 double,表示模型动画未经缩放的总时长,单位为秒。如果模型没有动画,值为 0。
currentTime
可读可写的 double,表示模型动画未经缩放的播放时间,单位为秒。它会被限制在动画总时长范围内,因此对于没有动画的模型,这个值始终为 0。
playbackRate
可读可写的 double,表示动画的时间缩放比例。例如,一个动画时长为 10 秒的模型,如果 playbackRate 为 0.5,则需要 20 秒播放完成。
paused
只读 Boolean,表示模型动画当前是否处于暂停状态。
play()
尝试播放模型动画(如果模型包含动画)。返回一个 Promise,在播放成功开始后 resolve。
pause()
尝试暂停模型动画的播放。如果模型已经处于暂停状态,这个方法不会产生额外效果。