<pc-model>
<pc-model> 定义从 GLB 文件实例化模型的实体。
导出、压缩、查看结构和调整的完整流程详见加载模型。
- 必须直接位于
<pc-scene>、<pc-entity>、另一模型或<pc-node>下。 - 可包含多个
<pc-node>,绑定内部节点以覆盖属性、添加组件或挂接内容。 - 可包含实体和模型子项,以及每类一个组件,规则与
<pc-entity>相同。
模型本身是实体宿主,不仅是加载器。它创建独立宿主,将 GLB 内容放在其下,因此可直接包含组件和子项:
<pc-model name="t-rex" asset="t-rex" scale="3 3 3">
<pc-anim></pc-anim>
</pc-model>
entity 是稳定宿主,从启动开始存在,asset 变化和重载后仍保留全部组件及子项。GLB 内容则单独通过 contentEntity 访问。
position、rotation 和 scale 属于宿主,即实例摆放,与资源根的原始变换组合,而不是替换。
属性
支持 <pc-entity> 全部属性及 onclick/onpointer*,另增加 asset。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
asset | 资源 ID | - | 必须引用 container 资源 |
enabled | Boolean(布尔) | "true" | 模型启用状态 |
name | String(字符串) | - | 宿主名称 |
position | Vector3 | "0 0 0" | 局部位置 X Y Z |
rotation | Vector3 | "0 0 0" | 局部角度制欧拉角 X Y Z |
scale | Vector3 | "1 1 1" | 局部缩放 X Y Z |
tags | String(字符串) | - | 逗号分隔标签 |
事件
通过 addEventListener() 或 oneventname property 监听。
| 事件 | 说明 |
|---|---|
load | 每次容器实例化完成触发,包括 asset 修改后的重建 |
error | 容器失败时触发 ErrorEvent。若查询前资源已失败,message 只报告该事实;原始引擎错误见资源 error |
两者不冒泡,可直接监听或在祖先捕获多个模型。
宿主注册为拾取目标,因此也支持实体的九个指针事件及内联处理,无需包装或 pc-node 即可使整模型可点击:
<pc-model asset="t-rex" onclick="this.setAttribute('scale', '2 2 2')"></pc-model>
没有绑定部件时,命中模型任意位置以 pc-model 为目标;有 pc-node 时则以节点为目标。均向元素树冒泡,祖先无需模型自身监听也能收到。
就绪表示当前选择已结束:成功实例化、失败或未指定 asset 均包括。id 无匹配则警告且永不就绪。宿主 entity 始终非空,不能区分成功与否,应监听 error 或检查 contentEntity:
const model = await whenReady('pc-model');
if (!model.contentEntity) {
// no asset, or the load failed
}
动画
直接在模型内放 <pc-anim>,空标签按轨道名添加全部动画并播放第一段:
<pc-model asset="robot">
<pc-anim></pc-anim>
</pc-model>
组件挂在宿主,无需包装。可添加 <pc-anim-clip> 自定义名称、速度、循环或外部来源。
可询问组件,检查导出后有哪些动画:
import { whenReady } from '@playcanvas/web-components';
const anim = await whenReady('pc-anim');
console.log(anim.clips); // ['Walk', 'Idle']
按包名导入需要 import map 配置,详见代码访问。容器无动画会警告,名称带点的轨道也会跳过并警告,因此不写代码也可查看控制台。
示例
带骨骼动画的 GLB,由内嵌 pc-anim 播放,拖动可环绕:
<pc-app>
<pc-asset src="https://cdn.jsdelivr.net/npm/[email protected]/scripts/esm/camera-controls.mjs"></pc-asset>
<pc-asset src="https://developer.playcanvas.com/assets/t-rex.glb" id="t-rex"></pc-asset>
<pc-material id="floor" diffuse="#3a3f4b"></pc-material>
<pc-scene>
<pc-entity name="camera" position="2.5 1.5 3.5">
<pc-camera clear-color="#2a2d36"></pc-camera>
<pc-script>
<pc-script-instance name="cameraControls" focus-point="0 1.2 0" pitch-range="-90 0" zoom-range="1.5 10"></pc-script-instance>
</pc-script>
</pc-entity>
<pc-entity name="light" rotation="45 30 0">
<pc-light cast-shadows normal-offset-bias="0.05" shadow-bias="0.2" shadow-distance="20" intensity="1.5"></pc-light>
</pc-entity>
<pc-entity name="ground" scale="30 30 30">
<pc-render type="plane" material="floor"></pc-render>
</pc-entity>
<pc-model name="t-rex" asset="t-rex" scale="1.5 1.5 1.5">
<pc-anim></pc-anim>
</pc-model>
</pc-scene>
</pc-app>
要修改内部节点,为各目标嵌套 <pc-node>:
<pc-model asset="car">
<!-- Hide the ground plane the GLB was exported with -->
<pc-node name="Plane" enabled="false"></pc-node>
</pc-model>
JavaScript 接口
可以通过 ModelElement API创建和操作元素。
pc-model 也适合作为模板预制体根,AR 热狗风暴据此生成投射物,详见模板复用。
两个实体
模型暴露两个实体,注意区别:
| 属性 | 含义 |
|---|---|
entity | 元素创建并代表的宿主,启动后非空,asset 改变仍稳定,组件和额外子项挂在这里 |
contentEntity | 宿主下的 GLB 实例化根,加载成功前为 null,每次重载替换 |
因此组件放到 entity,查询文件内容则从 contentEntity 开始:
const model = await whenReady('pc-model');
model.entity.anim; // the component a nested <pc-anim> added
model.contentEntity.name; // the GLB root's own name, e.g. 'Sketchfab_model'
hierarchy() 和 pc-node 查找仅限内容根,宿主不出现在打印树、path 或名称查找中。
检查层级
hierarchy() 报告真实实例化树,也是 pc-node 的匹配依据,不一定等于源文件名称。加载模型有完整案例,下面给出参考:
import { whenReady } from '@playcanvas/web-components';
const model = await whenReady('pc-model');
console.log(String(model.hierarchy()));
Car
├─ FrontAxle
│ └─ Wheel [0] (render) {defaultGlbMaterial}
├─ RearAxle
│ └─ Wheel [1] (render) {defaultGlbMaterial}
├─ Wing
└─ Wing1
每行包含节点名,有同名时带 index,括号列组件,花括号列材质。例如两个 Wheel 用 index=0 和 1 区分,Wing1 是引擎为第二个同名同级项添加后缀。
返回纯数据树根;尚未实例化、失败或元素移出文档时为 null。各节点包含:
| 属性 | 类型 | 说明 |
|---|---|---|
name | String | 实例化名称,pc-node 按它查找。无名节点生成 node_index,同名同级项会重命名 |
path | String | 模型根下的斜杠分隔路径,直接位于模型内的 pc-node 返回此路径,根路径为自身名称 |
index | Number | 全模型深度优先顺序中的同名索引。嵌套 pc-node 则仅在外层节点子树内查找、计数并报告路径 |
components | String[] | 已排序组件类型,例如 render |
materials | Object[] | Render 各网格实例按组件顺序对应的 index、name 对象,没有 Render 则为空 |
children | Object[] | 子节点 |
toString() | Function | 将当前子树打印为上述形式,String(node) 可打印任意分支 |
材质 name 是当前运行时标签,并非唯一标识。未命名为 Untitled,无材质图元用共享 defaultGlbMaterial,无导出法线会创建带 -flatShaded 后缀的副本,重复名仍重复,脚本清空分配则为 null。index 才无歧义。两者供节点材质覆盖选择,替换材质会报告其 name,建议显式设置以便识别。
树是每次调用重新计算的快照,不跟踪后续修改,改变快照也不影响场景。纯数据可 JSON.stringify,方便日志、差异比较和测试。
另请参阅
<pc-asset>:容器来源。<pc-node>:访问内部层级。<pc-anim>:播放自带动画。- 加载模型:加载和声明式调整。