跳转到内容

3D对象

相关参考:

在 Web 高级 API 里,绝大多数能力都是围绕“对象句柄”展开的。

获取对象

最常见的入口是按名称获取:

js
const obj = await api.getObject('rabbit');

如果你已经知道场景内对象名称,这是最直接的方式。

也可以一次取回所有对象:

js
const objects = await api.getAllObject();

命名建议

如果你计划在宿主页面里频繁通过 API 操作对象,建议在场景编辑中就把对象名称命名清晰。

句柄不是原生 3D 对象

getObject() 返回的不是可直接操作的 Object3D,而是一个跨 iframe 通信的对象句柄。

因此下面这种写法不成立:

js
const obj = await api.getObject('rabbit');
obj.position.x = 1; // 错误

正确方式:

js
const obj = await api.getObject('rabbit');
await api.setPosition(obj, 1, 0, 0);

基础属性

名称

js
const name = await api.getObjectName(obj);

await api.setObjectName(obj, 'rabbit-main');

显隐

js
const visible = await api.getObjectVisible(obj);

await api.setObjectVisible(obj, !visible);

渲染顺序

js
// 查看当前渲染顺序
const renderOrder = await api.getRenderOrder(obj);

// 设置当前渲染顺序
await api.setRenderOrder(obj, 10);

当你需要让某个对象更稳定地盖在其他对象前面时,这个属性会很有用。

点击禁用

js
// 查询是否禁用点击
const isDisableClick = await api.getDisableClick(obj);

// 设置为禁止点击
await api.setDisableClick(obj, true);

这会阻止对象被点击中。

变换属性

位置

js
const [x, y, z] = await api.getPosition(obj);

await api.setPosition(obj, x, y + 0.2, z);

旋转

js
const [x, y, z, order] = await api.getRotation(obj);

// 注意:值为弧度,不是角度
await api.setRotation(obj, 0, Math.PI / 2, 0, 'YXZ');

四元数

js
const [x, y, z, w] = await api.getQuaternion(obj);

await api.setQuaternion(obj, 0, 0, 0, 1);

缩放

js
const [x, y, z] = await api.getScale(obj);

await api.setScale(obj, 1.2, 1.2, 1.2);

面向某点

js
await api.lookAt(obj, 0, 0, 0);

获取尺寸

js
const [width, height, depth] = await api.getSize(obj);

尺寸来自运行时包围盒计算,更适合做布局判断、点击区域估算或动态缩放。

遍历子对象

js
const children = await api.getChildren(obj);

const mesh = await api.getChildByProperty(obj, 'name', 'rabbit-head');

这一组 API 对 glTF 模型尤其有用,因为很多模型的材质、事件等需要落到内部子节点上。

对象事件

你可以监听对象级事件,当前支持:

  • click - 被点击时触发【支持事件冒泡,因为异步因素,暂不支持阻止冒泡】

支持对象类型:所有3D类型对象。

js
const obj = await api.getObject('rabbit');

function onClick(event) {
  const { type, name, object, target } = event;
  // type - click
  // name - 被点击到的子级3d对象名称,或是自身。
  // object - 被点击到的子级3d对象句柄,或是自身。
  // target - 当前监听点击事件的对象。click事件会沿父级方向一直冒泡,直到根场景。
}

await api.on('click', onClick, obj);
  • play - 音频/视频/动画/动图等播放时触发

支持对象类型:视频、模型、动图、音频。

js
const obj = await api.getObject('rabbit');

function onPlay(event) {
  // 不同的对象类型,和不同的media play类型,支持的info不一致,详细可看不同对象类型的事件说明。
  const { type, target, ...info } = event;
}

await api.on('play', onPlay, obj);
  • pause - 音频/视频/动画/动图等暂停时触发

支持对象类型:视频、模型、动图、音频。

js
const obj = await api.getObject('rabbit');

function onPause(event) {
  // 不同的对象类型,和不同的media play类型,支持的info不一致,详细可看不同对象类型的事件说明。
  const { type, target, ...info } = event;
}

await api.on('pause', onPause, obj);
  • ended - 音频/视频/动画/动图等自然播放完毕时触发

支持对象类型:视频、模型、动图、音频。

js
const obj = await api.getObject('rabbit');

function onEnded(event) {
  // 不同的对象类型,和不同的media play类型,支持的info不一致,详细可看不同对象类型的事件说明。
  const { type, target, ...info } = event;
}

await api.on('ended', onEnded, obj);
  • replay - 视频/动画/动图等重新播放时触发

支持对象类型:视频、模型、动图、音频。

js
const obj = await api.getObject('rabbit');

function onReplay(event) {
  // 不同的对象类型,和不同的media play类型,支持的info不一致,详细可看不同对象类型的事件说明。
  const { type, target, ...info } = event;
}

await api.on('replay', onReplay, obj);
  • 以及某些对象的特殊事件,详细查看不同对象类型的事件说明

推荐模式

在实际项目里,比较稳妥的做法是:

  1. 等待 loadSceneEndsceneStart
  2. 通过 getObject()getAllObject() 拿到对象句柄
  3. 把这些句柄缓存在宿主层状态里
  4. 后续统一通过 API 改变对象状态